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,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 *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 InitExprStmts; for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) { if (PathDiagnosticCallPiece *C = dyn_cast(*I)) removeEdgesToDefaultInitializers(C->path); @@ -265,11 +276,28 @@ 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 (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(*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(*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() :