summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp6
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp6
-rw-r--r--clang/lib/StaticAnalyzer/Core/MemRegion.cpp92
-rw-r--r--clang/lib/StaticAnalyzer/Core/Store.cpp11
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);
}
OpenPOWER on IntegriCloud