diff options
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 19 | ||||
| -rw-r--r-- | clang/test/Analysis/temporaries.cpp | 16 |
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 |

