aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp35
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp34
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp4
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 {