diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/Store.h | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 11 | ||||
-rw-r--r-- | test/Analysis/derived-to-base.cpp | 9 |
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; + } +}; |