]> granicus.if.org Git - clang/commitdiff
[analyzer] A CXXBaseObjectRegion should correspond to a DIRECT base.
authorJordan Rose <jordan_rose@apple.com>
Thu, 9 Aug 2012 21:24:02 +0000 (21:24 +0000)
committerJordan Rose <jordan_rose@apple.com>
Thu, 9 Aug 2012 21:24:02 +0000 (21:24 +0000)
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

include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
lib/StaticAnalyzer/Core/ExprEngineC.cpp
lib/StaticAnalyzer/Core/Store.cpp
test/Analysis/derived-to-base.cpp

index eb60c92113b0c0e7056d65c403cc2a5887ed9996..466be9af51145d8e014f921e092b6344c2e55351 100644 (file)
@@ -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:
index 7ec151ef6d7eae8904f6e86be8f9b18973779f8f..46cba81b14f76f955393137d41ee1c60d02b448e 100644 (file)
@@ -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;
index b8097ab7c6290ddffaf747b3fa0ba5699f5102ce..3af60a1707276d3e4c1e9602e8b6a4c53bfc1f8e 100644 (file)
@@ -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
index f65b9db17b6573548e8cb74665edbbda45ed99a7..f6c9beb46576cac1a77be938cfba3fd6f7ad111d 100644 (file)
@@ -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;
+  }
+};