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

Jordan Rose jordan_rose at apple.com
Mon Aug 13 16:46:01 PDT 2012


Author: jrose
Date: Mon Aug 13 18:46:01 2012
New Revision: 161808

URL: http://llvm.org/viewvc/llvm-project?rev=161808&view=rev
Log:
[analyzer] Be more careful when downcasting for devirtualization.

Virtual base regions are never layered, so simply stripping them off won't
necessarily get you to the correct casted class. Instead, what we want is
the same logic for evaluating dynamic_cast: strip off base regions if possible,
but add new base regions if necessary.

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=161808&r1=161807&r2=161808&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Mon Aug 13 18:46:01 2012
@@ -419,21 +419,18 @@
     Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx);
 
     if (const MemRegion *ThisReg = ThisVal.getAsRegion()) {
+      ASTContext &Ctx = SVB.getContext();
       const CXXRecordDecl *Class = MD->getParent();
+      QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class));
 
-      // 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);
+      // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager.
+      bool Failed;
+      ThisVal = StateMgr.getStoreManager().evalDynamicCast(ThisVal, Ty, Failed);
+      assert(!Failed && "Calling an incorrectly devirtualized method");
+
+      // If we couldn't build the correct cast, just strip off all casts.
+      if (ThisVal.isUnknown())
+        ThisVal = loc::MemRegionVal(ThisReg->StripCasts());
     }
 
     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=161808&r1=161807&r2=161808&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.cpp (original)
+++ cfe/trunk/test/Analysis/inline.cpp Mon Aug 13 18:46:01 2012
@@ -106,6 +106,63 @@
     // Don't crash when inlining and devirtualizing.
     x.interface();
   }
+
+
+  class Grandchild : public Child {};
+
+  void testDevirtualizeToMiddle() {
+    Grandchild x;
+    x.m_child = 42;
+
+    // Don't crash when inlining and devirtualizing.
+    x.interface();
+  }
 }
 
+namespace PR13569_virtual {
+  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 : virtual 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();
+  }
+
+
+  class Grandchild : virtual public Child {};
+
+  void testDevirtualizeToMiddle() {
+    Grandchild x;
+    x.m_child = 42;
+
+    // Don't crash when inlining and devirtualizing.
+    x.interface();
+  }
+}





More information about the cfe-commits mailing list