1 // RUN: %clang_analyze_cc1 -verify %s \ 2 // RUN: -analyzer-checker=core,debug.ExprInspection \ 3 // RUN: -analyzer-config eagerly-assume=false 4 5 #define NULL (void *)0 6 7 #define UCHAR_MAX (unsigned char)(~0U) 8 #define CHAR_MAX (char)(UCHAR_MAX & (UCHAR_MAX >> 1)) 9 #define CHAR_MIN (char)(UCHAR_MAX & ~(UCHAR_MAX >> 1)) 10 11 void clang_analyzer_eval(int); 12 void clang_analyzer_warnIfReached(); 13 14 int getInt(); 15 16 void zeroImpliesEquality(int a, int b) { 17 clang_analyzer_eval((a - b) == 0); // expected-warning{{UNKNOWN}} 18 if ((a - b) == 0) { 19 clang_analyzer_eval(b != a); // expected-warning{{FALSE}} 20 clang_analyzer_eval(b == a); // expected-warning{{TRUE}} 21 clang_analyzer_eval(!(a != b)); // expected-warning{{TRUE}} 22 clang_analyzer_eval(!(b == a)); // expected-warning{{FALSE}} 23 return; 24 } 25 clang_analyzer_eval((a - b) == 0); // expected-warning{{FALSE}} 26 clang_analyzer_eval(b == a); // expected-warning{{FALSE}} 27 clang_analyzer_eval(b != a); // expected-warning{{TRUE}} 28 } 29 30 void zeroImpliesReversedEqual(int a, int b) { 31 clang_analyzer_eval((b - a) == 0); // expected-warning{{UNKNOWN}} 32 if ((b - a) == 0) { 33 clang_analyzer_eval(b != a); // expected-warning{{FALSE}} 34 clang_analyzer_eval(b == a); // expected-warning{{TRUE}} 35 return; 36 } 37 clang_analyzer_eval((b - a) == 0); // expected-warning{{FALSE}} 38 clang_analyzer_eval(b == a); // expected-warning{{FALSE}} 39 clang_analyzer_eval(b != a); // expected-warning{{TRUE}} 40 } 41 42 void canonicalEqual(int a, int b) { 43 clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}} 44 if (a == b) { 45 clang_analyzer_eval(b == a); // expected-warning{{TRUE}} 46 return; 47 } 48 clang_analyzer_eval(a == b); // expected-warning{{FALSE}} 49 clang_analyzer_eval(b == a); // expected-warning{{FALSE}} 50 } 51 52 void test(int a, int b, int c, int d) { 53 if (a == b && c == d) { 54 if (a == 0 && b == d) { 55 clang_analyzer_eval(c == 0); // expected-warning{{TRUE}} 56 } 57 c = 10; 58 if (b == d) { 59 clang_analyzer_eval(c == 10); // expected-warning{{TRUE}} 60 clang_analyzer_eval(d == 10); // expected-warning{{UNKNOWN}} 61 // expected-warning@-1{{FALSE}} 62 clang_analyzer_eval(b == a); // expected-warning{{TRUE}} 63 clang_analyzer_eval(a == d); // expected-warning{{TRUE}} 64 65 b = getInt(); 66 clang_analyzer_eval(a == d); // expected-warning{{TRUE}} 67 clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}} 68 } 69 } 70 71 if (a != b && b == c) { 72 if (c == 42) { 73 clang_analyzer_eval(b == 42); // expected-warning{{TRUE}} 74 clang_analyzer_eval(a != 42); // expected-warning{{TRUE}} 75 } 76 } 77 } 78 79 void testIntersection(int a, int b, int c) { 80 if (a < 42 && b > 15 && c >= 25 && c <= 30) { 81 if (a != b) 82 return; 83 84 clang_analyzer_eval(a > 15); // expected-warning{{TRUE}} 85 clang_analyzer_eval(b < 42); // expected-warning{{TRUE}} 86 clang_analyzer_eval(a <= 30); // expected-warning{{UNKNOWN}} 87 88 if (c == b) { 89 // For all equal symbols, we should track the minimal common range. 90 // 91 // Also, it should be noted that c is dead at this point, but the 92 // constraint initially associated with c is still around. 93 clang_analyzer_eval(a >= 25 && a <= 30); // expected-warning{{TRUE}} 94 clang_analyzer_eval(b >= 25 && b <= 30); // expected-warning{{TRUE}} 95 } 96 } 97 } 98 99 void testPromotion(int a, char b) { 100 if (b > 10) { 101 if (a == b) { 102 // FIXME: support transferring char ranges onto equal int symbols 103 // when char is promoted to int 104 clang_analyzer_eval(a > 10); // expected-warning{{UNKNOWN}} 105 clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}} 106 } 107 } 108 } 109 110 void testPromotionOnlyTypes(int a, char b) { 111 if (a == b) { 112 // FIXME: support transferring char ranges onto equal int symbols 113 // when char is promoted to int 114 clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}} 115 } 116 } 117 118 void testDowncast(int a, unsigned char b) { 119 if (a <= -10) { 120 if ((unsigned char)a == b) { 121 // Even though ranges for a and b do not intersect, 122 // ranges for (unsigned char)a and b do. 123 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 124 } 125 if (a == b) { 126 // FIXME: This case on the other hand is different, it shouldn't be 127 // reachable. However, the corrent symbolic information available 128 // to the solver doesn't allow it to distinguish this expression 129 // from the previous one. 130 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 131 } 132 } 133 } 134 135 void testPointers(int *a, int *b, int *c, int *d) { 136 if (a == b && c == d) { 137 if (a == NULL && b == d) { 138 clang_analyzer_eval(c == NULL); // expected-warning{{TRUE}} 139 } 140 } 141 142 if (a != b && b == c) { 143 if (c == NULL) { 144 clang_analyzer_eval(a != NULL); // expected-warning{{TRUE}} 145 } 146 } 147 } 148 149 void testDisequalitiesAfter(int a, int b, int c) { 150 if (a >= 10 && b <= 42) { 151 if (a == b && c == 15 && c != a) { 152 clang_analyzer_eval(b != c); // expected-warning{{TRUE}} 153 clang_analyzer_eval(a != 15); // expected-warning{{TRUE}} 154 clang_analyzer_eval(b != 15); // expected-warning{{TRUE}} 155 clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}} 156 clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}} 157 } 158 } 159 } 160 161 void testDisequalitiesBefore(int a, int b, int c) { 162 if (a >= 10 && b <= 42 && c == 15) { 163 if (a == b && c != a) { 164 clang_analyzer_eval(b != c); // expected-warning{{TRUE}} 165 clang_analyzer_eval(a != 15); // expected-warning{{TRUE}} 166 clang_analyzer_eval(b != 15); // expected-warning{{TRUE}} 167 clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}} 168 clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}} 169 } 170 } 171 } 172 173 void avoidInfeasibleConstraintsForClasses(int a, int b) { 174 if (a >= 0 && a <= 10 && b >= 20 && b <= 50) { 175 if ((b - a) == 0) { 176 clang_analyzer_warnIfReached(); // no warning 177 } 178 if (a == b) { 179 clang_analyzer_warnIfReached(); // no warning 180 } 181 if (a != b) { 182 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 183 } else { 184 clang_analyzer_warnIfReached(); // no warning 185 } 186 } 187 } 188 189 void avoidInfeasibleConstraintforGT(int a, int b) { 190 int c = b - a; 191 if (c <= 0) 192 return; 193 // c > 0 194 // b - a > 0 195 // b > a 196 if (a != b) { 197 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 198 return; 199 } 200 clang_analyzer_warnIfReached(); // no warning 201 // a == b 202 if (c < 0) 203 ; 204 } 205 206 void avoidInfeasibleConstraintforLT(int a, int b) { 207 int c = b - a; 208 if (c >= 0) 209 return; 210 // c < 0 211 // b - a < 0 212 // b < a 213 if (a != b) { 214 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 215 return; 216 } 217 clang_analyzer_warnIfReached(); // no warning 218 // a == b 219 if (c < 0) 220 ; 221 } 222 223 void implyDisequalityFromGT(int a, int b) { 224 if (a > b) { 225 clang_analyzer_eval(a == b); // expected-warning{{FALSE}} 226 clang_analyzer_eval(a != b); // expected-warning{{TRUE}} 227 } 228 } 229 230 void implyDisequalityFromLT(int a, int b) { 231 if (a < b) { 232 clang_analyzer_eval(a == b); // expected-warning{{FALSE}} 233 clang_analyzer_eval(a != b); // expected-warning{{TRUE}} 234 } 235 } 236