1 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s
3 void clang_analyzer_eval(int);
4 void clang_analyzer_warnOnDeadSymbol(int);
5 void clang_analyzer_numTimesReached();
6 void clang_analyzer_warnIfReached();
12 void test_that_expr_inspection_works() {
14 int x = conjure_index();
15 clang_analyzer_warnOnDeadSymbol(x);
16 } while(0); // expected-warning{{SYMBOL DEAD}}
18 // Make sure we don't accidentally split state in ExprInspection.
19 clang_analyzer_numTimesReached(); // expected-warning{{1}}
22 // These tests verify the reaping of symbols that are only referenced as
23 // index values in element regions. Most of the time, depending on where
24 // the element region, as Loc value, is stored, it is possible to
25 // recover the index symbol in checker code, which is also demonstrated
26 // in the return_ptr_range.c test file.
30 int *test_element_index_lifetime_in_environment_values() {
33 int x = conjure_index();
34 clang_analyzer_warnOnDeadSymbol(x);
40 void test_element_index_lifetime_in_store_keys() {
42 int x = conjure_index();
43 clang_analyzer_warnOnDeadSymbol(x);
46 } while (0); // no-warning
50 void test_element_index_lifetime_in_store_values() {
52 int x = conjure_index();
53 clang_analyzer_warnOnDeadSymbol(x);
55 } while (0); // no-warning
68 struct S1 *conjure_S1();
69 struct S3 *conjure_S3();
71 void test_element_index_lifetime_with_complicated_hierarchy_of_regions() {
73 int x = conjure_index();
74 clang_analyzer_warnOnDeadSymbol(x);
75 s2.array[x].field = 1;
77 } while (0); // no-warning
80 void test_loc_as_integer_element_index_lifetime() {
83 struct S3 *s = conjure_S3();
84 clang_analyzer_warnOnDeadSymbol((int)s);
91 // Test below checks lifetime of SymbolRegionValue in certain conditions.
94 void test_region_lifetime_as_store_value(int *x) {
95 clang_analyzer_warnOnDeadSymbol((int) x);
98 (void)0; // No-op; make sure the environment forgets things and the GC runs.
99 clang_analyzer_eval(**ptrptr); // expected-warning{{TRUE}}
102 int *produce_region_referenced_only_through_field_in_environment_value() {
103 struct S1 *s = conjure_S1();
104 clang_analyzer_warnOnDeadSymbol((int) s);
109 void test_region_referenced_only_through_field_in_environment_value() {
110 produce_region_referenced_only_through_field_in_environment_value();
111 } // expected-warning{{SYMBOL DEAD}}
113 void test_region_referenced_only_through_field_in_store_value() {
114 struct S1 *s = conjure_S1();
115 clang_analyzer_warnOnDeadSymbol((int) s);
116 ptr = &s->field; // Write the symbol into a global. It should live forever.
118 exit(0); // no-warning (symbol should not die here)
119 // exit() is noreturn.
120 clang_analyzer_warnIfReached(); // no-warning
122 if (!ptr) { // no-warning (symbol should not die here)
123 // We exit()ed under these constraints earlier.
124 clang_analyzer_warnIfReached(); // no-warning
126 // The exit() call invalidates globals. The symbol will die here because
127 // the exit() statement itself is already over and there's no better statement
128 // to put the diagnostic on.
129 } // expected-warning{{SYMBOL DEAD}}
131 void test_zombie_referenced_only_through_field_in_store_value() {
132 struct S1 *s = conjure_S1();
133 clang_analyzer_warnOnDeadSymbol((int) s);
135 } // expected-warning{{SYMBOL DEAD}}