diff options
Diffstat (limited to 'clang/test/Analysis/temporaries.cpp')
-rw-r--r-- | clang/test/Analysis/temporaries.cpp | 173 |
1 files changed, 11 insertions, 162 deletions
diff --git a/clang/test/Analysis/temporaries.cpp b/clang/test/Analysis/temporaries.cpp index 0cc90880f44..c57d984a1dc 100644 --- a/clang/test/Analysis/temporaries.cpp +++ b/clang/test/Analysis/temporaries.cpp @@ -1,9 +1,8 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s -std=c++11 +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s extern bool clang_analyzer_eval(bool); -extern bool clang_analyzer_warnIfReached(); struct Trivial { Trivial(int x) : value(x) {} @@ -112,13 +111,13 @@ namespace compound_literals { } namespace destructors { - struct Dtor { - ~Dtor(); - }; - extern bool coin(); - extern bool check(const Dtor &); - void testPR16664andPR18159Crash() { + struct Dtor { + ~Dtor(); + }; + extern bool coin(); + extern bool check(const Dtor &); + // Regression test: we used to assert here when tmp dtors are enabled. // PR16664 and PR18159 if (coin() && (coin() || coin() || check(Dtor()))) { @@ -194,7 +193,8 @@ namespace destructors { (i == 4 || i == 4 || compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) || i != 4) { - clang_analyzer_eval(true); // no warning, unreachable code + // FIXME: This shouldn't cause a warning. + clang_analyzer_eval(true); // expected-warning{{TRUE}} } } @@ -211,7 +211,8 @@ namespace destructors { void testConsistencyNestedComplex(bool value) { if (value) { if (!value || !value || check(NoReturnDtor())) { - clang_analyzer_eval(true); // no warning, unreachable code + // FIXME: This shouldn't cause a warning. + clang_analyzer_eval(true); // expected-warning{{TRUE}} } } } @@ -224,112 +225,6 @@ namespace destructors { } } } - // PR16664 and PR18159 - void testConsistencyNestedComplexMidBranch(bool value) { - if (value) { - if (!value || !value || check(NoReturnDtor()) || value) { - clang_analyzer_eval(true); // no warning, unreachable code - } - } - } - - // PR16664 and PR18159 - void testConsistencyNestedComplexNestedBranch(bool value) { - if (value) { - if (!value || (!value || check(NoReturnDtor()) || value)) { - clang_analyzer_eval(true); // no warning, unreachable code - } - } - } - - // PR16664 and PR18159 - void testConsistencyNestedVariableModification(bool value) { - bool other = true; - if (value) { - if (!other || !value || (other = false) || check(NoReturnDtor()) || - !other) { - clang_analyzer_eval(true); // no warning, unreachable code - } - } - } - - void testTernaryNoReturnTrueBranch(bool value) { - if (value) { - bool b = value && value ? check(NoReturnDtor()) : true; - clang_analyzer_eval(true); // no warning, unreachable code - } - } - void testTernaryNoReturnFalseBranch(bool value) { - if (value) { - bool b = !value && !value ? true : check(NoReturnDtor()); - clang_analyzer_eval(true); // no warning, unreachable code - } - } - void testTernaryIgnoreNoreturnBranch(bool value) { - if (value) { - bool b = !value && !value ? check(NoReturnDtor()) : true; - clang_analyzer_eval(true); // expected-warning{{TRUE}} - } - } - - void testLoop() { - for (int i = 0; i < 10; ++i) { - if (i < 3 && (i >= 2 || check(NoReturnDtor()))) { - clang_analyzer_eval(true); // no warning, unreachable code - } - } - } - - bool testRecursiveFrames(bool isInner) { - if (isInner || - (clang_analyzer_warnIfReached(), false) || // expected-warning{{REACHABLE}} - check(NoReturnDtor()) || - testRecursiveFrames(true)) { - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - } - } - void testRecursiveFramesStart() { testRecursiveFrames(false); } - - void testLambdas() { - // This is the test we would like to write: - // []() { check(NoReturnDtor()); } != nullptr || check(Dtor()); - // But currently the analyzer stops when it encounters a lambda: - [] {}; - // The CFG for this now looks correct, but we still do not reach the line - // below. - clang_analyzer_warnIfReached(); // FIXME: Should warn. - } - - void testGnuExpressionStatements(int v) { - ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23; - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - - ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23; - clang_analyzer_warnIfReached(); // no warning, unreachable code - } - - void testGnuExpressionStatementsDestructionPoint(int v) { - // In normal context, the temporary destructor runs at the end of the full - // statement, thus the last statement is reached. - (++v, check(NoReturnDtor()), v == 42), - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - - // GNU expression statements execute temporary destructors within the - // blocks, thus the last statement is not reached. - ({ ++v; check(NoReturnDtor()); v == 42; }), - clang_analyzer_warnIfReached(); // no warning, unreachable code - } - - void testMultipleTemporaries(bool value) { - if (value) { - // FIXME: Find a way to verify construction order. - // ~Dtor should run before ~NoReturnDtor() because construction order is - // guaranteed by comma operator. - if (!value || check((NoReturnDtor(), Dtor())) || value) { - clang_analyzer_eval(true); // no warning, unreachable code - } - } - } void testBinaryOperatorShortcut(bool value) { if (value) { @@ -339,52 +234,6 @@ namespace destructors { } } - void testIfAtEndOfLoop() { - int y = 0; - while (true) { - if (y > 0) { - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - } - ++y; - // Test that the CFG gets hooked up correctly when temporary destructors - // are handled after a statically known branch condition. - if (true) (void)0; else (void)check(NoReturnDtor()); - } - } - - void testTernaryAtEndOfLoop() { - int y = 0; - while (true) { - if (y > 0) { - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - } - ++y; - // Test that the CFG gets hooked up correctly when temporary destructors - // are handled after a statically known branch condition. - true ? (void)0 : (void)check(NoReturnDtor()); - } - } - - void testNoReturnInComplexCondition() { - check(Dtor()) && - (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor()); - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - } - - void testSequencingOfConditionalTempDtors(bool b) { - b || (check(Dtor()), check(NoReturnDtor())); - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - } - - void testSequencingOfConditionalTempDtors2(bool b) { - (b || check(Dtor())), check(NoReturnDtor()); - clang_analyzer_warnIfReached(); // no warning, unreachable code - } - - void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) { - b || (check(Dtor()) + check(NoReturnDtor())); - clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} - } #endif // TEMPORARY_DTORS } |