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(Init)->getSubExpr()); } + if (CXXDefaultInitExpr *Default = dyn_cast(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(End)) { - PathPieces::iterator Next = llvm::next(I); - if (Next != E) { - if (PathDiagnosticControlFlowPiece *NextCF = - dyn_cast(*Next)) { - NextCF->setStartLocation(CF->getStartLocation()); + const Expr *InitExpr = cast(End)->getExpr(); + if (Start && containsStmt(InitExpr, Start)) { + if (I != Pieces.begin()) { + PathPieces::iterator Prev = llvm::prior(I); + if (PathDiagnosticControlFlowPiece *PrevCF = + dyn_cast(*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(*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() :