1 // RUN: %clang_analyze_cc1 %s \ 2 // RUN: -Wno-conversion -Wno-tautological-constant-compare \ 3 // RUN: -analyzer-checker=core,apiModeling,alpha.core.Conversion \ 4 // RUN: -verify 5 6 unsigned char U8; 7 signed char S8; 8 9 void assign(unsigned U, signed S) { 10 if (S < -10) 11 U8 = S; // expected-warning {{Loss of sign in implicit conversion}} 12 if (U > 300) 13 S8 = U; // expected-warning {{Loss of precision in implicit conversion}} 14 if (S > 10) 15 U8 = S; // no-warning 16 if (U < 200) 17 S8 = U; // no-warning 18 } 19 20 void addAssign() { 21 unsigned long L = 1000; 22 int I = -100; 23 U8 += L; // expected-warning {{Loss of precision in implicit conversion}} 24 L += I; // no-warning 25 } 26 27 void subAssign() { 28 unsigned long L = 1000; 29 int I = -100; 30 U8 -= L; // expected-warning {{Loss of precision in implicit conversion}} 31 L -= I; // no-warning 32 } 33 34 void mulAssign() { 35 unsigned long L = 1000; 36 int I = -1; 37 U8 *= L; // expected-warning {{Loss of precision in implicit conversion}} 38 L *= I; // expected-warning {{Loss of sign in implicit conversion}} 39 I = 10; 40 L *= I; // no-warning 41 } 42 43 void divAssign() { 44 unsigned long L = 1000; 45 int I = -1; 46 U8 /= L; // no-warning 47 L /= I; // expected-warning {{Loss of sign in implicit conversion}} 48 } 49 50 void remAssign() { 51 unsigned long L = 1000; 52 int I = -1; 53 U8 %= L; // no-warning 54 L %= I; // expected-warning {{Loss of sign in implicit conversion}} 55 } 56 57 void andAssign() { 58 unsigned long L = 1000; 59 int I = -1; 60 U8 &= L; // no-warning 61 L &= I; // expected-warning {{Loss of sign in implicit conversion}} 62 } 63 64 void orAssign() { 65 unsigned long L = 1000; 66 int I = -1; 67 U8 |= L; // expected-warning {{Loss of precision in implicit conversion}} 68 L |= I; // expected-warning {{Loss of sign in implicit conversion}} 69 } 70 71 void xorAssign() { 72 unsigned long L = 1000; 73 int I = -1; 74 U8 ^= L; // expected-warning {{Loss of precision in implicit conversion}} 75 L ^= I; // expected-warning {{Loss of sign in implicit conversion}} 76 } 77 78 void init1() { 79 long long A = 1LL << 60; 80 short X = A; // expected-warning {{Loss of precision in implicit conversion}} 81 } 82 83 void relational(unsigned U, signed S) { 84 if (S > 10) { 85 if (U < S) { // no-warning 86 } 87 } 88 if (S < -10) { 89 if (U < S) { // expected-warning {{Loss of sign in implicit conversion}} 90 } 91 } 92 } 93 94 void multiplication(unsigned U, signed S) { 95 if (S > 5) 96 S = U * S; // no-warning 97 if (S < -10) 98 S = U * S; // expected-warning {{Loss of sign}} 99 } 100 101 void division(unsigned U, signed S) { 102 if (S > 5) 103 S = U / S; // no-warning 104 if (S < -10) 105 S = U / S; // expected-warning {{Loss of sign}} 106 } 107 108 void f(unsigned x) {} 109 void g(unsigned x) {} 110 111 void functioncall1() { 112 long x = -1; 113 int y = 0; 114 f(x); // expected-warning {{Loss of sign in implicit conversion}} 115 f(y); 116 } 117 118 void functioncall2(int x, int y) { 119 if (x < 0) 120 f(x); // expected-warning {{Loss of sign in implicit conversion}} 121 f(y); 122 f(x); // expected-warning {{Loss of sign in implicit conversion}} 123 } 124 125 void dontwarn1(unsigned U, signed S) { 126 U8 = S; // It might be known that S is always 0x00-0xff. 127 S8 = U; // It might be known that U is always 0x00-0xff. 128 129 U8 = -1; // Explicit conversion. 130 S8 = ~0U; // Explicit conversion. 131 if (U > 300) 132 U8 &= U; // No loss of precision since there is &=. 133 } 134 135 void dontwarn2(unsigned int U) { 136 if (U <= 4294967295) { 137 } 138 if (U <= (2147483647 * 2U + 1U)) { 139 } 140 } 141 142 void dontwarn3(int X) { 143 S8 = X ? 'a' : 'b'; 144 } 145 146 // don't warn for macros 147 #define DOSTUFF ({ unsigned X = 1000; U8 = X; }) 148 void dontwarn4() { 149 DOSTUFF; 150 } 151 152 void dontwarn5() { 153 unsigned char c1 = 'A'; 154 c1 = (c1 >= 'A' && c1 <= 'Z') ? c1 - 'A' + 'a' : c1; 155 unsigned char c2 = 0; 156 c2 = (c2 >= 'A' && c2 <= 'Z') ? c2 - 'A' + 'a' : c2; 157 unsigned char c3 = 'Z'; 158 c3 = (c3 >= 'A' && c3 <= 'Z') ? c3 - 'A' + 'a' : c3; 159 unsigned char c4 = 'a'; 160 c4 = (c4 >= 'A' && c4 <= 'Z') ? c4 - 'A' + 'a' : c4; 161 unsigned char c5 = '@'; 162 c5 = (c5 >= 'A' && c5 <= 'Z') ? c5 - 'A' + 'a' : c5; 163 } 164 165 void dontwarn6() { 166 int x = ~0; 167 unsigned y = ~0; 168 } 169 170 void dontwarn7(unsigned x) { 171 if (x == (unsigned)-1) { 172 } 173 } 174 175 void dontwarn8() { 176 unsigned x = (unsigned)-1; 177 } 178 179 unsigned dontwarn9() { 180 return ~0; 181 } 182 183 char dontwarn10(long long x) { 184 long long y = 42; 185 y += x; 186 return y == 42; 187 } 188 189 190 // C library functions, handled via apiModeling.StdCLibraryFunctions 191 192 int isascii(int c); 193 void libraryFunction1() { 194 char kb2[5]; 195 int X = 1000; 196 if (isascii(X)) { 197 kb2[0] = X; // no-warning 198 } 199 } 200 201 202 typedef struct FILE {} FILE; int getc(FILE *stream); 203 # define EOF (-1) 204 char reply_string[8192]; 205 FILE *cin; 206 extern int dostuff(void); 207 int libraryFunction2() { 208 int c, n; 209 int dig; 210 char *cp = reply_string; 211 int pflag = 0; 212 int code; 213 214 for (;;) { 215 dig = n = code = 0; 216 while ((c = getc(cin)) != '\n') { 217 if (dig < 4 && dostuff()) 218 code = code * 10 + (c - '0'); 219 if (!pflag && code == 227) 220 pflag = 1; 221 if (n == 0) 222 n = c; 223 if (c == EOF) 224 return(4); 225 if (cp < &reply_string[sizeof(reply_string) - 1]) 226 *cp++ = c; // no-warning 227 } 228 } 229 } 230 231 double floating_point(long long a, int b) { 232 if (a > 1LL << 55) { 233 double r = a; // expected-warning {{Loss of precision}} 234 return r; 235 } else if (b > 1 << 25) { 236 float f = b; // expected-warning {{Loss of precision}} 237 return f; 238 } 239 return 137; 240 } 241 242 double floating_point2() { 243 int a = 1 << 24; 244 long long b = 1LL << 53; 245 float f = a; // no-warning 246 double d = b; // no-warning 247 return d - f; 248 } 249 250 int floating_point_3(unsigned long long a) { 251 double b = a; // no-warning 252 return 42; 253 } 254