1 // RUN: %clang_analyze_cc1 %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=debug.ExprInspection \
4 // RUN: -analyzer-config eagerly-assume=false \
5 // RUN: -verify
6
7 void clang_analyzer_eval(bool);
8 void clang_analyzer_warnIfReached();
9
test_legacy_behavior(int x,int y)10 int test_legacy_behavior(int x, int y) {
11 if (y != 0)
12 return 0;
13 if (x + y != 0)
14 return 0;
15 clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
16 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
17 return y / (x + y); // expected-warning{{Division by zero}}
18 }
19
test_rhs_further_constrained(int x,int y)20 int test_rhs_further_constrained(int x, int y) {
21 if (x + y != 0)
22 return 0;
23 if (y != 0)
24 return 0;
25 clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
26 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
27 return 0;
28 }
29
test_lhs_further_constrained(int x,int y)30 int test_lhs_further_constrained(int x, int y) {
31 if (x + y != 0)
32 return 0;
33 if (x != 0)
34 return 0;
35 clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
36 clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
37 return 0;
38 }
39
test_lhs_and_rhs_further_constrained(int x,int y)40 int test_lhs_and_rhs_further_constrained(int x, int y) {
41 if (x % y != 1)
42 return 0;
43 if (x != 1)
44 return 0;
45 if (y != 2)
46 return 0;
47 clang_analyzer_eval(x % y == 1); // expected-warning{{TRUE}}
48 clang_analyzer_eval(y == 2); // expected-warning{{TRUE}}
49 return 0;
50 }
51
test_commutativity(int x,int y)52 int test_commutativity(int x, int y) {
53 if (x + y != 0)
54 return 0;
55 if (y != 0)
56 return 0;
57 clang_analyzer_eval(y + x == 0); // expected-warning{{TRUE}}
58 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
59 return 0;
60 }
61
test_binop_when_height_is_2_r(int a,int x,int y,int z)62 int test_binop_when_height_is_2_r(int a, int x, int y, int z) {
63 switch (a) {
64 case 1: {
65 if (x + y + z != 0)
66 return 0;
67 if (z != 0)
68 return 0;
69 clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
70 clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
71 break;
72 }
73 case 2: {
74 if (x + y + z != 0)
75 return 0;
76 if (y != 0)
77 return 0;
78 clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
79 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
80 break;
81 }
82 case 3: {
83 if (x + y + z != 0)
84 return 0;
85 if (x != 0)
86 return 0;
87 clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
88 clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
89 break;
90 }
91 case 4: {
92 if (x + y + z != 0)
93 return 0;
94 if (x + y != 0)
95 return 0;
96 clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
97 clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
98 break;
99 }
100 case 5: {
101 if (z != 0)
102 return 0;
103 if (x + y + z != 0)
104 return 0;
105 clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
106 if (y != 0)
107 return 0;
108 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
109 clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
110 clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
111 break;
112 }
113
114 }
115 return 0;
116 }
117
test_equivalence_classes_are_updated(int a,int b,int c,int d)118 void test_equivalence_classes_are_updated(int a, int b, int c, int d) {
119 if (a + b != c)
120 return;
121 if (a != d)
122 return;
123 if (b != 0)
124 return;
125 clang_analyzer_eval(c == d); // expected-warning{{TRUE}}
126 // Keep the symbols and the constraints! alive.
127 (void)(a * b * c * d);
128 return;
129 }
130
test_contradiction(int a,int b,int c,int d)131 void test_contradiction(int a, int b, int c, int d) {
132 if (a + b != c)
133 return;
134 if (a == c)
135 return;
136 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
137
138 // Bring in the contradiction.
139 if (b != 0)
140 return;
141 clang_analyzer_warnIfReached(); // no-warning, i.e. UNREACHABLE
142 // Keep the symbols and the constraints! alive.
143 (void)(a * b * c * d);
144 return;
145 }
146
test_deferred_contradiction(int e0,int b0,int b1)147 void test_deferred_contradiction(int e0, int b0, int b1) {
148
149 int e1 = e0 - b0; // e1 is bound to (reg_$0<int e0>) - (reg_$1<int b0>)
150 (void)(b0 == 2); // bifurcate
151
152 int e2 = e1 - b1;
153 if (e2 > 0) { // b1 != e1
154 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
155 // Here, e1 is still bound to (reg_$0<int e0>) - (reg_$1<int b0>) but we
156 // should be able to simplify it to (reg_$0<int e0>) - 2 and thus realize
157 // the contradiction.
158 if (b1 == e1) {
159 clang_analyzer_warnIfReached(); // no-warning, i.e. UNREACHABLE
160 (void)(b0 * b1 * e0 * e1 * e2);
161 }
162 }
163 }
164