1 // RUN: %clang_analyze_cc1 %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=debug.ExprInspection \
4 // RUN: -analyzer-config eagerly-assume=false \
7 void clang_analyzer_warnIfReached(void);
8 void clang_analyzer_eval(_Bool
);
10 void test_simplification_adjustment_concrete_int(int b
, int c
) {
11 if (b
< 0 || b
> 1) // b: [0,1]
13 if (c
< -1 || c
> 1) // c: [-1,1]
15 if (c
+ b
!= 0) // c + b == 0
17 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
18 if (b
!= 1) // b == 1 --> c + 1 == 0 --> c == -1
20 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
21 clang_analyzer_eval(c
== -1); // expected-warning{{TRUE}}
23 // Keep the symbols and the constraints! alive.
28 void test_simplification_adjustment_range(int b
, int c
) {
29 if (b
< 0 || b
> 1) // b: [0,1]
31 if (c
< -1 || c
> 1) // c: [-1,1]
33 if (c
+ b
< -1 || c
+ b
> 0) // c + b: [-1,0]
35 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
36 if (b
!= 1) // b == 1 --> c + 1: [-1,0] --> c: [-2,-1]
38 // c: [-2,-1] is intersected with the
39 // already associated range which is [-1,1],
40 // thus we get c: [-1,-1]
41 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
42 clang_analyzer_eval(c
== -1); // expected-warning{{TRUE}}
44 // Keep the symbols and the constraints! alive.
49 void test_simplification_adjustment_to_infeasible_concrete_int(int b
, int c
) {
50 if (b
< 0 || b
> 1) // b: [0,1]
52 if (c
< 0 || c
> 1) // c: [0,1]
54 if (c
+ b
!= 0) // c + b == 0
56 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
57 if (b
!= 1) { // b == 1 --> c + 1 == 0 --> c == -1 contradiction
58 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
59 clang_analyzer_eval(c
== 0); // expected-warning{{TRUE}}
60 // Keep the symbols and the constraints! alive.
64 clang_analyzer_warnIfReached(); // no warning
66 // Keep the symbols and the constraints! alive.
71 void test_simplification_adjustment_to_infeassible_range(int b
, int c
) {
72 if (b
< 0 || b
> 1) // b: [0,1]
74 if (c
< 0 || c
> 1) // c: [0,1]
76 if (c
+ b
< -1 || c
+ b
> 0) // c + b: [-1,0]
78 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
79 if (b
!= 1) // b == 1 --> c + 1: [-1,0] --> c: [-2,-1] contradiction
81 clang_analyzer_warnIfReached(); // no warning
83 // Keep the symbols and the constraints! alive.
88 void test_simplification_adjusment_no_infinite_loop(int a
, int b
, int c
) {
96 // The above simplification of `b == 0` could result in an infinite loop
97 // unless we detect that the State is unchanged.
99 // 1) Simplification of the trivial equivalence class
100 // "symbol": "(reg_$0<int a>) == (reg_$1<int b>)", "range": "{ [0, 0] }"
102 // "symbol": "(reg_$0<int a>) == 0", "range": "{ [0, 0] }" }
103 // which in turn creates a non-trivial equivalence class
104 // [ "(reg_$0<int a>) == (reg_$1<int b>)", "(reg_$0<int a>) == 0" ]
105 // 2) We call assumeSymInclusiveRange("(reg_$0<int a>) == 0")
106 // and that calls **simplify** on the associated non-trivial equivalence
107 // class. During the simplification the State does not change, we reached