161 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -Wno-pointer-to-int-cast -verify %s2 3void clang_analyzer_eval(int);4void clang_analyzer_warnOnDeadSymbol(int);5void clang_analyzer_numTimesReached(void);6void clang_analyzer_warnIfReached(void);7 8void exit(int);9 10int conjure_index(void);11 12void test_that_expr_inspection_works(void) {13 do {14 int x = conjure_index();15 clang_analyzer_warnOnDeadSymbol(x);16 } while(0); // expected-warning{{SYMBOL DEAD}}17 18 // Make sure we don't accidentally split state in ExprInspection.19 clang_analyzer_numTimesReached(); // expected-warning{{1}}20}21 22// These tests verify the reaping of symbols that are only referenced as23// index values in element regions. Most of the time, depending on where24// the element region, as Loc value, is stored, it is possible to25// recover the index symbol in checker code, which is also demonstrated26// in the return_ptr_range.c test file.27 28int arr[3];29 30int *test_element_index_lifetime_in_environment_values(void) {31 int *ptr;32 do {33 int x = conjure_index();34 clang_analyzer_warnOnDeadSymbol(x);35 ptr = arr + x;36 } while (0);37 return ptr;38}39 40void test_element_index_lifetime_in_store_keys(void) {41 do {42 int x = conjure_index();43 clang_analyzer_warnOnDeadSymbol(x);44 arr[x] = 1;45 if (x) {}46 } while (0); // no-warning47}48 49int *ptr;50void test_element_index_lifetime_in_store_values(void) {51 do {52 int x = conjure_index();53 clang_analyzer_warnOnDeadSymbol(x);54 ptr = arr + x;55 } while (0); // no-warning56}57 58struct S1 {59 int field;60};61struct S2 {62 struct S1 array[5];63} s2;64struct S3 {65 void *field;66};67 68struct S1 *conjure_S1(void);69struct S3 *conjure_S3(void);70 71void test_element_index_lifetime_with_complicated_hierarchy_of_regions(void) {72 do {73 int x = conjure_index();74 clang_analyzer_warnOnDeadSymbol(x);75 s2.array[x].field = 1;76 if (x) {}77 } while (0); // no-warning78}79 80void test_loc_as_integer_element_index_lifetime(void) {81 do {82 int x;83 struct S3 *s = conjure_S3();84 clang_analyzer_warnOnDeadSymbol((int)s);85 x = (int)&(s->field);86 ptr = &arr[x];87 if (s) {}88 } while (0);89}90 91// Test below checks lifetime of SymbolRegionValue in certain conditions.92 93int **ptrptr;94void test_region_lifetime_as_store_value(int *x) {95 clang_analyzer_warnOnDeadSymbol((int) x);96 *x = 1;97 ptrptr = &x;98 (void)0; // No-op; make sure the environment forgets things and the GC runs.99 clang_analyzer_eval(**ptrptr); // expected-warning{{TRUE}}100} // no-warning101 102int *produce_region_referenced_only_through_field_in_environment_value(void) {103 struct S1 *s = conjure_S1();104 clang_analyzer_warnOnDeadSymbol((int) s);105 int *x = &s->field;106 return x;107}108 109void test_region_referenced_only_through_field_in_environment_value(void) {110 produce_region_referenced_only_through_field_in_environment_value();111} // expected-warning{{SYMBOL DEAD}}112 113void test_region_referenced_only_through_field_in_store_value(void) {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.117 if (!s) {118 exit(0); // no-warning (symbol should not die here)119 // exit() is noreturn.120 clang_analyzer_warnIfReached(); // no-warning121 }122 if (!ptr) { // no-warning (symbol should not die here)123 // We exit()ed under these constraints earlier.124 clang_analyzer_warnIfReached(); // no-warning125 }126 // The exit() call invalidates globals. The symbol will die here because127 // the exit() statement itself is already over and there's no better statement128 // to put the diagnostic on.129} // expected-warning{{SYMBOL DEAD}}130 131void test_zombie_referenced_only_through_field_in_store_value(void) {132 struct S1 *s = conjure_S1();133 clang_analyzer_warnOnDeadSymbol((int) s);134 int *x = &s->field;135} // expected-warning{{SYMBOL DEAD}}136 137void double_dereference_of_implicit_value_aux1(int *p) {138 *p = 0;139}140 141void double_dereference_of_implicit_value_aux2(int *p) {142 if (*p != 0)143 clang_analyzer_warnIfReached(); // no-warning144}145 146void test_double_dereference_of_implicit_value(int **x) {147 clang_analyzer_warnOnDeadSymbol(**x);148 int **y = x;149 {150 double_dereference_of_implicit_value_aux1(*y);151 // Give time for symbol reaping to happen.152 ((void)0);153 // The symbol for **y was cleaned up from the Store at this point,154 // even though it was not perceived as dead when asked explicitly.155 // For that reason the SYMBOL DEAD warning never appeared at this point.156 double_dereference_of_implicit_value_aux2(*y);157 }158 // The symbol is generally reaped here regardless.159 ((void)0); // expected-warning{{SYMBOL DEAD}}160}161