[PATCH] Append CXXDefaultInitExpr's wrapped expression to the CFG when visiting a constructor initializer

Enrico Pertoso epertoso at google.com
Wed Dec 11 08:27:48 PST 2013


Hi rsmith, jordan_rose,

http://llvm-reviews.chandlerc.com/D2370

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2370?vs=6000&id=6026#toc

Files:
  lib/Analysis/CFG.cpp
  lib/StaticAnalyzer/Core/BugReporter.cpp
  test/Analysis/edges-new.mm

Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -766,9 +766,19 @@
       // generating destructors for the second time.
       return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
     }
+    if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(Init)) {
+      // In general, appending the expression wrapped by a CXXDefaultInitExpr
+      // may cause the same Expr to appear more than once in the CFG. Doing it
+      // here is safe because there's only one initializer per field.
+      autoCreateBlock();
+      appendStmt(Block, Default);
+      if (Stmt *Child = Default->getExpr())
+        if (CFGBlock *R = Visit(Child))
+          Block = R;
+      return Block;
+    }
     return Visit(Init);
   }
-
   return Block;
 }
 
Index: lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporter.cpp
+++ lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -246,10 +246,21 @@
   }
 }
 
+/// Populates the given set with all the statements that appear in the given
+/// expression.
+static void BuildStmtSet(const Stmt *Ex, llvm::DenseSet<const Stmt *> *Set) {
+  Set->insert(Ex);
+  for (Stmt::const_child_iterator I = Ex->child_begin(), E = Ex->child_end();
+       I != E; ++I) {
+    BuildStmtSet(*I, Set);
+  }
+}
+
 /// Remove edges in and out of C++ default initializer expressions. These are
 /// for fields that have in-class initializers, as opposed to being initialized
 /// explicitly in a constructor or braced list.
 static void removeEdgesToDefaultInitializers(PathPieces &Pieces) {
+  llvm::DenseSet<const Stmt *> InitExprStmts;
   for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
     if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I))
       removeEdgesToDefaultInitializers(C->path);
@@ -265,11 +276,28 @@
         I = Pieces.erase(I);
         continue;
       } else if (End && isa<CXXDefaultInitExpr>(End)) {
-        PathPieces::iterator Next = llvm::next(I);
-        if (Next != E) {
-          if (PathDiagnosticControlFlowPiece *NextCF =
-                dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
-            NextCF->setStartLocation(CF->getStartLocation());
+        const Expr *InitExpr = cast<CXXDefaultInitExpr>(End)->getExpr();
+        if (InitExprStmts.empty())
+          BuildStmtSet(InitExpr, &InitExprStmts);
+        if (Start && InitExprStmts.find(Start) != InitExprStmts.end()) {
+          if (I != Pieces.begin()) {
+            PathPieces::iterator Prev = llvm::prior(I);
+            if (PathDiagnosticControlFlowPiece *PrevCF =
+                    dyn_cast<PathDiagnosticControlFlowPiece>(*Prev)) {
+              CF->setStartLocation(PrevCF->getStartLocation());
+              Start = CF->getStartLocation().asStmt();
+              Pieces.erase(Prev);
+              continue;
+            }
+          }
+        } else {
+          InitExprStmts.clear();
+          PathPieces::iterator Next = llvm::next(I);
+          if (Next != E) {
+            if (PathDiagnosticControlFlowPiece *NextCF =
+                    dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
+              NextCF->setStartLocation(CF->getStartLocation());
+            }
           }
         }
         I = Pieces.erase(I);
Index: test/Analysis/edges-new.mm
===================================================================
--- test/Analysis/edges-new.mm
+++ test/Analysis/edges-new.mm
@@ -577,7 +577,7 @@
 namespace rdar14960554 {
   class Foo {
     int a = 1;
-    int b = 2;
+    int b = a ? 2 : 1;
     int c = 3;
 
     Foo() :
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2370.2.patch
Type: text/x-patch
Size: 3721 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131211/9dde937d/attachment.bin>


More information about the cfe-commits mailing list