xref: /llvm-project/clang/test/Analysis/find-binop-constraints.cpp (revision 8ddbb442b6e87efc9c6599280740c6f4fc40963d)
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