diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 6 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 92 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/Store.cpp | 11 |
4 files changed, 65 insertions, 50 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 89df40fecb1..d03f3bd0487 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -487,8 +487,10 @@ void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, SVal ThisVal = Pred->getState()->getSVal(ThisPtr); // Create the base object region. - QualType BaseTy = D.getBaseSpecifier()->getType(); - SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy); + const CXXBaseSpecifier *Base = D.getBaseSpecifier(); + QualType BaseTy = Base->getType(); + SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy, + Base->isVirtual()); VisitCXXDestructor(BaseTy, BaseVal.castAs<loc::MemRegionVal>().getRegion(), CurDtor->getBody(), /*IsBase=*/ true, Pred, Dst); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index cb3339d9cc5..d7cb5d18786 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -161,8 +161,10 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, Target = ThisVal.getAsRegion(); } else { // Cast to the base type. - QualType BaseTy = CE->getType(); - SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy); + bool IsVirtual = + (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); + SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), + IsVirtual); Target = BaseVal.getAsRegion(); } break; diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 922a9849aba..9792a306b05 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -234,7 +234,7 @@ QualType ObjCIvarRegion::getValueType() const { } QualType CXXBaseObjectRegion::getValueType() const { - return QualType(decl->getTypeForDecl(), 0); + return QualType(getDecl()->getTypeForDecl(), 0); } //===----------------------------------------------------------------------===// @@ -402,14 +402,16 @@ void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { } void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, - const CXXRecordDecl *decl, - const MemRegion *sReg) { - ID.AddPointer(decl); - ID.AddPointer(sReg); + const CXXRecordDecl *RD, + bool IsVirtual, + const MemRegion *SReg) { + ID.AddPointer(RD); + ID.AddBoolean(IsVirtual); + ID.AddPointer(SReg); } void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { - ProfileRegion(ID, decl, superRegion); + ProfileRegion(ID, getDecl(), isVirtual(), superRegion); } //===----------------------------------------------------------------------===// @@ -472,7 +474,7 @@ void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { } void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { - os << "base{" << superRegion << ',' << decl->getName() << '}'; + os << "base{" << superRegion << ',' << getDecl()->getName() << '}'; } void CXXThisRegion::dumpToStream(raw_ostream &os) const { @@ -885,41 +887,49 @@ MemRegionManager::getCXXTempObjectRegion(Expr const *E, return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC)); } -const CXXBaseObjectRegion * -MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *decl, - const MemRegion *superRegion) { - // Check that the base class is actually a direct base of this region. - if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(superRegion)) { - if (const CXXRecordDecl *Class = TVR->getValueType()->getAsCXXRecordDecl()){ - if (Class->isVirtuallyDerivedFrom(decl)) { - // Virtual base regions should not be layered, since the layout rules - // are different. - while (const CXXBaseObjectRegion *Base = - dyn_cast<CXXBaseObjectRegion>(superRegion)) { - superRegion = Base->getSuperRegion(); - } - assert(superRegion && !isa<MemSpaceRegion>(superRegion)); +/// Checks whether \p BaseClass is a valid virtual or direct non-virtual base +/// class of the type of \p Super. +static bool isValidBaseClass(const CXXRecordDecl *BaseClass, + const TypedValueRegion *Super, + bool IsVirtual) { + const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl(); + if (!Class) + return true; - } else { - // Non-virtual bases should always be direct bases. -#ifndef NDEBUG - bool FoundBase = false; - for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), - E = Class->bases_end(); - I != E; ++I) { - if (I->getType()->getAsCXXRecordDecl() == decl) { - FoundBase = true; - break; - } - } + if (IsVirtual) + return Class->isVirtuallyDerivedFrom(BaseClass); - assert(FoundBase && "Not a direct base class of this region"); -#endif + for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), + E = Class->bases_end(); + I != E; ++I) { + if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass) + return true; + } + + return false; +} + +const CXXBaseObjectRegion * +MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, + const MemRegion *Super, + bool IsVirtual) { + RD = RD->getCanonicalDecl(); + + if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(Super)) { + assert(isValidBaseClass(RD, TVR, IsVirtual)); + + if (IsVirtual) { + // Virtual base regions should not be layered, since the layout rules + // are different. + while (const CXXBaseObjectRegion *Base = + dyn_cast<CXXBaseObjectRegion>(Super)) { + Super = Base->getSuperRegion(); } + assert(Super && !isa<MemSpaceRegion>(Super)); } } - return getSubRegion<CXXBaseObjectRegion>(decl, superRegion); + return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super); } const CXXThisRegion* @@ -1146,14 +1156,12 @@ RegionOffset MemRegion::getAsOffset() const { if (SymbolicOffsetBase) continue; - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child); - CharUnits BaseOffset; - const CXXRecordDecl *Base = BOR->getDecl(); - if (Child->isVirtuallyDerivedFrom(Base)) - BaseOffset = Layout.getVBaseClassOffset(Base); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child); + if (BOR->isVirtual()) + BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl()); else - BaseOffset = Layout.getBaseClassOffset(Base); + BaseOffset = Layout.getBaseClassOffset(BOR->getDecl()); // The base offset is in chars, not in bits. Offset += BaseOffset.getQuantity() * getContext().getCharWidth(); diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp index 3695cbcce8b..a0c24fedcfc 100644 --- a/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/clang/lib/StaticAnalyzer/Core/Store.cpp @@ -254,7 +254,7 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { for (CastExpr::path_const_iterator I = Cast->path_begin(), E = Cast->path_end(); I != E; ++I) { - Result = evalDerivedToBase(Result, (*I)->getType()); + Result = evalDerivedToBase(Result, (*I)->getType(), (*I)->isVirtual()); } return Result; } @@ -264,12 +264,14 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { SVal Result = Derived; for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end(); I != E; ++I) { - Result = evalDerivedToBase(Result, I->Base->getType()); + Result = evalDerivedToBase(Result, I->Base->getType(), + I->Base->isVirtual()); } return Result; } -SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) { +SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, + bool IsVirtual) { Optional<loc::MemRegionVal> DerivedRegVal = Derived.getAs<loc::MemRegionVal>(); if (!DerivedRegVal) @@ -281,7 +283,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) { assert(BaseDecl && "not a C++ object?"); const MemRegion *BaseReg = - MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion()); + MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(), + IsVirtual); return loc::MemRegionVal(BaseReg); } |