[cfe-commits] r161710 - in /cfe/trunk: lib/StaticAnalyzer/Core/CallEvent.cpp test/Analysis/inline.cpp

Jordan Rose jordan_rose at apple.com
Fri Aug 10 15:26:46 PDT 2012


Author: jrose
Date: Fri Aug 10 17:26:46 2012
New Revision: 161710

URL: http://llvm.org/viewvc/llvm-project?rev=161710&view=rev
Log:
[analyzer] Strip CXXBaseObjectRegions when devirtualizing method calls.

This was causing a crash when we tried to re-apply a base object region to
itself. It probably also caused incorrect offset calculations in RegionStore.

PR13569 / <rdar://problem/12076683>

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
    cfe/trunk/test/Analysis/inline.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=161710&r1=161709&r2=161710&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Fri Aug 10 17:26:46 2012
@@ -15,6 +15,7 @@
 
 #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"
@@ -408,11 +409,34 @@
                                             BindingsTy &Bindings) const {
   AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings);
 
+  // Handle the binding of 'this' in the new stack frame.
+  // We need to make sure we have the proper layering of CXXBaseObjectRegions.
   SVal ThisVal = getCXXThisVal();
   if (!ThisVal.isUnknown()) {
-    SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
+    ProgramStateManager &StateMgr = getState()->getStateManager();
+    SValBuilder &SVB = StateMgr.getSValBuilder();
+    
     const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl());
     Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
+
+    if (const MemRegion *ThisReg = ThisVal.getAsRegion()) {
+      const CXXRecordDecl *Class = MD->getParent();
+
+      // We may be downcasting to call a devirtualized virtual method.
+      // Search through the base casts we already have to see if we can just
+      // strip them off.
+      const CXXBaseObjectRegion *BaseReg;
+      while ((BaseReg = dyn_cast<CXXBaseObjectRegion>(ThisReg))) {
+        if (BaseReg->getDecl() == Class)
+          break;
+        ThisReg = BaseReg->getSuperRegion();
+      }
+
+      // Either we found the right base class, or we stripped all the casts to
+      // the most derived type. Either one is good.
+      ThisVal = loc::MemRegionVal(ThisReg);
+    }
+
     Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
   }
 }

Modified: cfe/trunk/test/Analysis/inline.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.cpp?rev=161710&r1=161709&r2=161710&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.cpp (original)
+++ cfe/trunk/test/Analysis/inline.cpp Fri Aug 10 17:26:46 2012
@@ -71,3 +71,41 @@
 }
 
 
+namespace PR13569 {
+  class Parent {
+  protected:
+    int m_parent;
+    virtual int impl() const = 0;
+
+    Parent() : m_parent(0) {}
+
+  public:
+    int interface() const {
+      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+      return impl();
+    }
+  };
+
+  class Child : public Parent {
+  protected:
+    virtual int impl() const {
+      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+      return m_parent + m_child;
+    }
+
+  public:
+    Child() : m_child(0) {}
+
+    int m_child;
+  };
+
+  void testVirtual() {
+    Child x;
+    x.m_child = 42;
+
+    // Don't crash when inlining and devirtualizing.
+    x.interface();
+  }
+}
+
+





More information about the cfe-commits mailing list