r175716 - [analyzer] Record whether a base object region represents a virtual base.
Jordan Rose
jordan_rose at apple.com
Wed Feb 20 19:12:33 PST 2013
Author: jrose
Date: Wed Feb 20 21:12:32 2013
New Revision: 175716
URL: http://llvm.org/viewvc/llvm-project?rev=175716&view=rev
Log:
[analyzer] Record whether a base object region represents a virtual base.
This allows MemRegion and MemRegionManager to avoid asking over and over
again whether an class is a virtual base or a non-virtual base.
Minor optimization/cleanup; no functionality change.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Wed Feb 20 21:12:32 2013
@@ -1055,16 +1055,18 @@ public:
class CXXBaseObjectRegion : public TypedValueRegion {
friend class MemRegionManager;
- const CXXRecordDecl *decl;
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
- CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg)
- : TypedValueRegion(sReg, CXXBaseObjectRegionKind), decl(d) {}
+ CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
+ const MemRegion *SReg)
+ : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {}
- static void ProfileRegion(llvm::FoldingSetNodeID &ID,
- const CXXRecordDecl *decl, const MemRegion *sReg);
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+ bool IsVirtual, const MemRegion *SReg);
public:
- const CXXRecordDecl *getDecl() const { return decl; }
+ const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
+ bool isVirtual() const { return Data.getInt(); }
QualType getValueType() const;
@@ -1214,15 +1216,21 @@ public:
const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
LocationContext const *LC);
- const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
- const MemRegion *superRegion);
+ /// Create a CXXBaseObjectRegion with the given base class for region
+ /// \p Super.
+ ///
+ /// The type of \p Super is assumed be a class deriving from \p BaseClass.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super,
+ bool IsVirtual);
/// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
/// super region.
const CXXBaseObjectRegion *
getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
const MemRegion *superRegion) {
- return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
+ return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
+ baseReg->isVirtual());
}
const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Wed Feb 20 21:12:32 2013
@@ -136,7 +136,8 @@ public:
SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
/// Evaluates a derived-to-base cast through a single level of derivation.
- SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType);
+ SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
+ bool IsVirtual);
/// \brief Evaluates C++ dynamic_cast cast.
/// The callback may result in the following 3 scenarios:
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Feb 20 21:12:32 2013
@@ -487,8 +487,10 @@ void ExprEngine::ProcessBaseDtor(const C
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);
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Feb 20 21:12:32 2013
@@ -161,8 +161,10 @@ void ExprEngine::VisitCXXConstructExpr(c
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;
Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Wed Feb 20 21:12:32 2013
@@ -234,7 +234,7 @@ QualType ObjCIvarRegion::getValueType()
}
QualType CXXBaseObjectRegion::getValueType() const {
- return QualType(decl->getTypeForDecl(), 0);
+ return QualType(getDecl()->getTypeForDecl(), 0);
}
//===----------------------------------------------------------------------===//
@@ -402,14 +402,16 @@ void CXXTempObjectRegion::Profile(llvm::
}
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(r
}
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
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;
+
+ if (IsVirtual)
+ return Class->isVirtuallyDerivedFrom(BaseClass);
+
+ 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;
+ }
- } 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;
- }
- }
+ 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));
- assert(FoundBase && "Not a direct base class of this region");
-#endif
+ 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() co
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();
Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Wed Feb 20 21:12:32 2013
@@ -254,7 +254,7 @@ SVal StoreManager::evalDerivedToBase(SVa
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(SVa
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(SVa
assert(BaseDecl && "not a C++ object?");
const MemRegion *BaseReg =
- MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion());
+ MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(),
+ IsVirtual);
return loc::MemRegionVal(BaseReg);
}
More information about the cfe-commits
mailing list