summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-02-15 19:34:19 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-02-15 19:34:19 +0000
commit543e8af99d8d4d529d89bde398f9eea809c9d712 (patch)
treecf4cc9b3568399dcc2effb5a1082081f252cc237
parenta5e3675bd3bb333257191a0dc37c59e41b418823 (diff)
downloadbcm5719-llvm-543e8af99d8d4d529d89bde398f9eea809c9d712.tar.gz
bcm5719-llvm-543e8af99d8d4d529d89bde398f9eea809c9d712.zip
[analyzer] Suppress temporary destructors for temporary arrays.
Array destructors, like constructors, need to be called for each element of the array separately. We do not have any mechanisms to do this in the analyzer, so for now all we do is evaluate a single constructor or destructor conservatively and give up. It automatically causes the necessary invalidation and pointer escape for the whole array, because this is how RegionStore works. Implement this conservative behavior for temporary destructors. This fixes the crash on the provided test. Differential Revision: https://reviews.llvm.org/D43149 llvm-svn: 325286
-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