NoQ created this revision. `std::initializer_list` objects can be constructed sort of explicitly, eg. `(std::initializer_list<int>){12}`. This produces an AST that looks like
CompoundLiteralExpr 0x11987f1a0 'std::initializer_list<int>':'class std::initializer_list<int>' `-CXXStdInitializerListExpr 0x11987f188 'std::initializer_list<int>':'class std::initializer_list<int>' `-MaterializeTemporaryExpr 0x11987f170 'const int [1]' xvalue `-InitListExpr 0x11987f128 'const int [1]' `-IntegerLiteral 0x11987cd18 'int' 12 We crash because we did not expect to see `CompoundLiteralExpr` containing `CXXStdInitializerListExpr`. It seems correct to pass the value through `CompoundLiteralExpr` transparently (the value is currently a conjured structure-symbol of `initializer_list` type, which sounds like a correct value for the expression, even if not super verbose), hence the patch. https://reviews.llvm.org/D39803 Files: lib/StaticAnalyzer/Core/ExprEngineC.cpp test/Analysis/initializer.cpp Index: test/Analysis/initializer.cpp =================================================================== --- test/Analysis/initializer.cpp +++ test/Analysis/initializer.cpp @@ -211,12 +211,16 @@ struct C { C(std::initializer_list<int *> list); }; -void foo() { +void testPointerEscapeIntoLists() { C empty{}; // no-crash // Do not warn that 'x' leaks. It might have been deleted by // the destructor of 'c'. int *x = new int; C c{x}; // no-warning } + +void testPassListsWithExplicitConstructors() { + (void)(std::initializer_list<int>){12}; // no-crash +} } Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -530,7 +530,7 @@ const Expr *Init = CL->getInitializer(); SVal V = State->getSVal(CL->getInitializer(), LCtx); - if (isa<CXXConstructExpr>(Init)) { + if (isa<CXXConstructExpr>(Init) || isa<CXXStdInitializerListExpr>(Init)) { // No work needed. Just pass the value up to this expression. } else { assert(isa<InitListExpr>(Init));
Index: test/Analysis/initializer.cpp =================================================================== --- test/Analysis/initializer.cpp +++ test/Analysis/initializer.cpp @@ -211,12 +211,16 @@ struct C { C(std::initializer_list<int *> list); }; -void foo() { +void testPointerEscapeIntoLists() { C empty{}; // no-crash // Do not warn that 'x' leaks. It might have been deleted by // the destructor of 'c'. int *x = new int; C c{x}; // no-warning } + +void testPassListsWithExplicitConstructors() { + (void)(std::initializer_list<int>){12}; // no-crash +} } Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -530,7 +530,7 @@ const Expr *Init = CL->getInitializer(); SVal V = State->getSVal(CL->getInitializer(), LCtx); - if (isa<CXXConstructExpr>(Init)) { + if (isa<CXXConstructExpr>(Init) || isa<CXXStdInitializerListExpr>(Init)) { // No work needed. Just pass the value up to this expression. } else { assert(isa<InitListExpr>(Init));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits