[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