[cfe-commits] r161798 - in /cfe/trunk: lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/derived-to-base.cpp

Jordan Rose jordan_rose at apple.com
Mon Aug 13 15:11:42 PDT 2012


Author: jrose
Date: Mon Aug 13 17:11:42 2012
New Revision: 161798

URL: http://llvm.org/viewvc/llvm-project?rev=161798&view=rev
Log:
[analyzer] Handle dynamic_casts that turn out to be upcasts.

This can occur with multiple inheritance, which jumps from one parent to
the other, and with virtual inheritance, since virtual base regions always
wrap the actual object and can't be nested within other base regions.

This also exposed some incorrect logic for multiple inheritance: even if B
is known not to derive from C, D might still derive from both of them.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/test/Analysis/derived-to-base.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=161798&r1=161797&r2=161798&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Mon Aug 13 17:11:42 2012
@@ -17,6 +17,7 @@
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/CXXInheritance.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Basic/TargetInfo.h"
@@ -960,19 +961,16 @@
     if (!derivedType->isVoidType()) {
       // Static upcasts are marked as DerivedToBase casts by Sema, so this will
       // only happen when multiple or virtual inheritance is involved.
-      // FIXME: We should build the correct stack of CXXBaseObjectRegions here,
-      // instead of just punting.
-      if (SRDecl->isDerivedFrom(DerivedDecl))
-        return UnknownVal();
-
-      // If super region is not a parent of derived class, the cast definitely
-      // fails.
-      // FIXME: This and the above test each require walking the entire
-      // inheritance hierarchy, and this will happen for each
-      // CXXBaseObjectRegion wrapper. We should probably be combining the two.
-      if (DerivedDecl->isProvablyNotDerivedFrom(SRDecl)) {
-        Failed = true;
-        return UnknownVal();
+      CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
+                         /*DetectVirtual=*/false);
+      if (SRDecl->isDerivedFrom(DerivedDecl, Paths)) {
+        SVal Result = loc::MemRegionVal(TSR);
+        const CXXBasePath &Path = *Paths.begin();
+        for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end();
+             I != E; ++I) {
+          Result = evalDerivedToBase(Result, I->Base->getType());
+        }
+        return Result;
       }
     }
 

Modified: cfe/trunk/test/Analysis/derived-to-base.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/derived-to-base.cpp?rev=161798&r1=161797&r2=161798&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/derived-to-base.cpp (original)
+++ cfe/trunk/test/Analysis/derived-to-base.cpp Mon Aug 13 17:11:42 2012
@@ -85,3 +85,53 @@
     clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
   }
 }
+
+
+namespace DynamicVirtualUpcast {
+  class A {
+  public:
+    virtual ~A();
+  };
+
+  class B : virtual public A {};
+  class C : virtual public B {};
+  class D : virtual public C {};
+
+  bool testCast(A *a) {
+    return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
+  }
+
+  void test() {
+    D d;
+    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
+  }
+}
+
+namespace DynamicMultipleInheritanceUpcast {
+  class B {
+  public:
+    virtual ~B();
+  };
+  class C {
+  public:
+    virtual ~C();
+  };
+  class D : public B, public C {};
+
+  bool testCast(B *a) {
+    return dynamic_cast<C*>(a);
+  }
+
+  void test() {
+    D d;
+    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
+  }
+
+
+  class DV : virtual public B, virtual public C {};
+
+  void testVirtual() {
+    DV d;
+    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
+  }
+}





More information about the cfe-commits mailing list