diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 1 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 35 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 34 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SVals.cpp | 4 |
4 files changed, 53 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 619f9b200b..6a5faa054c 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -15,7 +15,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/Analysis/ProgramPoint.h" -#include "clang/AST/CXXInheritance.h" #include "clang/AST/ParentMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 19548be5e1..62e602a7e1 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -888,6 +888,37 @@ MemRegionManager::getCXXTempObjectRegion(Expr const *E, 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)); + + } 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; + } + } + + assert(FoundBase && "Not a direct base class of this region"); +#endif + } + } + } + return getSubRegion<CXXBaseObjectRegion>(decl, superRegion); } @@ -963,7 +994,7 @@ const MemRegion *MemRegion::getBaseRegion() const { // View handling. //===----------------------------------------------------------------------===// -const MemRegion *MemRegion::StripCasts() const { +const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const { const MemRegion *R = this; while (true) { switch (R->getKind()) { @@ -975,6 +1006,8 @@ const MemRegion *MemRegion::StripCasts() const { break; } case CXXBaseObjectRegionKind: + if (!StripBaseCasts) + return R; R = cast<CXXBaseObjectRegion>(R)->getSuperRegion(); break; default: diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index f0eac9dc2b..05d1bd0dcf 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -934,7 +934,7 @@ SVal RegionStoreManager::evalDynamicCast(SVal base, QualType derivedType, loc::MemRegionVal *baseRegVal = dyn_cast<loc::MemRegionVal>(&base); if (!baseRegVal) return UnknownVal(); - const MemRegion *BaseRegion = baseRegVal->stripCasts(); + const MemRegion *BaseRegion = baseRegVal->stripCasts(/*StripBases=*/false); // Assume the derived class is a pointer or a reference to a CXX record. derivedType = derivedType->getPointeeType(); @@ -957,23 +957,23 @@ SVal RegionStoreManager::evalDynamicCast(SVal base, QualType derivedType, if (SRDecl == DerivedDecl) return loc::MemRegionVal(TSR); - // If the region type is a subclass of the derived type. - if (!derivedType->isVoidType() && SRDecl->isDerivedFrom(DerivedDecl)) { - // This occurs in two cases. - // 1) We are processing an upcast. - // 2) We are processing a downcast but we jumped directly from the - // ancestor to a child of the cast value, so conjure the - // appropriate region to represent value (the intermediate node). - return loc::MemRegionVal(MRMgr.getCXXBaseObjectRegion(DerivedDecl, - BaseRegion)); - } + if (!derivedType->isVoidType()) { + // Static upcasts are marked as DerivedToBase casts by Sema, so this will + // only happen when multiple or virtual inheritance is involved. + // FIXME: We should build the correct stack of CXXBaseObjectRegions here, + // instead of just punting. + if (SRDecl->isDerivedFrom(DerivedDecl)) + return UnknownVal(); - // If super region is not a parent of derived class, the cast definitely - // fails. - if (!derivedType->isVoidType() && - DerivedDecl->isProvablyNotDerivedFrom(SRDecl)) { - Failed = true; - return UnknownVal(); + // If super region is not a parent of derived class, the cast definitely + // fails. + // FIXME: This and the above test each require walking the entire + // inheritance hierarchy, and this will happen for each + // CXXBaseObjectRegion wrapper. We should probably be combining the two. + if (DerivedDecl->isProvablyNotDerivedFrom(SRDecl)) { + Failed = true; + return UnknownVal(); + } } if (const CXXBaseObjectRegion *R = dyn_cast<CXXBaseObjectRegion>(TSR)) diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index e32ffe2b48..8437f50f91 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -133,9 +133,9 @@ const MemRegion *SVal::getAsRegion() const { return 0; } -const MemRegion *loc::MemRegionVal::stripCasts() const { +const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const { const MemRegion *R = getRegion(); - return R ? R->StripCasts() : NULL; + return R ? R->StripCasts(StripBaseCasts) : NULL; } const void *nonloc::LazyCompoundVal::getStore() const { |