[PATCH] Append CXXDefaultInitExpr's wrapped expression to the CFG when visiting a constructor initializer
Enrico Pertoso
epertoso at google.com
Tue Dec 10 03:09:39 PST 2013
enrico added you to the CC list for the revision "Append CXXDefaultInitExpr's wrapped expression to the CFG when visiting a constructor initializer".
Hi rsmith, jordan_rose,
This patch is part of http://llvm-reviews.chandlerc.com/D2181.
In-class initializers are appended to the CFG when CFGBuilder::addInitializer is called.
http://llvm-reviews.chandlerc.com/D2370
Files:
test/Analysis/edges-new.mm
lib/Analysis/CFG.cpp
lib/StaticAnalyzer/Core/BugReporter.cpp
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() :
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,6 +246,20 @@
}
}
+/// Returns true if the children tree spanned by the first statement contains
+/// the second statement.
+static bool containsStmt(const Stmt *Ex, const Stmt *S) {
+ if (Ex == S)
+ return true;
+
+ for (Stmt::const_child_iterator I = Ex->child_begin(), E = Ex->child_end();
+ I != E; ++I) {
+ if (containsStmt(*I, S))
+ return true;
+ }
+ 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.
@@ -265,11 +279,25 @@
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 (Start && containsStmt(InitExpr, Start)) {
+ 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 {
+ PathPieces::iterator Next = llvm::next(I);
+ if (Next != E) {
+ if (PathDiagnosticControlFlowPiece *NextCF =
+ dyn_cast<PathDiagnosticControlFlowPiece>(*Next)) {
+ NextCF->setStartLocation(CF->getStartLocation());
+ }
}
}
I = Pieces.erase(I);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2370.1.patch
Type: text/x-patch
Size: 3306 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131210/c5633a25/attachment.bin>
More information about the cfe-commits
mailing list