summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp19
-rw-r--r--clang/test/Analysis/temporaries.cpp16
2 files changed, 32 insertions, 3 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index d1e3a8e86d8..8808e95aedd 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -957,7 +957,7 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
}
StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
- QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
+ QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
// FIXME: Currently CleanDtorState can be empty here due to temporaries being
// bound to default parameters.
assert(CleanDtorState.size() <= 1);
@@ -966,9 +966,22 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
EvalCallOptions CallOpts;
CallOpts.IsTemporaryCtorOrDtor = true;
- if (!MR)
+ if (!MR) {
CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
- VisitCXXDestructor(varType, MR, D.getBindTemporaryExpr(),
+
+ // If we have no MR, we still need to unwrap the array to avoid destroying
+ // the whole array at once. Regardless, we'd eventually need to model array
+ // destructors properly, element-by-element.
+ while (const ArrayType *AT = getContext().getAsArrayType(T)) {
+ T = AT->getElementType();
+ CallOpts.IsArrayCtorOrDtor = true;
+ }
+ } else {
+ // We'd eventually need to makeZeroElementRegion() trick here,
+ // but for now we don't have the respective construction contexts,
+ // so MR would always be null in this case. Do nothing for now.
+ }
+ VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),
/*IsBase=*/false, CleanPred, Dst, CallOpts);
}
diff --git a/clang/test/Analysis/temporaries.cpp b/clang/test/Analysis/temporaries.cpp
index fb0a0fdd6c4..2587e4ed56a 100644
--- a/clang/test/Analysis/temporaries.cpp
+++ b/clang/test/Analysis/temporaries.cpp
@@ -6,6 +6,8 @@ extern bool clang_analyzer_eval(bool);
extern bool clang_analyzer_warnIfReached();
void clang_analyzer_checkInlined(bool);
+#include "Inputs/system-header-simulator-cxx.h";
+
struct Trivial {
Trivial(int x) : value(x) {}
int value;
@@ -892,3 +894,17 @@ void test_ternary_temporary_with_copy(int coin) {
}
}
} // namespace test_match_constructors_and_destructors
+
+#if __cplusplus >= 201103L
+namespace temporary_list_crash {
+class C {
+public:
+ C() {}
+ ~C() {}
+};
+
+void test() {
+ std::initializer_list<C>{C(), C()}; // no-crash
+}
+} // namespace temporary_list_crash
+#endif // C++11
OpenPOWER on IntegriCloud