]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/symbol-reaper.c
Vendor import of clang trunk r351319 (just before the release_80 branch
[FreeBSD/FreeBSD.git] / test / Analysis / symbol-reaper.c
1 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s
2
3 void clang_analyzer_eval(int);
4 void clang_analyzer_warnOnDeadSymbol(int);
5 void clang_analyzer_numTimesReached();
6 void clang_analyzer_warnIfReached();
7
8 void exit(int);
9
10 int conjure_index();
11
12 void test_that_expr_inspection_works() {
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 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.
27
28 int arr[3];
29
30 int *test_element_index_lifetime_in_environment_values() {
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
40 void test_element_index_lifetime_in_store_keys() {
41   do {
42     int x = conjure_index();
43     clang_analyzer_warnOnDeadSymbol(x);
44     arr[x] = 1;
45     if (x) {}
46   } while (0); // no-warning
47 }
48
49 int *ptr;
50 void test_element_index_lifetime_in_store_values() {
51   do {
52     int x = conjure_index();
53     clang_analyzer_warnOnDeadSymbol(x);
54     ptr = arr + x;
55   } while (0); // no-warning
56 }
57
58 struct S1 {
59   int field;
60 };
61 struct S2 {
62   struct S1 array[5];
63 } s2;
64 struct S3 {
65   void *field;
66 };
67
68 struct S1 *conjure_S1();
69 struct S3 *conjure_S3();
70
71 void test_element_index_lifetime_with_complicated_hierarchy_of_regions() {
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-warning
78 }
79
80 void test_loc_as_integer_element_index_lifetime() {
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
93 int **ptrptr;
94 void 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-warning
101
102 int *produce_region_referenced_only_through_field_in_environment_value() {
103   struct S1 *s = conjure_S1();
104   clang_analyzer_warnOnDeadSymbol((int) s);
105   int *x = &s->field;
106   return x;
107 }
108
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}}
112
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.
117   if (!s) {
118     exit(0); // no-warning (symbol should not die here)
119     // exit() is noreturn.
120     clang_analyzer_warnIfReached(); // no-warning
121   }
122   if (!ptr) { // no-warning (symbol should not die here)
123     // We exit()ed under these constraints earlier.
124     clang_analyzer_warnIfReached(); // no-warning
125   }
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}}
130
131 void test_zombie_referenced_only_through_field_in_store_value() {
132   struct S1 *s = conjure_S1();
133   clang_analyzer_warnOnDeadSymbol((int) s);
134   int *x = &s->field;
135 } // expected-warning{{SYMBOL DEAD}}