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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits