xref: /aosp_15_r20/external/clang/test/Analysis/symbol-reaper.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=debug.ExprInspection -verify %s
2*67e74705SXin Li 
3*67e74705SXin Li void clang_analyzer_eval(int);
4*67e74705SXin Li void clang_analyzer_warnOnDeadSymbol(int);
5*67e74705SXin Li 
6*67e74705SXin Li int conjure_index();
7*67e74705SXin Li 
test_that_expr_inspection_works()8*67e74705SXin Li void test_that_expr_inspection_works() {
9*67e74705SXin Li   do {
10*67e74705SXin Li     int x = conjure_index();
11*67e74705SXin Li     clang_analyzer_warnOnDeadSymbol(x);
12*67e74705SXin Li   } while(0); // expected-warning{{SYMBOL DEAD}}
13*67e74705SXin Li }
14*67e74705SXin Li 
15*67e74705SXin Li // These tests verify the reaping of symbols that are only referenced as
16*67e74705SXin Li // index values in element regions. Most of the time, depending on where
17*67e74705SXin Li // the element region, as Loc value, is stored, it is possible to
18*67e74705SXin Li // recover the index symbol in checker code, which is also demonstrated
19*67e74705SXin Li // in the return_ptr_range.c test file.
20*67e74705SXin Li 
21*67e74705SXin Li int arr[3];
22*67e74705SXin Li 
test_element_index_lifetime_in_environment_values()23*67e74705SXin Li int *test_element_index_lifetime_in_environment_values() {
24*67e74705SXin Li   int *ptr;
25*67e74705SXin Li   do {
26*67e74705SXin Li     int x = conjure_index();
27*67e74705SXin Li     clang_analyzer_warnOnDeadSymbol(x);
28*67e74705SXin Li     ptr = arr + x;
29*67e74705SXin Li   } while (0);
30*67e74705SXin Li   return ptr;
31*67e74705SXin Li }
32*67e74705SXin Li 
test_element_index_lifetime_in_store_keys()33*67e74705SXin Li void test_element_index_lifetime_in_store_keys() {
34*67e74705SXin Li   do {
35*67e74705SXin Li     int x = conjure_index();
36*67e74705SXin Li     clang_analyzer_warnOnDeadSymbol(x);
37*67e74705SXin Li     arr[x] = 1;
38*67e74705SXin Li     if (x) {}
39*67e74705SXin Li   } while (0); // no-warning
40*67e74705SXin Li }
41*67e74705SXin Li 
42*67e74705SXin Li int *ptr;
test_element_index_lifetime_in_store_values()43*67e74705SXin Li void test_element_index_lifetime_in_store_values() {
44*67e74705SXin Li   do {
45*67e74705SXin Li     int x = conjure_index();
46*67e74705SXin Li     clang_analyzer_warnOnDeadSymbol(x);
47*67e74705SXin Li     ptr = arr + x;
48*67e74705SXin Li   } while (0); // no-warning
49*67e74705SXin Li }
50*67e74705SXin Li 
51*67e74705SXin Li struct S1 {
52*67e74705SXin Li   int field;
53*67e74705SXin Li };
54*67e74705SXin Li struct S2 {
55*67e74705SXin Li   struct S1 array[5];
56*67e74705SXin Li } s2;
57*67e74705SXin Li 
test_element_index_lifetime_with_complicated_hierarchy_of_regions()58*67e74705SXin Li void test_element_index_lifetime_with_complicated_hierarchy_of_regions() {
59*67e74705SXin Li   do {
60*67e74705SXin Li     int x = conjure_index();
61*67e74705SXin Li     clang_analyzer_warnOnDeadSymbol(x);
62*67e74705SXin Li     s2.array[x].field = 1;
63*67e74705SXin Li     if (x) {}
64*67e74705SXin Li   } while (0); // no-warning
65*67e74705SXin Li }
66*67e74705SXin Li 
67*67e74705SXin Li // Test below checks lifetime of SymbolRegionValue in certain conditions.
68*67e74705SXin Li 
69*67e74705SXin Li int **ptrptr;
test_region_lifetime_as_store_value(int * x)70*67e74705SXin Li void test_region_lifetime_as_store_value(int *x) {
71*67e74705SXin Li   clang_analyzer_warnOnDeadSymbol((int) x);
72*67e74705SXin Li   *x = 1;
73*67e74705SXin Li   ptrptr = &x;
74*67e74705SXin Li   (void)0; // No-op; make sure the environment forgets things and the GC runs.
75*67e74705SXin Li   clang_analyzer_eval(**ptrptr); // expected-warning{{TRUE}}
76*67e74705SXin Li } // no-warning
77