diff options
Diffstat (limited to 'test/Analysis/temporaries.cpp')
-rw-r--r-- | test/Analysis/temporaries.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp index efc0825..6b49fcb 100644 --- a/test/Analysis/temporaries.cpp +++ b/test/Analysis/temporaries.cpp @@ -1,5 +1,6 @@ // 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 extern bool clang_analyzer_eval(bool); @@ -109,3 +110,148 @@ namespace compound_literals { } } +namespace destructors { + void testPR16664andPR18159Crash() { + struct Dtor { + ~Dtor(); + }; + extern bool coin(); + extern bool check(const Dtor &); + +#ifndef TEMPORARY_DTORS + // FIXME: Don't crash here when tmp dtros are enabled. + // PR16664 and PR18159 + if (coin() && (coin() || coin() || check(Dtor()))) { + Dtor(); + } +#endif + } + +#ifdef TEMPORARY_DTORS + struct NoReturnDtor { + ~NoReturnDtor() __attribute__((noreturn)); + }; + + void noReturnTemp(int *x) { + if (! x) NoReturnDtor(); + *x = 47; // no warning + } + + void noReturnInline(int **x) { + NoReturnDtor(); + } + + void callNoReturn() { + int *x; + noReturnInline(&x); + *x = 47; // no warning + } + + extern bool check(const NoReturnDtor &); + + void testConsistencyIf(int i) { + if (i != 5) + return; + if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) { + clang_analyzer_eval(true); // no warning, unreachable code + } + } + + void testConsistencyTernary(int i) { + (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0; + + clang_analyzer_eval(true); // expected-warning{{TRUE}} + + if (i != 5) + return; + + (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0; + + clang_analyzer_eval(true); // no warning, unreachable code + } + + +/* + // PR16664 and PR18159 + FIXME: Don't crash here. + void testConsistencyNested(int i) { + extern bool compute(bool); + + if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor()))) + clang_analyzer_eval(true); // expected TRUE + + if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor()))) + clang_analyzer_eval(true); // expected TRUE + + if (i != 5) + return; + + if (compute(i == 5 && + (i == 4 || compute(true) || + compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) || + i != 4) { + clang_analyzer_eval(true); // expected TRUE + } + + if (compute(i == 5 && + (i == 4 || i == 4 || + compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) || + i != 4) { + clang_analyzer_eval(true); // no warning, unreachable code + } + }*/ + +#endif // TEMPORARY_DTORS +} + +void testStaticMaterializeTemporaryExpr() { + static const Trivial &ref = getTrivial(); + clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}} + + static const Trivial &directRef = Trivial(42); + clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}} + +#if __has_feature(cxx_thread_local) + thread_local static const Trivial &threadRef = getTrivial(); + clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}} + + thread_local static const Trivial &threadDirectRef = Trivial(42); + clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}} +#endif +} + +namespace PR16629 { + struct A { + explicit A(int* p_) : p(p_) {} + int* p; + }; + + extern void escape(const A*[]); + extern void check(int); + + void callEscape(const A& a) { + const A* args[] = { &a }; + escape(args); + } + + void testNoWarning() { + int x; + callEscape(A(&x)); + check(x); // Analyzer used to give a "x is uninitialized warning" here + } + + void set(const A*a[]) { + *a[0]->p = 47; + } + + void callSet(const A& a) { + const A* args[] = { &a }; + set(args); + } + + void testConsistency() { + int x; + callSet(A(&x)); + clang_analyzer_eval(x == 47); // expected-warning{{TRUE}} + } +} |