aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-08-09 21:24:02 +0000
committerJordan Rose <jordan_rose@apple.com>2012-08-09 21:24:02 +0000
commit2c5f8d79ed128892fa548a3308a938a3a53fbb5e (patch)
treeee6cd4b4e61f60b876678cc09b0baf2f05b190f2
parent6940972c33891ff5d2189fbf232dcdeee0e9daf8 (diff)
[analyzer] A CXXBaseObjectRegion should correspond to a DIRECT base.
An ASTContext's RecordLayoutInfo can only be used to look up offsets of direct base classes, and we need the offset to make non-symbolic bindings in RegionStore. This change makes sure that we have one layer of CXXBaseObjectRegion for each base we are casting through. This was causing crashes on an internal buildbot. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161621 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h5
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp11
-rw-r--r--test/Analysis/derived-to-base.cpp9
4 files changed, 25 insertions, 2 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index eb60c92113..466be9af51 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -115,7 +115,10 @@ public:
virtual SVal ArrayToPointer(Loc Array) = 0;
/// Evaluates DerivedToBase casts.
- virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) = 0;
+ virtual SVal evalDerivedToBase(SVal derived, const CastExpr *Cast);
+
+ /// Evaluates a derived-to-base cast through a single level of derivation.
+ virtual SVal evalDerivedToBase(SVal derived, QualType derivedPtrType) = 0;
/// \brief Evaluates C++ dynamic_cast cast.
/// The callback may result in the following 3 scenarios:
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 7ec151ef6d..46cba81b14 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -318,7 +318,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
SVal val = state->getSVal(Ex, LCtx);
- val = getStoreManager().evalDerivedToBase(val, T);
+ val = getStoreManager().evalDerivedToBase(val, CastE);
state = state->BindExpr(CastE, LCtx, val);
Bldr.generateNode(CastE, Pred, state);
continue;
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index b8097ab7c6..3af60a1707 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -222,6 +222,17 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
llvm_unreachable("unreachable");
}
+SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) {
+ // Walk through the cast path to create nested CXXBaseRegions.
+ SVal Result = Derived;
+ for (CastExpr::path_const_iterator I = Cast->path_begin(),
+ E = Cast->path_end();
+ I != E; ++I) {
+ Result = evalDerivedToBase(Result, (*I)->getType());
+ }
+ return Result;
+}
+
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
/// implicit casts that arise from loads from regions that are reinterpreted
diff --git a/test/Analysis/derived-to-base.cpp b/test/Analysis/derived-to-base.cpp
index f65b9db17b..f6c9beb465 100644
--- a/test/Analysis/derived-to-base.cpp
+++ b/test/Analysis/derived-to-base.cpp
@@ -13,3 +13,12 @@ public:
void B::f() {
x = 3;
}
+
+
+class C : public B {
+public:
+ void g() {
+ // This used to crash because we are upcasting through two bases.
+ x = 5;
+ }
+};