Author: dergachev Date: Wed Jun 13 18:54:21 2018 New Revision: 334683 URL: http://llvm.org/viewvc/llvm-project?rev=334683&view=rev Log: [analyzer] Re-enable C++17-specific variable and member construction contexts.
Not contexts themselves, but rather support for them in the analyzer. Such construction contexts appear when C++17 mandatory copy elision occurs during initialization, and presence of a destructor causes a CXXBindTemporaryExpr to appear in the AST. Similar C++17-specific constructors for return values are still to be supported. Differential Revision: https://reviews.llvm.org/D47351 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=334683&r1=334682&r2=334683&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Jun 13 18:54:21 2018 @@ -119,8 +119,9 @@ std::pair<ProgramStateRef, SVal> ExprEng // current construction context. if (CC) { switch (CC->getKind()) { + case ConstructionContext::CXX17ElidedCopyVariableKind: case ConstructionContext::SimpleVariableKind: { - const auto *DSCC = cast<SimpleVariableConstructionContext>(CC); + const auto *DSCC = cast<VariableConstructionContext>(CC); const auto *DS = DSCC->getDeclStmt(); const auto *Var = cast<VarDecl>(DS->getSingleDecl()); SVal LValue = State->getLValue(Var, LCtx); @@ -131,6 +132,7 @@ std::pair<ProgramStateRef, SVal> ExprEng addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, LValue); return std::make_pair(State, LValue); } + case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: case ConstructionContext::SimpleConstructorInitializerKind: { const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC); const auto *Init = ICC->getCXXCtorInitializer(); @@ -259,9 +261,7 @@ std::pair<ProgramStateRef, SVal> ExprEng CallOpts.IsTemporaryCtorOrDtor = true; return std::make_pair(State, V); } - case ConstructionContext::CXX17ElidedCopyVariableKind: case ConstructionContext::CXX17ElidedCopyReturnedValueKind: - case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: // Not implemented yet. break; } Modified: cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp?rev=334683&r1=334682&r2=334683&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp (original) +++ cfe/trunk/test/Analysis/cxx17-mandatory-elision.cpp Wed Jun 13 18:54:21 2018 @@ -49,9 +49,64 @@ public: } }; + +struct A { + int x; + A(): x(0) {} + ~A() {} +}; + +struct B { + A a; + B() : a(A()) {} +}; + +void foo() { + B b; + clang_analyzer_eval(b.a.x == 0); // expected-warning{{TRUE}} +} + } // namespace ctor_initializer +namespace elision_on_ternary_op_branches { +class C1 { + int x; +public: + C1(int x): x(x) {} + int getX() const { return x; } + ~C1(); +}; + +class C2 { + int x; + int y; +public: + C2(int x, int y): x(x), y(y) {} + int getX() const { return x; } + int getY() const { return y; } + ~C2(); +}; + +void foo(int coin) { + C1 c1 = coin ? C1(1) : C1(2); + if (coin) { + clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}} + } else { + clang_analyzer_eval(c1.getX() == 2); // expected-warning{{TRUE}} + } + C2 c2 = coin ? C2(3, 4) : C2(5, 6); + if (coin) { + clang_analyzer_eval(c2.getX() == 3); // expected-warning{{TRUE}} + clang_analyzer_eval(c2.getY() == 4); // expected-warning{{TRUE}} + } else { + clang_analyzer_eval(c2.getX() == 5); // expected-warning{{TRUE}} + clang_analyzer_eval(c2.getY() == 6); // expected-warning{{TRUE}} + } +} +} // namespace elision_on_ternary_op_branches + + namespace address_vector_tests { template <typename T> struct AddressVector { @@ -108,4 +163,68 @@ void testMultipleReturns() { #endif } +class ClassWithDestructor { + AddressVector<ClassWithDestructor> &v; + +public: + ClassWithDestructor(AddressVector<ClassWithDestructor> &v) : v(v) { + v.push(this); + } + + ClassWithDestructor(ClassWithDestructor &&c) : v(c.v) { v.push(this); } + ClassWithDestructor(const ClassWithDestructor &c) : v(c.v) { + v.push(this); + } + + ~ClassWithDestructor() { v.push(this); } +}; + +void testVariable() { + AddressVector<ClassWithDestructor> v; + { + ClassWithDestructor c = ClassWithDestructor(v); + } +#if __cplusplus >= 201703L + // 0. Construct the variable. + // 1. Destroy the variable. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} +#else + // 0. Construct the temporary. + // 1. Construct the variable. + // 2. Destroy the temporary. + // 3. Destroy the variable. + clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}} +#endif +} + +struct TestCtorInitializer { + ClassWithDestructor c; + TestCtorInitializer(AddressVector<ClassWithDestructor> &v) + : c(ClassWithDestructor(v)) {} +}; + +void testCtorInitializer() { + AddressVector<ClassWithDestructor> v; + { + TestCtorInitializer t(v); + } +#if __cplusplus >= 201703L + // 0. Construct the member variable. + // 1. Destroy the member variable. + clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}} +#else + // 0. Construct the temporary. + // 1. Construct the member variable. + // 2. Destroy the temporary. + // 3. Destroy the member variable. + clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}} + clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}} +#endif +} + } // namespace address_vector_tests _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits