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 &c1 = 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<ReturnStmt>(TriggerStmt)) { CallOpts.IsTemporaryCtorOrDtor = true; return MRMgr.getCXXTempObjectRegion(CE, LCtx); + } else if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(TriggerStmt)) { + CallOpts.IsTemporaryCtorOrDtor = true; + return MRMgr.getCXXTempObjectRegion(CE, LCtx); } // TODO: Consider other directly initialized elements. } else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits