示例#1
0
// Try to retrieve the function declaration and find the function parameter
// types which are pointers/references to a non-pointer const.
// We do not invalidate the corresponding argument regions.
static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
                       const CallOrObjCMessage &Call) {
  const Decl *CallDecl = Call.getDecl();
  if (!CallDecl)
    return;

  if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) {
    const IdentifierInfo *II = FDecl->getIdentifier();

    // List the cases, where the region should be invalidated even if the
    // argument is const.
    if (II) {
      StringRef FName = II->getName();
      //  - 'int pthread_setspecific(ptheread_key k, const void *)' stores a
      // value into thread local storage. The value can later be retrieved with
      // 'void *ptheread_getspecific(pthread_key)'. So even thought the
      // parameter is 'const void *', the region escapes through the call.
      //  - funopen - sets a buffer for future IO calls.
      //  - ObjC functions that end with "NoCopy" can free memory, of the passed
      // in buffer.
      // - Many CF containers allow objects to escape through custom
      // allocators/deallocators upon container construction.
      // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
      // be deallocated by NSMapRemove.
      // - Any call that has a callback as one of the arguments.
      if (FName == "pthread_setspecific" ||
          FName == "funopen" ||
          FName.endswith("NoCopy") ||
          (FName.startswith("NS") &&
            (FName.find("Insert") != StringRef::npos)) ||
          Call.isCFCGAllowingEscape(FName) ||
          Call.hasNonZeroCallbackArg())
        return;
    }

    for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) {
      if (FDecl && Idx < FDecl->getNumParams()) {
        if (isPointerToConst(FDecl->getParamDecl(Idx)))
          PreserveArgs.insert(Idx);
      }
    }
    return;
  }

  if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) {
    assert(MDecl->param_size() <= Call.getNumArgs());
    unsigned Idx = 0;

    if (Call.hasNonZeroCallbackArg())
      return;

    for (clang::ObjCMethodDecl::param_const_iterator
         I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) {
      if (isPointerToConst(*I))
        PreserveArgs.insert(Idx);
    }
    return;
  }
}
示例#2
0
// Try to retrieve the function declaration and find the function parameter
// types which are pointers/references to a non-pointer const.
// We will not invalidate the corresponding argument regions.
static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
                                 const CallEvent &Call) {
  unsigned Idx = 0;
  for (CallEvent::param_type_iterator I = Call.param_type_begin(),
                                      E = Call.param_type_end();
       I != E; ++I, ++Idx) {
    if (isPointerToConst(*I))
      PreserveArgs.insert(Idx);
  }
}
static const TypeVec
throwsException(const FunctionDecl *Func,
                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
  if (CallStack.count(Func))
    return TypeVec();

  if (const Stmt *Body = Func->getBody()) {
    CallStack.insert(Func);
    const TypeVec Result = throwsException(Body, TypeVec(), CallStack);
    CallStack.erase(Func);
    return Result;
  }

  TypeVec Result;
  if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
    for (const QualType Ex : FPT->exceptions()) {
      Result.push_back(Ex.getTypePtr());
    }
  }
  return Result;
}
void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
                                                const CXXRecordDecl *PB,
                                                int64_t Offset,
                                 llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
                    llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
         e = RD->bases_end(); i != e; ++i) {
    const CXXRecordDecl *Base = 
      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
#if 0
    const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
    const CXXRecordDecl *PB = L.getPrimaryBase();
    if (PB && L.getPrimaryBaseWasVirtual()
        && IndirectPrimary.count(PB)) {
      int64_t BaseOffset;
      // FIXME: calculate this.
      BaseOffset = (1<<63) | (1<<31);
      VBases.push_back(PB);
      VBaseOffsets.push_back(BaseOffset);
    }
#endif
    int64_t BaseOffset = Offset;;
    // FIXME: Calculate BaseOffset.
    if (i->isVirtual()) {
      if (Base == PB) {
        // Only lay things out once.
        if (mark.count(Base))
          continue;
        // Mark it so we don't lay it out twice.
        mark.insert(Base);
        assert (IndirectPrimary.count(Base) && "IndirectPrimary was wrong");
        VBases.push_back(Base);
        VBaseOffsets.push_back(Offset);
      } else if (IndirectPrimary.count(Base)) {
        // Someone else will eventually lay this out.
        ;
      } else {
        // Only lay things out once.
        if (mark.count(Base))
          continue;
        // Mark it so we don't lay it out twice.
        mark.insert(Base);
        LayoutVirtualBase(Base);
        BaseOffset = *(VBaseOffsets.end()-1);
      }
    }
    if (Base->getNumVBases()) {
      const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
      const CXXRecordDecl *PB = L.getPrimaryBase();
      LayoutVirtualBases(Base, PB, BaseOffset, mark, IndirectPrimary);
    }
  }
}
void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
                                                const CXXRecordDecl *RD,
                                                const CXXRecordDecl *PB,
                                                uint64_t Offset,
                                 llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
                    llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
         e = RD->bases_end(); i != e; ++i) {
    assert(!i->getType()->isDependentType() &&
           "Cannot layout class with dependent bases.");
    const CXXRecordDecl *Base =
      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
    uint64_t BaseOffset = Offset;
    if (i->isVirtual()) {
      if (Base == PB) {
        // Only lay things out once.
        if (mark.count(Base))
          continue;
        // Mark it so we don't lay it out twice.
        mark.insert(Base);
        assert (IndirectPrimary.count(Base) && "IndirectPrimary was wrong");
        VBases.push_back(std::make_pair(Base, Offset));
      } else if (IndirectPrimary.count(Base)) {
        // Someone else will eventually lay this out.
        ;
      } else {
        // Only lay things out once.
        if (mark.count(Base))
          continue;
        // Mark it so we don't lay it out twice.
        mark.insert(Base);
        LayoutVirtualBase(Base);
        BaseOffset = VBases.back().second;
      }
    } else {
      if (RD == Class)
        BaseOffset = getBaseOffset(Base);
      else {
        const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
        BaseOffset = Offset + Layout.getBaseClassOffset(Base);
      }
    }
    
    if (Base->getNumVBases()) {
      const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base);
      const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase();
      LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark, 
                         IndirectPrimary);
    }
  }
}
void ASTRecordLayoutBuilder::SelectPrimaryForBase(const CXXRecordDecl *RD,
                    llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
  const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
  const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
  const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();

  if (PrimaryBaseWasVirtual)
    IndirectPrimary.insert(PrimaryBase);

  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
       e = RD->bases_end(); i != e; ++i) {
    const CXXRecordDecl *Base = 
      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
    // Only bases with virtual bases participate in computing the
    // indirect primary virtual base classes.
    if (Base->getNumVBases())
      SelectPrimaryForBase(Base, IndirectPrimary);
  }
}
void ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
                                             const CXXRecordDecl *&FirstPrimary,
                    llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
  for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
         e = RD->bases_end(); i != e; ++i) {
    const CXXRecordDecl *Base = 
      cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
    if (!i->isVirtual()) {
      SelectPrimaryVBase(Base, FirstPrimary, IndirectPrimary);
      if (PrimaryBase)
        return;
      continue;
    }
    if (IsNearlyEmpty(Base)) {
      if (FirstPrimary==0)
        FirstPrimary = Base;
      if (!IndirectPrimary.count(Base)) {
        setPrimaryBase(Base, true);
        return;
      }
    }
  }
}