// 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