aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+ }
+};