r184814 - [analyzer] Don't initialize virtual base classes more than once.

Jordan Rose jordan_rose at apple.com
Mon Jun 24 18:56:00 PDT 2013


Author: jrose
Date: Mon Jun 24 20:55:59 2013
New Revision: 184814

URL: http://llvm.org/viewvc/llvm-project?rev=184814&view=rev
Log:
[analyzer] Don't initialize virtual base classes more than once.

In order to make sure virtual base classes are always initialized once,
the AST contains initializers for the base class in /all/ of its
descendents, not just the immediate descendents. However, at runtime,
the most-derived object is responsible for initializing all the virtual
base classes; all the other initializers will be ignored.

The analyzer now checks to see if it's being called from another base
constructor, and if so does not perform virtual base initialization.

<rdar://problem/14236851>

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
    cfe/trunk/test/Analysis/ctor-inlining.mm

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=184814&r1=184813&r2=184814&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Mon Jun 24 20:55:59 2013
@@ -187,8 +187,26 @@ void ExprEngine::VisitCXXConstructExpr(c
 
     break;
   }
-  case CXXConstructExpr::CK_NonVirtualBase:
   case CXXConstructExpr::CK_VirtualBase:
+    // Make sure we are not calling virtual base class initializers twice.
+    // Only the most-derived object should initialize virtual base classes.
+    if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) {
+      const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer);
+      if (OuterCtor) {
+        switch (OuterCtor->getConstructionKind()) {
+        case CXXConstructExpr::CK_NonVirtualBase:
+        case CXXConstructExpr::CK_VirtualBase:
+          // Bail out!
+          destNodes.Add(Pred);
+          return;
+        case CXXConstructExpr::CK_Complete:
+        case CXXConstructExpr::CK_Delegating:
+          break;
+        }
+      }
+    }
+    // FALLTHROUGH
+  case CXXConstructExpr::CK_NonVirtualBase:
   case CXXConstructExpr::CK_Delegating: {
     const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
     Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,

Modified: cfe/trunk/test/Analysis/ctor-inlining.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ctor-inlining.mm?rev=184814&r1=184813&r2=184814&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/ctor-inlining.mm (original)
+++ cfe/trunk/test/Analysis/ctor-inlining.mm Mon Jun 24 20:55:59 2013
@@ -500,3 +500,37 @@ namespace ArrayMembers {
     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
   }
 };
+
+namespace VirtualInheritance {
+  int counter;
+
+  struct base {
+    base() {
+      ++counter;
+    }
+  };
+
+  struct virtual_subclass : public virtual base {
+    virtual_subclass() {}
+  };
+
+  struct double_subclass : public virtual_subclass {
+    double_subclass() {}
+  };
+
+  void test() {
+    counter = 0;
+    double_subclass obj;
+    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
+  }
+
+  struct double_virtual_subclass : public virtual virtual_subclass {
+    double_virtual_subclass() {}
+  };
+
+  void testVirtual() {
+    counter = 0;
+    double_virtual_subclass obj;
+    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
+  }
+}





More information about the cfe-commits mailing list