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

Enrico Pertoso epertoso at google.com
Fri Dec 13 06:36:04 PST 2013


Hi rsmith, jordan_rose,

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

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

Files:
  lib/Analysis/CFG.cpp
  lib/Analysis/AnalysisDeclContext.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,6 +766,17 @@
       // 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);
   }
 
Index: lib/Analysis/AnalysisDeclContext.cpp
===================================================================
--- lib/Analysis/AnalysisDeclContext.cpp
+++ lib/Analysis/AnalysisDeclContext.cpp
@@ -239,6 +239,11 @@
                                                    E = C->init_end();
            I != E; ++I) {
         PM->addStmt((*I)->getInit());
+        if (const CXXDefaultInitExpr *DIE =
+                dyn_cast<CXXDefaultInitExpr>((*I)->getInit())) {
+          PM->addStmt(const_cast<Expr *>(DIE->getExpr()));
+          PM->setParent(DIE->getExpr(), DIE);
+        }
       }
     }
     if (builtCFG)
Index: lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporter.cpp
+++ lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -246,29 +246,38 @@
   }
 }
 
+static bool isInDefaultInitExpr(ParentMap &PM, const Stmt *S) {
+  while (S) {
+    if (isa<CXXDefaultInitExpr>(S))
+      return true;
+    S = PM.getParent(S);
+  }
+  return false;
+}
+
 /// 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) {
+static void removeEdgesToDefaultInitializers(PathPieces &Pieces, ParentMap &PM) {
   for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
     if (PathDiagnosticCallPiece *C = dyn_cast<PathDiagnosticCallPiece>(*I))
-      removeEdgesToDefaultInitializers(C->path);
+      removeEdgesToDefaultInitializers(C->path, PM);
 
     if (PathDiagnosticMacroPiece *M = dyn_cast<PathDiagnosticMacroPiece>(*I))
-      removeEdgesToDefaultInitializers(M->subPieces);
+      removeEdgesToDefaultInitializers(M->subPieces, PM);
 
     if (PathDiagnosticControlFlowPiece *CF =
           dyn_cast<PathDiagnosticControlFlowPiece>(*I)) {
       const Stmt *Start = CF->getStartLocation().asStmt();
       const Stmt *End = CF->getEndLocation().asStmt();
-      if (Start && isa<CXXDefaultInitExpr>(Start)) {
+      if (Start && isInDefaultInitExpr(PM, Start)) {
         I = Pieces.erase(I);
         continue;
-      } else if (End && isa<CXXDefaultInitExpr>(End)) {
+      } else if (End && isInDefaultInitExpr(PM, End)) {
         PathPieces::iterator Next = llvm::next(I);
         if (Next != E) {
           if (PathDiagnosticControlFlowPiece *NextCF =
-                dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
+                  dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
             NextCF->setStartLocation(CF->getStartLocation());
           }
         }
@@ -3229,7 +3238,7 @@
       // make sense.
       // We have to do this after edge optimization in the Extensive mode.
       removeRedundantMsgs(PD.getMutablePieces());
-      removeEdgesToDefaultInitializers(PD.getMutablePieces());
+      removeEdgesToDefaultInitializers(PD.getMutablePieces(), PDB.getParentMap());
     }
 
     // We found a report and didn't suppress it.
Index: test/Analysis/edges-new.mm
===================================================================
--- test/Analysis/edges-new.mm
+++ test/Analysis/edges-new.mm
@@ -588,6 +588,14 @@
         *(volatile int *)0 = 1;
     }
   };
+
+  class Bar {
+    int a = 1;
+    int b = a == 1 ? 2 : *(volatile int *)0;
+
+    Bar() :
+      a(2) {}
+  };
 }
 
 // CHECK:  <key>diagnostics</key>
@@ -19625,4 +19633,48 @@
 // CHECK-NEXT:    <key>file</key><integer>0</integer>
 // CHECK-NEXT:   </dict>
 // CHECK-NEXT:   </dict>
+// CHECK-NEXT:   <dict>
+// CHECK-NEXT:   <key>path</key>
+// CHECK-NEXT:   <array>
+// CHECK-NEXT:    <dict>
+// CHECK-NEXT:     <key>kind</key><string>event</string>
+// CHECK-NEXT:     <key>location</key>
+// CHECK-NEXT:     <dict>
+// CHECK-NEXT:      <key>line</key><integer>594</integer>
+// CHECK-NEXT:      <key>col</key><integer>26</integer>
+// CHECK-NEXT:      <key>file</key><integer>0</integer>
+// CHECK-NEXT:     </dict>
+// CHECK-NEXT:     <key>ranges</key>
+// CHECK-NEXT:     <array>
+// CHECK-NEXT:       <array>
+// CHECK-NEXT:        <dict>
+// CHECK-NEXT:         <key>line</key><integer>594</integer>
+// CHECK-NEXT:         <key>col</key><integer>26</integer>
+// CHECK-NEXT:         <key>file</key><integer>0</integer>
+// CHECK-NEXT:        </dict>
+// CHECK-NEXT:        <dict>
+// CHECK-NEXT:         <key>line</key><integer>594</integer>
+// CHECK-NEXT:         <key>col</key><integer>43</integer>
+// CHECK-NEXT:         <key>file</key><integer>0</integer>
+// CHECK-NEXT:        </dict>
+// CHECK-NEXT:       </array>
+// CHECK-NEXT:     </array>
+// CHECK-NEXT:     <key>depth</key><integer>0</integer>
+// CHECK-NEXT:     <key>extended_message</key>
+// CHECK-NEXT:     <string>Dereference of null pointer</string>
+// CHECK-NEXT:     <key>message</key>
+// CHECK-NEXT:     <string>Dereference of null pointer</string>
+// CHECK-NEXT:    </dict>
+// CHECK-NEXT:   </array>
+// CHECK-NEXT:   <key>description</key><string>Dereference of null pointer</string>
+// CHECK-NEXT:   <key>category</key><string>Logic error</string>
+// CHECK-NEXT:   <key>type</key><string>Dereference of null pointer</string>
+// CHECK-NEXT:  <key>issue_hash</key><string>4294967293</string>
+// CHECK-NEXT:  <key>location</key>
+// CHECK-NEXT:  <dict>
+// CHECK-NEXT:   <key>line</key><integer>594</integer>
+// CHECK-NEXT:   <key>col</key><integer>26</integer>
+// CHECK-NEXT:   <key>file</key><integer>0</integer>
+// CHECK-NEXT:  </dict>
+// CHECK-NEXT:  </dict>
 // CHECK-NEXT:  </array>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2370.3.patch
Type: text/x-patch
Size: 6436 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131213/03abfb5e/attachment.bin>


More information about the cfe-commits mailing list