| // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s | |
| void clang_analyzer_eval(int); | |
| void clang_analyzer_warnOnDeadSymbol(int); | |
| namespace test_dead_region_with_live_subregion_in_environment { | |
| int glob; | |
| struct A { | |
| int x; | |
| void foo() { | |
| // FIXME: Maybe just let clang_analyzer_eval() work within callees already? | |
| // The glob variable shouldn't keep our symbol alive because | |
| // 'x != 0' is concrete 'true'. | |
| glob = (x != 0); | |
| } | |
| }; | |
| void test_A(A a) { | |
| if (a.x == 0) | |
| return; | |
| clang_analyzer_warnOnDeadSymbol(a.x); | |
| // What we're testing is that a.x is alive until foo() exits. | |
| a.foo(); // no-warning // (i.e., no 'SYMBOL DEAD' yet) | |
| // Let's see if constraints on a.x were known within foo(). | |
| clang_analyzer_eval(glob); // expected-warning{{TRUE}} | |
| // expected-warning@-1{{SYMBOL DEAD}} | |
| } | |
| struct B { | |
| A a; | |
| int y; | |
| }; | |
| A &noop(A &a) { | |
| // This function ensures that the 'b' expression within its argument | |
| // would be cleaned up before its call, so that only 'b.a' remains | |
| // in the Environment. | |
| return a; | |
| } | |
| void test_B(B b) { | |
| if (b.a.x == 0) | |
| return; | |
| clang_analyzer_warnOnDeadSymbol(b.a.x); | |
| // What we're testing is that b.a.x is alive until foo() exits. | |
| noop(b.a).foo(); // no-warning // (i.e., no 'SYMBOL DEAD' yet) | |
| // Let's see if constraints on a.x were known within foo(). | |
| clang_analyzer_eval(glob); // expected-warning{{TRUE}} | |
| // expected-warning@-1{{SYMBOL DEAD}} | |
| } | |
| } // namespace test_dead_region_with_live_subregion_in_environment |