]> granicus.if.org Git - clang/commitdiff
[analyzer] Don't inline dynamic-dispatch methods unless -analyzer-ipa=dynamic.
authorJordan Rose <jordan_rose@apple.com>
Wed, 15 Aug 2012 00:52:00 +0000 (00:52 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 15 Aug 2012 00:52:00 +0000 (00:52 +0000)
Previously we were checking -analyzer-ipa=dynamic-bifurcate only, and
unconditionally inlining everything else that had an available definition,
even under -analyzer-ipa=inlining (but not under -analyzer-ipa=none).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161916 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
test/Analysis/inlining/dyn-dispatch-bifurcate.cpp [new file with mode: 0644]

index 8ee6723057a6153af0bb04be27eca77ae10f81dd..5b93dfdb83de3de5a8d06699f5e2663ea6cdcfa4 100644 (file)
@@ -555,12 +555,18 @@ void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
     RuntimeDefinition RD = Call->getRuntimeDefinition();
     const Decl *D = RD.getDecl();
     if (D) {
-      // Explore with and without inlining the call.
-      if (RD.mayHaveOtherDefinitions() &&
-          getAnalysisManager().IPAMode == DynamicDispatchBifurcate) {
-        BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred);
-        return;
+      if (RD.mayHaveOtherDefinitions()) {
+        // Explore with and without inlining the call.
+        if (getAnalysisManager().IPAMode == DynamicDispatchBifurcate) {
+          BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred);
+          return;
+        }
+
+        // Don't inline if we're not in any dynamic dispatch mode.
+        if (getAnalysisManager().IPAMode != DynamicDispatch)
+          return;
       }
+
       // We are not bifurcating and we do have a Decl, so just inline.
       if (inlineCall(*Call, D, Bldr, Pred, State))
         return;
@@ -575,6 +581,7 @@ void ExprEngine::BifurcateCall(const MemRegion *BifurReg,
                                const CallEvent &Call, const Decl *D,
                                NodeBuilder &Bldr, ExplodedNode *Pred) {
   assert(BifurReg);
+  BifurReg = BifurReg->StripCasts();
 
   // Check if we've performed the split already - note, we only want
   // to split the path once per memory region.
diff --git a/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp b/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp
new file mode 100644 (file)
index 0000000..fa473ae
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=dynamic-bifurcate -verify %s
+
+void clang_analyzer_eval(bool);
+
+class A {
+public:
+  virtual int get() { return 0; }
+};
+
+void testBifurcation(A *a) {
+  clang_analyzer_eval(a->get() == 0); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}}
+}
+
+void testKnown() {
+  A a;
+  clang_analyzer_eval(a.get() == 0); // expected-warning{{TRUE}}
+}