[PATCH] D43062: [analyzer] Support CXXTemporaryObjectExpr constructors that have destructors.
This revision was automatically updated to reflect the committed changes. Closed by commit rL325211: [analyzer] Inline constructors for destroyable temporaries. (authored by dergachev, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D43062?vs=133475=134368#toc Repository: rL LLVM https://reviews.llvm.org/D43062 Files: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/test/Analysis/temporaries.cpp Index: cfe/trunk/test/Analysis/temporaries.cpp === --- cfe/trunk/test/Analysis/temporaries.cpp +++ cfe/trunk/test/Analysis/temporaries.cpp @@ -607,22 +607,37 @@ clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}} C c4 = returnTemporaryWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c4.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c4.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c4.getX() == 1); + clang_analyzer_eval(c4.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif C c5 = returnTemporaryWithAnotherFunctionWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c5.getX() == 1); + clang_analyzer_eval(c5.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif C c6 = returnTemporaryWithCopyConstructionWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c5.getX() == 1); + clang_analyzer_eval(c5.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif #if __cplusplus >= 201103L @@ -683,10 +698,84 @@ // expected-warning@-6{{UNKNOWN}} #endif - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d3.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(d3.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(d3.getX() == 1); + clang_analyzer_eval(d3.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif } } // namespace test_return_temporary + + +namespace test_temporary_object_expr_without_dtor { +class C { + int x; +public: + C(int x) : x(x) {} + int getX() const { return x; } +}; + +void test() { + clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}} +}; +} + +namespace test_temporary_object_expr_with_dtor { +class C { + int x; + +public: + C(int x) : x(x) {} + ~C() {} + int getX() const { return x; } +}; + +void test(int coin) { + clang_analyzer_eval(C(3).getX() == 3); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + + const C = coin ? C(1) : C(2); + if (coin) { +clang_analyzer_eval(c1.getX() == 1); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } else { +clang_analyzer_eval(c1.getX() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } + + C c2 = coin ? C(1) : C(2); + if (coin) { +clang_analyzer_eval(c2.getX() == 1); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } else { +clang_analyzer_eval(c2.getX() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } +} + +} // namespace test_temporary_object_expr Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -148,6 +148,9 @@ // construction context that'd give us the right temporary expression.
[PATCH] D43062: [analyzer] Support CXXTemporaryObjectExpr constructors that have destructors.
NoQ updated this revision to Diff 133475. NoQ added a comment. Add a simple test for a class with no destructor. https://reviews.llvm.org/D43062 Files: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/temporaries.cpp Index: test/Analysis/temporaries.cpp === --- test/Analysis/temporaries.cpp +++ test/Analysis/temporaries.cpp @@ -607,22 +607,37 @@ clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}} C c4 = returnTemporaryWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c4.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c4.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c4.getX() == 1); + clang_analyzer_eval(c4.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif C c5 = returnTemporaryWithAnotherFunctionWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c5.getX() == 1); + clang_analyzer_eval(c5.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif C c6 = returnTemporaryWithCopyConstructionWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c5.getX() == 1); + clang_analyzer_eval(c5.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif #if __cplusplus >= 201103L @@ -683,10 +698,84 @@ // expected-warning@-6{{UNKNOWN}} #endif - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d3.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(d3.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(d3.getX() == 1); + clang_analyzer_eval(d3.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif } } // namespace test_return_temporary + + +namespace test_temporary_object_expr_without_dtor { +class C { + int x; +public: + C(int x) : x(x) {} + int getX() const { return x; } +}; + +void test() { + clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}} +}; +} + +namespace test_temporary_object_expr_with_dtor { +class C { + int x; + +public: + C(int x) : x(x) {} + ~C() {} + int getX() const { return x; } +}; + +void test(int coin) { + clang_analyzer_eval(C(3).getX() == 3); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + + const C = coin ? C(1) : C(2); + if (coin) { +clang_analyzer_eval(c1.getX() == 1); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } else { +clang_analyzer_eval(c1.getX() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } + + C c2 = coin ? C(1) : C(2); + if (coin) { +clang_analyzer_eval(c2.getX() == 1); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } else { +clang_analyzer_eval(c2.getX() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } +} + +} // namespace test_temporary_object_expr Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -137,6 +137,9 @@ } else if (auto *RS = dyn_cast(TriggerStmt)) { CallOpts.IsTemporaryCtorOrDtor = true; return MRMgr.getCXXTempObjectRegion(CE, LCtx); + } else if (auto *BTE = dyn_cast(TriggerStmt)) { +CallOpts.IsTemporaryCtorOrDtor = true; +return MRMgr.getCXXTempObjectRegion(CE, LCtx); } // TODO: Consider other directly initialized elements. } else if (const CXXCtorInitializer
[PATCH] D43062: [analyzer] Support CXXTemporaryObjectExpr constructors that have destructors.
NoQ created this revision. NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet. Herald added subscribers: cfe-commits, rnkovacs. NoQ added a dependency: D43056: [CFG] [analyzer] Add construction context for CXXBindTemporaryExpr.. Patch https://reviews.llvm.org/D43056 adds support for such `CXXTemporaryObjectExpr` kind of constructors in the CFG. Here i add a straightforward analyzer-side support. Note that when we don't have destructors (i.e. we have trivial destructors), the analyzer inlines the temporary constructor regardless of whether it has a destructor in the CFG or not, actually also regardless of whether the target region is correct, so it kinda worked before, in simple cases. Repository: rC Clang https://reviews.llvm.org/D43062 Files: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp test/Analysis/temporaries.cpp Index: test/Analysis/temporaries.cpp === --- test/Analysis/temporaries.cpp +++ test/Analysis/temporaries.cpp @@ -607,22 +607,37 @@ clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}} C c4 = returnTemporaryWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c4.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c4.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c4.getX() == 1); + clang_analyzer_eval(c4.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif C c5 = returnTemporaryWithAnotherFunctionWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c5.getX() == 1); + clang_analyzer_eval(c5.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif C c6 = returnTemporaryWithCopyConstructionWithConstruction(); - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. - clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(c5.getX() == 1); + clang_analyzer_eval(c5.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif #if __cplusplus >= 201103L @@ -683,10 +698,71 @@ // expected-warning@-6{{UNKNOWN}} #endif - // Should be TRUE under TEMPORARY_DTORS once this sort of construction - // in the inlined function is supported. D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy(); - clang_analyzer_eval(d3.getX() == 1); // expected-warning{{UNKNOWN}} - clang_analyzer_eval(d3.getY() == 2); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(d3.getX() == 1); + clang_analyzer_eval(d3.getY() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-3{{TRUE}} + // expected-warning@-3{{TRUE}} +#else + // expected-warning@-6{{UNKNOWN}} + // expected-warning@-6{{UNKNOWN}} +#endif } } // namespace test_return_temporary + +namespace test_temporary_object_expr { + +class C { + int x; + +public: + C(int x) : x(x) {} + ~C() {} + int getX() const { return x; } +}; + +void test(int coin) { + clang_analyzer_eval(C(3).getX() == 3); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + + const C = coin ? C(1) : C(2); + if (coin) { +clang_analyzer_eval(c1.getX() == 1); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } else { +clang_analyzer_eval(c1.getX() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } + + C c2 = coin ? C(1) : C(2); + if (coin) { +clang_analyzer_eval(c2.getX() == 1); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } else { +clang_analyzer_eval(c2.getX() == 2); +#ifdef TEMPORARY_DTORS + // expected-warning@-2{{TRUE}} +#else + // expected-warning@-4{{UNKNOWN}} +#endif + } +} + +} // namespace test_temporary_object_expr Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp === --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -137,6 +137,9 @@ } else if (auto *RS =