Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -802,6 +802,21 @@ } } +namespace { +class CollectReachableSymbolsCallback final : public SymbolVisitor { + InvalidatedSymbols Symbols; + +public: + CollectReachableSymbolsCallback(ProgramStateRef State) {} + const InvalidatedSymbols &getSymbols() const { return Symbols; } + + bool VisitSymbol(SymbolRef Sym) override { + Symbols.insert(Sym); + return true; + } +}; +} // end anonymous namespace + void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &DstTop) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), @@ -1078,8 +1093,24 @@ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, resultType, currBldrCtx->blockCount()); - ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result); - Bldr2.generateNode(S, N, state); + ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result); + + // FIXME: Remove this first check when we begin modelling these + // expression classes separately. + if (!isa(Ex)) + for (auto Child : Ex->children()) { + if (!Child) + continue; + SVal Val = State->getSVal(Child, LCtx); + CollectReachableSymbolsCallback Scanner = + State->scanReachableSymbols( + Val); + const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols(); + State = getCheckerManager().runCheckersForPointerEscape( + State, EscapedSymbols, + /*CallEvent*/ nullptr, PSK_EscapeOther, nullptr); + } + Bldr2.generateNode(S, N, State); } getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this); @@ -2193,21 +2224,6 @@ getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this); } -namespace { -class CollectReachableSymbolsCallback final : public SymbolVisitor { - InvalidatedSymbols Symbols; - -public: - CollectReachableSymbolsCallback(ProgramStateRef State) {} - const InvalidatedSymbols &getSymbols() const { return Symbols; } - - bool VisitSymbol(SymbolRef Sym) override { - Symbols.insert(Sym); - return true; - } -}; -} // end anonymous namespace - // A value escapes in three possible cases: // (1) We are binding to something that is not a memory region. // (2) We are binding to a MemrRegion that does not have stack storage. Index: test/Analysis/initializer.cpp =================================================================== --- test/Analysis/initializer.cpp +++ test/Analysis/initializer.cpp @@ -1,7 +1,9 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s void clang_analyzer_eval(bool); +#include "Inputs/system-header-simulator-cxx.h" + class A { int x; public: @@ -204,3 +206,13 @@ const char(&f)[2]; }; } + +namespace CXX_initializer_lists { +struct C { + C(std::initializer_list list); +}; +void foo() { + int *x = new int; + C c{x}; // no-warning +} +}