Пример #1
0
SVal StoreManager::evalDynamicCast(SVal Base, QualType DerivedType,
                                   bool &Failed) {
  Failed = false;

  loc::MemRegionVal *BaseRegVal = dyn_cast<loc::MemRegionVal>(&Base);
  if (!BaseRegVal)
    return UnknownVal();
  const MemRegion *BaseRegion = BaseRegVal->stripCasts(/*StripBases=*/false);

  // Assume the derived class is a pointer or a reference to a CXX record.
  DerivedType = DerivedType->getPointeeType();
  assert(!DerivedType.isNull());
  const CXXRecordDecl *DerivedDecl = DerivedType->getAsCXXRecordDecl();
  if (!DerivedDecl && !DerivedType->isVoidType())
    return UnknownVal();

  // Drill down the CXXBaseObject chains, which represent upcasts (casts from
  // derived to base).
  const MemRegion *SR = BaseRegion;
  while (const TypedRegion *TSR = dyn_cast_or_null<TypedRegion>(SR)) {
    QualType BaseType = TSR->getLocationType()->getPointeeType();
    assert(!BaseType.isNull());
    const CXXRecordDecl *SRDecl = BaseType->getAsCXXRecordDecl();
    if (!SRDecl)
      return UnknownVal();

    // If found the derived class, the cast succeeds.
    if (SRDecl == DerivedDecl)
      return loc::MemRegionVal(TSR);

    if (!DerivedType->isVoidType()) {
      // Static upcasts are marked as DerivedToBase casts by Sema, so this will
      // only happen when multiple or virtual inheritance is involved.
      CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
                         /*DetectVirtual=*/false);
      if (SRDecl->isDerivedFrom(DerivedDecl, Paths))
        return evalDerivedToBase(loc::MemRegionVal(TSR), Paths.front());
    }

    if (const CXXBaseObjectRegion *R = dyn_cast<CXXBaseObjectRegion>(TSR))
      // Drill down the chain to get the derived classes.
      SR = R->getSuperRegion();
    else {
      // We reached the bottom of the hierarchy.

      // If this is a cast to void*, return the region.
      if (DerivedType->isVoidType())
        return loc::MemRegionVal(TSR);

      // We did not find the derived class. We we must be casting the base to
      // derived, so the cast should fail.
      Failed = true;
      return UnknownVal();
    }
  }
  
  return UnknownVal();
}
Пример #2
0
void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T,
                                                SourceLocation Loc) {
  const char *Inherits =
      "%1 is a %0 type because it inherits from a %0 type %2";
  const char *Member = "%1 is a %0 type because member %2 is a %0 type %3";
  const char *Array = "%1 is a %0 type because it is an array of %0 type %2";
  const char *Templ =
      "%1 is a %0 type because it has a template argument %0 type %2";
  const char *Implicit = "%1 is a %0 type because %2";

  AnnotationReason Reason = directAnnotationReason(T);
  for (;;) {
    switch (Reason.Kind) {
    case RK_ArrayElement:
      Check.diag(Loc, Array, DiagnosticIDs::Note) << Pretty << T << Reason.Type;
      break;
    case RK_BaseClass: {
      const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl();
      assert(Declaration && "This type should be a C++ class");

      Check.diag(Declaration->getLocation(), Inherits, DiagnosticIDs::Note)
          << Pretty << T << Reason.Type;
      break;
    }
    case RK_Field:
      Check.diag(Reason.Field->getLocation(), Member, DiagnosticIDs::Note)
          << Pretty << T << Reason.Field << Reason.Type;
      break;
    case RK_TemplateInherited: {
      const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl();
      assert(Declaration && "This type should be a C++ class");

      Check.diag(Declaration->getLocation(), Templ, DiagnosticIDs::Note)
          << Pretty << T << Reason.Type;
      break;
    }
    case RK_Implicit: {
      const TagDecl *Declaration = T->getAsTagDecl();
      assert(Declaration && "This type should be a TagDecl");

      Check.diag(Declaration->getLocation(), Implicit, DiagnosticIDs::Note)
          << Pretty << T << Reason.ImplicitReason;
      return;
    }
    default:
      // FIXME (bug 1203263): note the original annotation.
      return;
    }

    T = Reason.Type;
    Reason = directAnnotationReason(T);
  }
}
Пример #3
0
CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
  // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this.

  // If there was a nested name specifier, it names the naming class.
  // It can't be dependent: after all, we were actually able to do the
  // lookup.
  CXXRecordDecl *Record = 0;
  if (getQualifier()) {
    const Type *T = getQualifier()->getAsType();
    assert(T && "qualifier in member expression does not name type");
    Record = T->getAsCXXRecordDecl();
    assert(Record && "qualifier in member expression does not name record");
  }
  // Otherwise the naming class must have been the base class.
  else {
    QualType BaseType = getBaseType().getNonReferenceType();
    if (isArrow()) {
      const PointerType *PT = BaseType->getAs<PointerType>();
      assert(PT && "base of arrow member access is not pointer");
      BaseType = PT->getPointeeType();
    }
    
    Record = BaseType->getAsCXXRecordDecl();
    assert(Record && "base of member expression does not name record");
  }
  
  return Record;
}
Пример #4
0
RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
  // Do we have a decl at all?
  const Decl *D = getDecl();
  if (!D)
    return RuntimeDefinition();

  // If the method is non-virtual, we know we can inline it.
  const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
  if (!MD->isVirtual())
    return AnyFunctionCall::getRuntimeDefinition();

  // Do we know the implicit 'this' object being called?
  const MemRegion *R = getCXXThisVal().getAsRegion();
  if (!R)
    return RuntimeDefinition();

  // Do we know anything about the type of 'this'?
  DynamicTypeInfo DynType = getState()->getDynamicTypeInfo(R);
  if (!DynType.isValid())
    return RuntimeDefinition();

  // Is the type a C++ class? (This is mostly a defensive check.)
  QualType RegionType = DynType.getType()->getPointeeType();
  assert(!RegionType.isNull() && "DynamicTypeInfo should always be a pointer.");

  const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl();
  if (!RD || !RD->hasDefinition())
    return RuntimeDefinition();

  // Find the decl for this method in that class.
  const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true);
  if (!Result) {
    // We might not even get the original statically-resolved method due to
    // some particularly nasty casting (e.g. casts to sister classes).
    // However, we should at least be able to search up and down our own class
    // hierarchy, and some real bugs have been caught by checking this.
    assert(!RD->isDerivedFrom(MD->getParent()) && "Couldn't find known method");
    
    // FIXME: This is checking that our DynamicTypeInfo is at least as good as
    // the static type. However, because we currently don't update
    // DynamicTypeInfo when an object is cast, we can't actually be sure the
    // DynamicTypeInfo is up to date. This assert should be re-enabled once
    // this is fixed. <rdar://problem/12287087>
    //assert(!MD->getParent()->isDerivedFrom(RD) && "Bad DynamicTypeInfo");

    return RuntimeDefinition();
  }

  // Does the decl that we found have an implementation?
  const FunctionDecl *Definition;
  if (!Result->hasBody(Definition))
    return RuntimeDefinition();

  // We found a definition. If we're not sure that this devirtualization is
  // actually what will happen at runtime, make sure to provide the region so
  // that ExprEngine can decide what to do with it.
  if (DynType.canBeASubClass())
    return RuntimeDefinition(Definition, R->StripCasts());
  return RuntimeDefinition(Definition, /*DispatchRegion=*/0);
}
/// If type represents a pointer to CXXRecordDecl,
/// and is not a typedef, return the decl name.
/// Otherwise, return the serialization of type.
static std::string getPrettyTypeName(QualType QT) {
  QualType PT = QT->getPointeeType();
  if (!PT.isNull() && !QT->getAs<TypedefType>())
    if (const auto *RD = PT->getAsCXXRecordDecl())
      return RD->getName();
  return QT.getAsString();
}
Пример #6
0
/// This matcher will match any class with the stack class assertion or an
/// array of such classes.
AST_MATCHER(QualType, stackClassAggregate) {
  QualType t = Node;
  while (const ArrayType *arrTy = t->getAsArrayTypeUnsafe())
    t = arrTy->getElementType();
  CXXRecordDecl *clazz = t->getAsCXXRecordDecl();
  return clazz && MozChecker::hasCustomAnnotation(clazz, "moz_stack_class");
}
Пример #7
0
SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
                                     bool IsVirtual) {
  const MemRegion *DerivedReg = Derived.getAsRegion();
  if (!DerivedReg)
    return Derived;

  const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl();
  if (!BaseDecl)
    BaseDecl = BaseType->getAsCXXRecordDecl();
  assert(BaseDecl && "not a C++ object?");

  if (const auto *AlreadyDerivedReg =
          dyn_cast<CXXDerivedObjectRegion>(DerivedReg)) {
    if (const auto *SR =
            dyn_cast<SymbolicRegion>(AlreadyDerivedReg->getSuperRegion()))
      if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl)
        return loc::MemRegionVal(SR);

    DerivedReg = AlreadyDerivedReg->getSuperRegion();
  }

  const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion(
      BaseDecl, cast<SubRegion>(DerivedReg), IsVirtual);

  return loc::MemRegionVal(BaseReg);
}
Пример #8
0
/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                            ConstantAddress addr) {
  CodeGenModule &CGM = CGF.CGM;

  // FIXME:  __attribute__((cleanup)) ?
  
  QualType type = D.getType();
  QualType::DestructionKind dtorKind = type.isDestructedType();

  switch (dtorKind) {
  case QualType::DK_none:
    return;

  case QualType::DK_cxx_destructor:
    break;

  case QualType::DK_objc_strong_lifetime:
  case QualType::DK_objc_weak_lifetime:
    // We don't care about releasing objects during process teardown.
    assert(!D.getTLSKind() && "should have rejected this");
    return;
  }

  llvm::Constant *function;
  llvm::Constant *argument;

  // Special-case non-array C++ destructors, if they have the right signature.
  // Under some ABIs, destructors return this instead of void, and cannot be
  // passed directly to __cxa_atexit if the target does not allow this mismatch.
  const CXXRecordDecl *Record = type->getAsCXXRecordDecl();
  bool CanRegisterDestructor =
      Record && (!CGM.getCXXABI().HasThisReturn(
                     GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||
                 CGM.getCXXABI().canCallMismatchedFunctionType());
  // If __cxa_atexit is disabled via a flag, a different helper function is
  // generated elsewhere which uses atexit instead, and it takes the destructor
  // directly.
  bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit;
  if (Record && (CanRegisterDestructor || UsingExternalHelper)) {
    assert(!Record->hasTrivialDestructor());
    CXXDestructorDecl *dtor = Record->getDestructor();

    function = CGM.getAddrOfCXXStructor(dtor, StructorType::Complete);
    argument = llvm::ConstantExpr::getBitCast(
        addr.getPointer(), CGF.getTypes().ConvertType(type)->getPointerTo());

  // Otherwise, the standard logic requires a helper function.
  } else {
    function = CodeGenFunction(CGM)
        .generateDestroyHelper(addr, type, CGF.getDestroyer(dtorKind),
                               CGF.needsEHCleanup(dtorKind), &D);
    argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
  }

  CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
}
Пример #9
0
int clang_Type_getNumTemplateArguments(CXType CT) {
  QualType T = GetQualType(CT);
  if (T.isNull())
    return -1;
  const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl();
  if (!RecordDecl)
    return -1;
  const ClassTemplateSpecializationDecl *TemplateDecl =
      dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
  if (!TemplateDecl)
    return -1;
  return TemplateDecl->getTemplateArgs().size();
}
Пример #10
0
bool
RetainSummaryManager::isKnownSmartPointer(QualType QT) {
  QT = QT.getCanonicalType();
  const auto *RD = QT->getAsCXXRecordDecl();
  if (!RD)
    return false;
  const IdentifierInfo *II = RD->getIdentifier();
  if (II && II->getName() == "smart_ptr")
    if (const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()))
      if (ND->getNameAsString() == "os")
        return true;
  return false;
}
Пример #11
0
/// A function is OSObject related if it is declared on a subclass
/// of OSObject, or any of the parameters is a subclass of an OSObject.
static bool isOSObjectRelated(const CXXMethodDecl *MD) {
  if (isOSObjectSubclass(MD->getParent()))
    return true;

  for (ParmVarDecl *Param : MD->parameters()) {
    QualType PT = Param->getType()->getPointeeType();
    if (!PT.isNull())
      if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl())
        if (isOSObjectSubclass(RD))
          return true;
  }

  return false;
}
Пример #12
0
/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                            llvm::Constant *addr) {
  CodeGenModule &CGM = CGF.CGM;

  // FIXME:  __attribute__((cleanup)) ?
  
  QualType type = D.getType();
  QualType::DestructionKind dtorKind = type.isDestructedType();

  switch (dtorKind) {
  case QualType::DK_none:
    return;

  case QualType::DK_cxx_destructor:
    break;

  case QualType::DK_objc_strong_lifetime:
  case QualType::DK_objc_weak_lifetime:
    // We don't care about releasing objects during process teardown.
    assert(!D.getTLSKind() && "should have rejected this");
    return;
  }

  llvm::Constant *function;
  llvm::Constant *argument;

  // Special-case non-array C++ destructors, where there's a function
  // with the right signature that we can just call.
  const CXXRecordDecl *record = nullptr;
  if (dtorKind == QualType::DK_cxx_destructor &&
      (record = type->getAsCXXRecordDecl())) {
    assert(!record->hasTrivialDestructor());
    CXXDestructorDecl *dtor = record->getDestructor();

    function = CGM.getAddrOfCXXStructor(dtor, StructorType::Complete);
    argument = llvm::ConstantExpr::getBitCast(
        addr, CGF.getTypes().ConvertType(type)->getPointerTo());

  // Otherwise, the standard logic requires a helper function.
  } else {
    function = CodeGenFunction(CGM)
        .generateDestroyHelper(addr, type, CGF.getDestroyer(dtorKind),
                               CGF.needsEHCleanup(dtorKind), &D);
    argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
  }

  if(CGM.getTarget().isByteAddressable())
    CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
}
Пример #13
0
void ExprEngine::VisitCXXDestructor(QualType ObjectType,
                                    const MemRegion *Dest,
                                    const Stmt *S,
                                    bool IsBaseDtor,
                                    ExplodedNode *Pred,
                                    ExplodedNodeSet &Dst,
                                    const EvalCallOptions &CallOpts) {
  assert(S && "A destructor without a trigger!");
  const LocationContext *LCtx = Pred->getLocationContext();
  ProgramStateRef State = Pred->getState();

  const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
  assert(RecordDecl && "Only CXXRecordDecls should have destructors");
  const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();

  // FIXME: There should always be a Decl, otherwise the destructor call
  // shouldn't have been added to the CFG in the first place.
  if (!DtorDecl) {
    // Skip the invalid destructor. We cannot simply return because
    // it would interrupt the analysis instead.
    static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");
    // FIXME: PostImplicitCall with a null decl may crash elsewhere anyway.
    PostImplicitCall PP(/*Decl=*/nullptr, S->getEndLoc(), LCtx, &T);
    NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
    Bldr.generateNode(PP, Pred->getState(), Pred);
    return;
  }

  CallEventManager &CEMgr = getStateManager().getCallEventManager();
  CallEventRef<CXXDestructorCall> Call =
    CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx);

  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                Call->getSourceRange().getBegin(),
                                "Error evaluating destructor");

  ExplodedNodeSet DstPreCall;
  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
                                            *Call, *this);

  ExplodedNodeSet DstInvalidated;
  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
       I != E; ++I)
    defaultEvalCall(Bldr, *I, *Call, CallOpts);

  getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
                                             *Call, *this);
}
Пример #14
0
SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) {
  loc::MemRegionVal *DerivedRegVal = dyn_cast<loc::MemRegionVal>(&Derived);
  if (!DerivedRegVal)
    return Derived;

  const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl();
  if (!BaseDecl)
    BaseDecl = BaseType->getAsCXXRecordDecl();
  assert(BaseDecl && "not a C++ object?");

  const MemRegion *BaseReg =
    MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion());

  return loc::MemRegionVal(BaseReg);
}
Пример #15
0
static Optional<ArrayRef<TemplateArgument>>
GetTemplateArguments(QualType Type) {
  assert(!Type.isNull());
  if (const auto *Specialization = Type->getAs<TemplateSpecializationType>())
    return Specialization->template_arguments();

  if (const auto *RecordDecl = Type->getAsCXXRecordDecl()) {
    const auto *TemplateDecl =
      dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
    if (TemplateDecl)
      return TemplateDecl->getTemplateArgs().asArray();
  }

  return None;
}
Пример #16
0
/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                            llvm::Constant *addr) {
  CodeGenModule &CGM = CGF.CGM;

  // FIXME:  __attribute__((cleanup)) ?
  
  QualType type = D.getType();
  QualType::DestructionKind dtorKind = type.isDestructedType();

  switch (dtorKind) {
  case QualType::DK_none:
    return;

  case QualType::DK_cxx_destructor:
    break;

  case QualType::DK_objc_strong_lifetime:
  case QualType::DK_objc_weak_lifetime:
    // We don't care about releasing objects during process teardown.
    return;
  }

  llvm::Constant *function;
  llvm::Constant *argument;

  // Special-case non-array C++ destructors, where there's a function
  // with the right signature that we can just call.
  const CXXRecordDecl *record = 0;
  if (dtorKind == QualType::DK_cxx_destructor &&
      (record = type->getAsCXXRecordDecl())) {
    assert(!record->hasTrivialDestructor());
    CXXDestructorDecl *dtor = record->getDestructor();

    function = CGM.GetAddrOfCXXDestructor(dtor, Dtor_Complete);
    argument = addr;

  // Otherwise, the standard logic requires a helper function.
  } else {
    function = CodeGenFunction(CGM).generateDestroyHelper(addr, type,
                                                  CGF.getDestroyer(dtorKind),
                                                  CGF.needsEHCleanup(dtorKind));
    argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
  }

  CGF.EmitCXXGlobalDtorRegistration(function, argument);
}
Пример #17
0
void ExprEngine::VisitCXXDestructor(QualType ObjectType,
                                    const MemRegion *Dest,
                                    const Stmt *S,
                                    bool IsBaseDtor,
                                    ExplodedNode *Pred, 
                                    ExplodedNodeSet &Dst) {
  const LocationContext *LCtx = Pred->getLocationContext();
  ProgramStateRef State = Pred->getState();

  // FIXME: We need to run the same destructor on every element of the array.
  // This workaround will just run the first destructor (which will still
  // invalidate the entire array).
  // This is a loop because of multidimensional arrays.
  while (const ArrayType *AT = getContext().getAsArrayType(ObjectType)) {
    ObjectType = AT->getElementType();
    Dest = State->getLValue(ObjectType, getSValBuilder().makeZeroArrayIndex(),
                            loc::MemRegionVal(Dest)).getAsRegion();
  }

  const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
  assert(RecordDecl && "Only CXXRecordDecls should have destructors");
  const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();

  CallEventManager &CEMgr = getStateManager().getCallEventManager();
  CallEventRef<CXXDestructorCall> Call =
    CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx);

  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                Call->getSourceRange().getBegin(),
                                "Error evaluating destructor");

  ExplodedNodeSet DstPreCall;
  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
                                            *Call, *this);

  ExplodedNodeSet DstInvalidated;
  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
       I != E; ++I)
    defaultEvalCall(Bldr, *I, *Call);

  ExplodedNodeSet DstPostCall;
  getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
                                             *Call, *this);
}
Пример #18
0
SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
                                     bool IsVirtual) {
  Optional<loc::MemRegionVal> DerivedRegVal =
      Derived.getAs<loc::MemRegionVal>();
  if (!DerivedRegVal)
    return Derived;

  const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl();
  if (!BaseDecl)
    BaseDecl = BaseType->getAsCXXRecordDecl();
  assert(BaseDecl && "not a C++ object?");

  const MemRegion *BaseReg =
    MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(),
                                 IsVirtual);

  return loc::MemRegionVal(BaseReg);
}
void MoveConstructorInitCheck::handleMoveConstructor(
    const MatchFinder::MatchResult &Result) {
  const auto *CopyCtor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
  const auto *Initializer = Result.Nodes.getNodeAs<CXXCtorInitializer>("move-init");

  // Do not diagnose if the expression used to perform the initialization is a
  // trivially-copyable type.
  QualType QT = Initializer->getInit()->getType();
  if (QT.isTriviallyCopyableType(*Result.Context))
    return;

  const auto *RD = QT->getAsCXXRecordDecl();
  if (RD && RD->isTriviallyCopyable())
    return;

  // Diagnose when the class type has a move constructor available, but the
  // ctor-initializer uses the copy constructor instead.
  const CXXConstructorDecl *Candidate = nullptr;
  for (const auto *Ctor : CopyCtor->getParent()->ctors()) {
    if (Ctor->isMoveConstructor() && Ctor->getAccess() <= AS_protected &&
        !Ctor->isDeleted()) {
      // The type has a move constructor that is at least accessible to the
      // initializer.
      //
      // FIXME: Determine whether the move constructor is a viable candidate
      // for the ctor-initializer, perhaps provide a fixit that suggests
      // using std::move().
      Candidate = Ctor;
      break;
    }
  }

  if (Candidate) {
    // There's a move constructor candidate that the caller probably intended
    // to call instead.
    diag(Initializer->getSourceLocation(),
         "move constructor initializes %0 by calling a copy constructor")
        << (Initializer->isBaseInitializer() ? "base class" : "class member");
    diag(CopyCtor->getLocation(), "copy constructor being called",
         DiagnosticIDs::Note);
    diag(Candidate->getLocation(), "candidate move constructor here",
         DiagnosticIDs::Note);
  }
}
Пример #20
0
CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) {
  QualType T = GetQualType(CT);
  if (T.isNull())
    return MakeCXType(QualType(), GetTU(CT));
  const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl();
  if (!RecordDecl)
    return MakeCXType(QualType(), GetTU(CT));
  const ClassTemplateSpecializationDecl *TemplateDecl =
      dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
  if (!TemplateDecl)
    return MakeCXType(QualType(), GetTU(CT));
  const TemplateArgumentList &TA = TemplateDecl->getTemplateArgs();
  if (TA.size() <= i)
    return MakeCXType(QualType(), GetTU(CT));
  const TemplateArgument &A = TA.get(i);
  if (A.getKind() != TemplateArgument::Type)
    return MakeCXType(QualType(), GetTU(CT));
  return MakeCXType(A.getAsType(), GetTU(CT));
}
Пример #21
0
static bool regionMatchesCXXRecordType(SVal V, QualType Ty) {
  const MemRegion *MR = V.getAsRegion();
  if (!MR)
    return true;

  const auto *TVR = dyn_cast<TypedValueRegion>(MR);
  if (!TVR)
    return true;

  const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl();
  if (!RD)
    return true;

  const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl();
  if (!Expected)
    Expected = Ty->getAsCXXRecordDecl();

  return Expected->getCanonicalDecl() == RD->getCanonicalDecl();
}
RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
  // Do we have a decl at all?
  const Decl *D = getDecl();
  if (!D)
    return RuntimeDefinition();

  // If the method is non-virtual, we know we can inline it.
  const CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
  if (!MD->isVirtual())
    return AnyFunctionCall::getRuntimeDefinition();

  // Do we know the implicit 'this' object being called?
  const MemRegion *R = getCXXThisVal().getAsRegion();
  if (!R)
    return RuntimeDefinition();

  // Do we know anything about the type of 'this'?
  DynamicTypeInfo DynType = getState()->getDynamicTypeInfo(R);
  if (!DynType.isValid())
    return RuntimeDefinition();

  // Is the type a C++ class? (This is mostly a defensive check.)
  QualType RegionType = DynType.getType()->getPointeeType();
  const CXXRecordDecl *RD = RegionType->getAsCXXRecordDecl();
  if (!RD || !RD->hasDefinition())
    return RuntimeDefinition();

  // Find the decl for this method in that class.
  const CXXMethodDecl *Result = MD->getCorrespondingMethodInClass(RD, true);
  assert(Result && "At the very least the static decl should show up.");

  // Does the decl that we found have an implementation?
  const FunctionDecl *Definition;
  if (!Result->hasBody(Definition))
    return RuntimeDefinition();

  // We found a definition. If we're not sure that this devirtualization is
  // actually what will happen at runtime, make sure to provide the region so
  // that ExprEngine can decide what to do with it.
  if (DynType.canBeASubClass())
    return RuntimeDefinition(Definition, R->StripCasts());
  return RuntimeDefinition(Definition, /*DispatchRegion=*/0);
}
Пример #23
0
/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                            ConstantAddress Addr) {
  // Honor __attribute__((no_destroy)) and bail instead of attempting
  // to emit a reference to a possibly nonexistent destructor, which
  // in turn can cause a crash. This will result in a global constructor
  // that isn't balanced out by a destructor call as intended by the
  // attribute. This also checks for -fno-c++-static-destructors and
  // bails even if the attribute is not present.
  if (D.isNoDestroy(CGF.getContext()))
    return;
  
  CodeGenModule &CGM = CGF.CGM;

  // FIXME:  __attribute__((cleanup)) ?

  QualType Type = D.getType();
  QualType::DestructionKind DtorKind = Type.isDestructedType();

  switch (DtorKind) {
  case QualType::DK_none:
    return;

  case QualType::DK_cxx_destructor:
    break;

  case QualType::DK_objc_strong_lifetime:
  case QualType::DK_objc_weak_lifetime:
  case QualType::DK_nontrivial_c_struct:
    // We don't care about releasing objects during process teardown.
    assert(!D.getTLSKind() && "should have rejected this");
    return;
  }

  llvm::FunctionCallee Func;
  llvm::Constant *Argument;

  // Special-case non-array C++ destructors, if they have the right signature.
  // Under some ABIs, destructors return this instead of void, and cannot be
  // passed directly to __cxa_atexit if the target does not allow this
  // mismatch.
  const CXXRecordDecl *Record = Type->getAsCXXRecordDecl();
  bool CanRegisterDestructor =
      Record && (!CGM.getCXXABI().HasThisReturn(
                     GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||
                 CGM.getCXXABI().canCallMismatchedFunctionType());
  // If __cxa_atexit is disabled via a flag, a different helper function is
  // generated elsewhere which uses atexit instead, and it takes the destructor
  // directly.
  bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit;
  if (Record && (CanRegisterDestructor || UsingExternalHelper)) {
    assert(!Record->hasTrivialDestructor());
    CXXDestructorDecl *Dtor = Record->getDestructor();

    Func = CGM.getAddrAndTypeOfCXXStructor(Dtor, StructorType::Complete);
    Argument = llvm::ConstantExpr::getBitCast(
        Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo());

  // Otherwise, the standard logic requires a helper function.
  } else {
    Func = CodeGenFunction(CGM)
           .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind),
                                  CGF.needsEHCleanup(DtorKind), &D);
    Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
  }

  CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument);
}
Пример #24
0
RegionOffset MemRegion::getAsOffset() const {
  const MemRegion *R = this;
  const MemRegion *SymbolicOffsetBase = 0;
  int64_t Offset = 0;

  while (1) {
    switch (R->getKind()) {
    default:
      return RegionOffset(R, RegionOffset::Symbolic);

    case SymbolicRegionKind:
    case AllocaRegionKind:
    case CompoundLiteralRegionKind:
    case CXXThisRegionKind:
    case StringRegionKind:
    case VarRegionKind:
    case CXXTempObjectRegionKind:
      goto Finish;

    case ObjCIvarRegionKind:
      // This is a little strange, but it's a compromise between
      // ObjCIvarRegions having unknown compile-time offsets (when using the
      // non-fragile runtime) and yet still being distinct, non-overlapping
      // regions. Thus we treat them as "like" base regions for the purposes
      // of computing offsets.
      goto Finish;

    case CXXBaseObjectRegionKind: {
      const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R);
      R = BOR->getSuperRegion();

      QualType Ty;
      if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R)) {
        Ty = TVR->getDesugaredValueType(getContext());
      } else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
        // If our base region is symbolic, we don't know what type it really is.
        // Pretend the type of the symbol is the true dynamic type.
        // (This will at least be self-consistent for the life of the symbol.)
        Ty = SR->getSymbol()->getType()->getPointeeType();
      }
      
      const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
      if (!Child) {
        // We cannot compute the offset of the base class.
        SymbolicOffsetBase = R;
      }

      // Don't bother calculating precise offsets if we already have a
      // symbolic offset somewhere in the chain.
      if (SymbolicOffsetBase)
        continue;

      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);

      CharUnits BaseOffset;
      const CXXRecordDecl *Base = BOR->getDecl();
      if (Child->isVirtuallyDerivedFrom(Base))
        BaseOffset = Layout.getVBaseClassOffset(Base);
      else
        BaseOffset = Layout.getBaseClassOffset(Base);

      // The base offset is in chars, not in bits.
      Offset += BaseOffset.getQuantity() * getContext().getCharWidth();
      break;
    }
    case ElementRegionKind: {
      const ElementRegion *ER = cast<ElementRegion>(R);
      R = ER->getSuperRegion();

      QualType EleTy = ER->getValueType();
      if (!IsCompleteType(getContext(), EleTy)) {
        // We cannot compute the offset of the base class.
        SymbolicOffsetBase = R;
        continue;
      }

      SVal Index = ER->getIndex();
      if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
        // Don't bother calculating precise offsets if we already have a
        // symbolic offset somewhere in the chain. 
        if (SymbolicOffsetBase)
          continue;

        int64_t i = CI->getValue().getSExtValue();
        // This type size is in bits.
        Offset += i * getContext().getTypeSize(EleTy);
      } else {
        // We cannot compute offset for non-concrete index.
        SymbolicOffsetBase = R;
      }
      break;
    }
    case FieldRegionKind: {
      const FieldRegion *FR = cast<FieldRegion>(R);
      R = FR->getSuperRegion();

      const RecordDecl *RD = FR->getDecl()->getParent();
      if (RD->isUnion() || !RD->isCompleteDefinition()) {
        // We cannot compute offset for incomplete type.
        // For unions, we could treat everything as offset 0, but we'd rather
        // treat each field as a symbolic offset so they aren't stored on top
        // of each other, since we depend on things in typed regions actually
        // matching their types.
        SymbolicOffsetBase = R;
      }

      // Don't bother calculating precise offsets if we already have a
      // symbolic offset somewhere in the chain.
      if (SymbolicOffsetBase)
        continue;

      // Get the field number.
      unsigned idx = 0;
      for (RecordDecl::field_iterator FI = RD->field_begin(), 
             FE = RD->field_end(); FI != FE; ++FI, ++idx)
        if (FR->getDecl() == *FI)
          break;

      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
      // This is offset in bits.
      Offset += Layout.getFieldOffset(idx);
      break;
    }
    }
  }

 Finish:
  if (SymbolicOffsetBase)
    return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
  return RegionOffset(R, Offset);
}
Пример #25
0
/// Create a fake body for std::call_once.
/// Emulates the following function body:
///
/// \code
/// typedef struct once_flag_s {
///   unsigned long __state = 0;
/// } once_flag;
/// template<class Callable>
/// void call_once(once_flag& o, Callable func) {
///   if (!o.__state) {
///     func();
///   }
///   o.__state = 1;
/// }
/// \endcode
static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
  DEBUG(llvm::dbgs() << "Generating body for call_once\n");

  // We need at least two parameters.
  if (D->param_size() < 2)
    return nullptr;

  ASTMaker M(C);

  const ParmVarDecl *Flag = D->getParamDecl(0);
  const ParmVarDecl *Callback = D->getParamDecl(1);

  if (!Callback->getType()->isReferenceType()) {
    llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
    return nullptr;
  }
  if (!Flag->getType()->isReferenceType()) {
    llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
    return nullptr;
  }

  QualType CallbackType = Callback->getType().getNonReferenceType();

  // Nullable pointer, non-null iff function is a CXXRecordDecl.
  CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl();
  QualType FlagType = Flag->getType().getNonReferenceType();
  auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl());

  if (!FlagRecordDecl) {
    DEBUG(llvm::dbgs() << "Flag field is not a record: "
                       << "unknown std::call_once implementation, "
                       << "ignoring the call.\n");
    return nullptr;
  }

  // We initially assume libc++ implementation of call_once,
  // where the once_flag struct has a field `__state_`.
  ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_");

  // Otherwise, try libstdc++ implementation, with a field
  // `_M_once`
  if (!FlagFieldDecl) {
    FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
  }

  if (!FlagFieldDecl) {
    DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
                       << "std::once_flag struct: unknown std::call_once "
                       << "implementation, ignoring the call.");
    return nullptr;
  }

  bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda();
  if (CallbackRecordDecl && !isLambdaCall) {
    DEBUG(llvm::dbgs() << "Not supported: synthesizing body for functors when "
                       << "body farming std::call_once, ignoring the call.");
    return nullptr;
  }

  SmallVector<Expr *, 5> CallArgs;
  const FunctionProtoType *CallbackFunctionType;
  if (isLambdaCall) {

    // Lambda requires callback itself inserted as a first parameter.
    CallArgs.push_back(
        M.makeDeclRefExpr(Callback,
                          /* RefersToEnclosingVariableOrCapture=*/ true));
    CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
                               ->getType()
                               ->getAs<FunctionProtoType>();
  } else if (!CallbackType->getPointeeType().isNull()) {
    CallbackFunctionType =
        CallbackType->getPointeeType()->getAs<FunctionProtoType>();
  } else {
    CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
  }

  if (!CallbackFunctionType)
    return nullptr;

  // First two arguments are used for the flag and for the callback.
  if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
    DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
                       << "params passed to std::call_once, "
                       << "ignoring the call\n");
    return nullptr;
  }

  // All arguments past first two ones are passed to the callback,
  // and we turn lvalues into rvalues if the argument is not passed by
  // reference.
  for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
    const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
    Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
    if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
      QualType PTy = PDecl->getType().getNonReferenceType();
      ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy);
    }
    CallArgs.push_back(ParamExpr);
  }

  CallExpr *CallbackCall;
  if (isLambdaCall) {

    CallbackCall = create_call_once_lambda_call(C, M, Callback,
                                                CallbackRecordDecl, CallArgs);
  } else {

    // Function pointer case.
    CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
  }

  DeclRefExpr *FlagDecl =
      M.makeDeclRefExpr(Flag,
                        /* RefersToEnclosingVariableOrCapture=*/true);


  MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl);
  assert(Deref->isLValue());
  QualType DerefType = Deref->getType();

  // Negation predicate.
  UnaryOperator *FlagCheck = new (C) UnaryOperator(
      /* input=*/
      M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
                         CK_IntegralToBoolean),
      /* opc=*/ UO_LNot,
      /* QualType=*/ C.IntTy,
      /* ExprValueKind=*/ VK_RValue,
      /* ExprObjectKind=*/ OK_Ordinary, SourceLocation());

  // Create assignment.
  BinaryOperator *FlagAssignment = M.makeAssignment(
      Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType),
      DerefType);

  IfStmt *Out = new (C)
      IfStmt(C, SourceLocation(),
             /* IsConstexpr=*/ false,
             /* init=*/ nullptr,
             /* var=*/ nullptr,
             /* cond=*/ FlagCheck,
             /* then=*/ M.makeCompound({CallbackCall, FlagAssignment}));

  return Out;
}
Пример #26
0
DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
  DSAVarData DVar;

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.1]
  //  Variables appearing in threadprivate directives are threadprivate.
  if (D->getTLSKind() != VarDecl::TLS_None) {
    DVar.CKind = OMPC_threadprivate;
    return DVar;
  }
  if (Stack[0].SharingMap.count(D)) {
    DVar.RefExpr = Stack[0].SharingMap[D].RefExpr;
    DVar.CKind = OMPC_threadprivate;
    return DVar;
  }

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.1]
  // Variables with automatic storage duration that are declared in a scope
  // inside the construct are private.
  OpenMPDirectiveKind Kind = getCurrentDirective();
  if (Kind != OMPD_parallel) {
    if (isOpenMPLocal(D, llvm::next(Stack.rbegin())) && D->isLocalVarDecl() &&
        (D->getStorageClass() == SC_Auto ||
         D->getStorageClass() == SC_None))
      DVar.CKind = OMPC_private;
      return DVar;
  }

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.4]
  //  Static data memebers are shared.
  if (D->isStaticDataMember()) {
    // Variables with const-qualified type having no mutable member may be listed
    // in a firstprivate clause, even if they are static data members.
    DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
    if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
      return DVar;

    DVar.CKind = OMPC_shared;
    return DVar;
  }

  QualType Type = D->getType().getNonReferenceType().getCanonicalType();
  bool IsConstant = Type.isConstant(Actions.getASTContext());
  while (Type->isArrayType()) {
    QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType();
    Type = ElemType.getNonReferenceType().getCanonicalType();
  }
  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.6]
  //  Variables with const qualified type having no mutable member are
  //  shared.
  CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ?
                                Type->getAsCXXRecordDecl() : 0;
  if (IsConstant &&
      !(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
    // Variables with const-qualified type having no mutable member may be
    // listed in a firstprivate clause, even if they are static data members.
    DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
    if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
      return DVar;

    DVar.CKind = OMPC_shared;
    return DVar;
  }

  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
  // in a Construct, C/C++, predetermined, p.7]
  //  Variables with static storage duration that are declared in a scope
  //  inside the construct are shared.
  if (D->isStaticLocal()) {
    DVar.CKind = OMPC_shared;
    return DVar;
  }

  // Explicitly specified attributes and local variables with predetermined
  // attributes.
  if (Stack.back().SharingMap.count(D)) {
    DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
    DVar.CKind = Stack.back().SharingMap[D].Attributes;
  }

  return DVar;
}
Пример #27
0
CustomTypeAnnotation::AnnotationReason
CustomTypeAnnotation::directAnnotationReason(QualType T) {
  if (const TagDecl *D = T->getAsTagDecl()) {
    if (hasCustomAnnotation(D, Spelling)) {
      AnnotationReason Reason = {T, RK_Direct, nullptr, ""};
      return Reason;
    }

    std::string ImplAnnotReason = getImplicitReason(D);
    if (!ImplAnnotReason.empty()) {
      AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason};
      return Reason;
    }
  }

  // Check if we have a cached answer
  void *Key = T.getAsOpaquePtr();
  ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr());
  if (Cached != Cache.end()) {
    return Cached->second;
  }

  // Check if we have a type which we can recurse into
  if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) {
    if (hasEffectiveAnnotation(Array->getElementType())) {
      AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement,
                                 nullptr, ""};
      Cache[Key] = Reason;
      return Reason;
    }
  }

  // Recurse into Base classes
  if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) {
    if (Declaration->hasDefinition()) {
      Declaration = Declaration->getDefinition();

      for (const CXXBaseSpecifier &Base : Declaration->bases()) {
        if (hasEffectiveAnnotation(Base.getType())) {
          AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr, ""};
          Cache[Key] = Reason;
          return Reason;
        }
      }

      // Recurse into members
      for (const FieldDecl *Field : Declaration->fields()) {
        if (hasEffectiveAnnotation(Field->getType())) {
          AnnotationReason Reason = {Field->getType(), RK_Field, Field, ""};
          Cache[Key] = Reason;
          return Reason;
        }
      }

      // Recurse into template arguments if the annotation
      // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
      if (hasCustomAnnotation(
              Declaration, "moz_inherit_type_annotations_from_template_args")) {
        const ClassTemplateSpecializationDecl *Spec =
            dyn_cast<ClassTemplateSpecializationDecl>(Declaration);
        if (Spec) {
          const TemplateArgumentList &Args = Spec->getTemplateArgs();

          AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray());
          if (Reason.Kind != RK_None) {
            Cache[Key] = Reason;
            return Reason;
          }
        }
      }
    }
  }

  AnnotationReason Reason = {QualType(), RK_None, nullptr, ""};
  Cache[Key] = Reason;
  return Reason;
}
Пример #28
0
RegionOffset MemRegion::getAsOffset() const {
  const MemRegion *R = this;
  const MemRegion *SymbolicOffsetBase = 0;
  int64_t Offset = 0;

  while (1) {
    switch (R->getKind()) {
    case GenericMemSpaceRegionKind:
    case StackLocalsSpaceRegionKind:
    case StackArgumentsSpaceRegionKind:
    case HeapSpaceRegionKind:
    case UnknownSpaceRegionKind:
    case StaticGlobalSpaceRegionKind:
    case GlobalInternalSpaceRegionKind:
    case GlobalSystemSpaceRegionKind:
    case GlobalImmutableSpaceRegionKind:
      // Stores can bind directly to a region space to set a default value.
      assert(Offset == 0 && !SymbolicOffsetBase);
      goto Finish;

    case FunctionTextRegionKind:
    case BlockTextRegionKind:
    case BlockDataRegionKind:
      // These will never have bindings, but may end up having values requested
      // if the user does some strange casting.
      if (Offset != 0)
        SymbolicOffsetBase = R;
      goto Finish;

    case SymbolicRegionKind:
    case AllocaRegionKind:
    case CompoundLiteralRegionKind:
    case CXXThisRegionKind:
    case StringRegionKind:
    case ObjCStringRegionKind:
    case VarRegionKind:
    case CXXTempObjectRegionKind:
      // Usual base regions.
      goto Finish;

    case ObjCIvarRegionKind:
      // This is a little strange, but it's a compromise between
      // ObjCIvarRegions having unknown compile-time offsets (when using the
      // non-fragile runtime) and yet still being distinct, non-overlapping
      // regions. Thus we treat them as "like" base regions for the purposes
      // of computing offsets.
      goto Finish;

    case CXXBaseObjectRegionKind: {
      const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R);
      R = BOR->getSuperRegion();

      QualType Ty;
      bool RootIsSymbolic = false;
      if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R)) {
        Ty = TVR->getDesugaredValueType(getContext());
      } else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
        // If our base region is symbolic, we don't know what type it really is.
        // Pretend the type of the symbol is the true dynamic type.
        // (This will at least be self-consistent for the life of the symbol.)
        Ty = SR->getSymbol()->getType()->getPointeeType();
        RootIsSymbolic = true;
      }
      
      const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
      if (!Child) {
        // We cannot compute the offset of the base class.
        SymbolicOffsetBase = R;
      }

      if (RootIsSymbolic) {
        // Base layers on symbolic regions may not be type-correct.
        // Double-check the inheritance here, and revert to a symbolic offset
        // if it's invalid (e.g. due to a reinterpret_cast).
        if (BOR->isVirtual()) {
          if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
            SymbolicOffsetBase = R;
        } else {
          if (!isImmediateBase(Child, BOR->getDecl()))
            SymbolicOffsetBase = R;
        }
      }

      // Don't bother calculating precise offsets if we already have a
      // symbolic offset somewhere in the chain.
      if (SymbolicOffsetBase)
        continue;

      CharUnits BaseOffset;
      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);
      if (BOR->isVirtual())
        BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl());
      else
        BaseOffset = Layout.getBaseClassOffset(BOR->getDecl());

      // The base offset is in chars, not in bits.
      Offset += BaseOffset.getQuantity() * getContext().getCharWidth();
      break;
    }
    case ElementRegionKind: {
      const ElementRegion *ER = cast<ElementRegion>(R);
      R = ER->getSuperRegion();

      QualType EleTy = ER->getValueType();
      if (!IsCompleteType(getContext(), EleTy)) {
        // We cannot compute the offset of the base class.
        SymbolicOffsetBase = R;
        continue;
      }

      SVal Index = ER->getIndex();
      if (Optional<nonloc::ConcreteInt> CI =
              Index.getAs<nonloc::ConcreteInt>()) {
        // Don't bother calculating precise offsets if we already have a
        // symbolic offset somewhere in the chain. 
        if (SymbolicOffsetBase)
          continue;

        int64_t i = CI->getValue().getSExtValue();
        // This type size is in bits.
        Offset += i * getContext().getTypeSize(EleTy);
      } else {
        // We cannot compute offset for non-concrete index.
        SymbolicOffsetBase = R;
      }
      break;
    }
    case FieldRegionKind: {
      const FieldRegion *FR = cast<FieldRegion>(R);
      R = FR->getSuperRegion();

      const RecordDecl *RD = FR->getDecl()->getParent();
      if (RD->isUnion() || !RD->isCompleteDefinition()) {
        // We cannot compute offset for incomplete type.
        // For unions, we could treat everything as offset 0, but we'd rather
        // treat each field as a symbolic offset so they aren't stored on top
        // of each other, since we depend on things in typed regions actually
        // matching their types.
        SymbolicOffsetBase = R;
      }

      // Don't bother calculating precise offsets if we already have a
      // symbolic offset somewhere in the chain.
      if (SymbolicOffsetBase)
        continue;

      // Get the field number.
      unsigned idx = 0;
      for (RecordDecl::field_iterator FI = RD->field_begin(), 
             FE = RD->field_end(); FI != FE; ++FI, ++idx)
        if (FR->getDecl() == *FI)
          break;

      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
      // This is offset in bits.
      Offset += Layout.getFieldOffset(idx);
      break;
    }
    }
  }

 Finish:
  if (SymbolicOffsetBase)
    return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
  return RegionOffset(R, Offset);
}
Пример #29
0
SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
                                   bool &Failed) {
  Failed = false;

  const MemRegion *MR = Base.getAsRegion();
  if (!MR)
    return UnknownVal();

  // Assume the derived class is a pointer or a reference to a CXX record.
  TargetType = TargetType->getPointeeType();
  assert(!TargetType.isNull());
  const CXXRecordDecl *TargetClass = TargetType->getAsCXXRecordDecl();
  if (!TargetClass && !TargetType->isVoidType())
    return UnknownVal();

  // Drill down the CXXBaseObject chains, which represent upcasts (casts from
  // derived to base).
  while (const CXXRecordDecl *MRClass = getCXXRecordType(MR)) {
    // If found the derived class, the cast succeeds.
    if (MRClass == TargetClass)
      return loc::MemRegionVal(MR);

    // We skip over incomplete types. They must be the result of an earlier
    // reinterpret_cast, as one can only dynamic_cast between types in the same
    // class hierarchy.
    if (!TargetType->isVoidType() && MRClass->hasDefinition()) {
      // Static upcasts are marked as DerivedToBase casts by Sema, so this will
      // only happen when multiple or virtual inheritance is involved.
      CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
                         /*DetectVirtual=*/false);
      if (MRClass->isDerivedFrom(TargetClass, Paths))
        return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front());
    }

    if (const auto *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) {
      // Drill down the chain to get the derived classes.
      MR = BaseR->getSuperRegion();
      continue;
    }

    // If this is a cast to void*, return the region.
    if (TargetType->isVoidType())
      return loc::MemRegionVal(MR);

    // Strange use of reinterpret_cast can give us paths we don't reason
    // about well, by putting in ElementRegions where we'd expect
    // CXXBaseObjectRegions. If it's a valid reinterpret_cast (i.e. if the
    // derived class has a zero offset from the base class), then it's safe
    // to strip the cast; if it's invalid, -Wreinterpret-base-class should
    // catch it. In the interest of performance, the analyzer will silently
    // do the wrong thing in the invalid case (because offsets for subregions
    // will be wrong).
    const MemRegion *Uncasted = MR->StripCasts(/*IncludeBaseCasts=*/false);
    if (Uncasted == MR) {
      // We reached the bottom of the hierarchy and did not find the derived
      // class. We must be casting the base to derived, so the cast should
      // fail.
      break;
    }

    MR = Uncasted;
  }

  // If we're casting a symbolic base pointer to a derived class, use
  // CXXDerivedObjectRegion to represent the cast. If it's a pointer to an
  // unrelated type, it must be a weird reinterpret_cast and we have to
  // be fine with ElementRegion. TODO: Should we instead make
  // Derived{TargetClass, Element{SourceClass, SR}}?
  if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) {
    QualType T = SR->getSymbol()->getType();
    const CXXRecordDecl *SourceClass = T->getPointeeCXXRecordDecl();
    if (TargetClass && SourceClass && TargetClass->isDerivedFrom(SourceClass))
      return loc::MemRegionVal(
          MRMgr.getCXXDerivedObjectRegion(TargetClass, SR));
    return loc::MemRegionVal(GetElementZeroRegion(SR, TargetType));
  }

  // We failed if the region we ended up with has perfect type info.
  Failed = isa<TypedValueRegion>(MR);
  return UnknownVal();
}
/// Checks whether the return types are covariant, according to
/// C++[class.virtual]p7.
///
/// Similar with clang::Sema::CheckOverridingFunctionReturnType.
/// \returns true if the return types of BaseMD and DerivedMD are covariant.
static bool checkOverridingFunctionReturnType(const ASTContext *Context,
                                              const CXXMethodDecl *BaseMD,
                                              const CXXMethodDecl *DerivedMD) {
  QualType BaseReturnTy = BaseMD->getType()
                              ->getAs<FunctionType>()
                              ->getReturnType()
                              .getCanonicalType();
  QualType DerivedReturnTy = DerivedMD->getType()
                                 ->getAs<FunctionType>()
                                 ->getReturnType()
                                 .getCanonicalType();

  if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
    return false;

  // Check if return types are identical.
  if (Context->hasSameType(DerivedReturnTy, BaseReturnTy))
    return true;

  /// Check if the return types are covariant.

  // Both types must be pointers or references to classes.
  if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) &&
      !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType()))
    return false;

  /// BTy is the class type in return type of BaseMD. For example,
  ///    B* Base::md()
  /// While BRD is the declaration of B.
  QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType();
  QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType();

  const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
  const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
  if (DRD == nullptr || BRD == nullptr)
    return false;

  if (!DRD->hasDefinition() || !BRD->hasDefinition())
    return false;

  if (DRD == BRD)
    return true;

  if (!Context->hasSameUnqualifiedType(DTy, BTy)) {
    // Begin checking whether the conversion from D to B is valid.
    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);

    // Check whether D is derived from B, and fill in a CXXBasePaths object.
    if (!DRD->isDerivedFrom(BRD, Paths))
      return false;

    // Check ambiguity.
    if (Paths.isAmbiguous(Context->getCanonicalType(BTy).getUnqualifiedType()))
      return false;

    // Check accessibility.
    // FIXME: We currently only support checking if B is accessible base class
    // of D, or D is the same class which DerivedMD is in.
    bool IsItself =
        DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
    bool HasPublicAccess = false;
    for (const auto &Path : Paths) {
      if (Path.Access == AS_public)
        HasPublicAccess = true;
    }
    if (!HasPublicAccess && !IsItself)
      return false;
    // End checking conversion from D to B.
  }

  // Both pointers or references should have the same cv-qualification.
  if (DerivedReturnTy.getLocalCVRQualifiers() !=
      BaseReturnTy.getLocalCVRQualifiers())
    return false;

  // The class type D should have the same cv-qualification as or less
  // cv-qualification than the class type B.
  if (DTy.isMoreQualifiedThan(BTy))
    return false;

  return true;
}