| // RUN: %clang_analyze_cc1 %s \ | |
| // RUN: -Wno-conversion -Wno-tautological-constant-compare \ | |
| // RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions,alpha.core.Conversion \ | |
| // RUN: -verify | |
| unsigned char U8; | |
| signed char S8; | |
| void assign(unsigned U, signed S) { | |
| if (S < -10) | |
| U8 = S; // expected-warning {{Loss of sign in implicit conversion}} | |
| if (U > 300) | |
| S8 = U; // expected-warning {{Loss of precision in implicit conversion}} | |
| if (S > 10) | |
| U8 = S; // no-warning | |
| if (U < 200) | |
| S8 = U; // no-warning | |
| } | |
| void addAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -100; | |
| U8 += L; // expected-warning {{Loss of precision in implicit conversion}} | |
| L += I; // no-warning | |
| } | |
| void subAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -100; | |
| U8 -= L; // expected-warning {{Loss of precision in implicit conversion}} | |
| L -= I; // no-warning | |
| } | |
| void mulAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -1; | |
| U8 *= L; // expected-warning {{Loss of precision in implicit conversion}} | |
| L *= I; // expected-warning {{Loss of sign in implicit conversion}} | |
| I = 10; | |
| L *= I; // no-warning | |
| } | |
| void divAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -1; | |
| U8 /= L; // no-warning | |
| L /= I; // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| void remAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -1; | |
| U8 %= L; // no-warning | |
| L %= I; // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| void andAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -1; | |
| U8 &= L; // no-warning | |
| L &= I; // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| void orAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -1; | |
| U8 |= L; // expected-warning {{Loss of precision in implicit conversion}} | |
| L |= I; // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| void xorAssign(void) { | |
| unsigned long L = 1000; | |
| int I = -1; | |
| U8 ^= L; // expected-warning {{Loss of precision in implicit conversion}} | |
| L ^= I; // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| void init1(void) { | |
| long long A = 1LL << 60; | |
| short X = A; // expected-warning {{Loss of precision in implicit conversion}} | |
| } | |
| void relational(unsigned U, signed S) { | |
| if (S > 10) { | |
| if (U < S) { // no-warning | |
| } | |
| } | |
| if (S < -10) { | |
| if (U < S) { // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| } | |
| } | |
| void multiplication(unsigned U, signed S) { | |
| if (S > 5) | |
| S = U * S; // no-warning | |
| if (S < -10) | |
| S = U * S; // expected-warning {{Loss of sign}} | |
| } | |
| void division(unsigned U, signed S) { | |
| if (S > 5) | |
| S = U / S; // no-warning | |
| if (S < -10) | |
| S = U / S; // expected-warning {{Loss of sign}} | |
| } | |
| void f(unsigned x) {} | |
| void g(unsigned x) {} | |
| void functioncall1(void) { | |
| long x = -1; | |
| int y = 0; | |
| f(x); // expected-warning {{Loss of sign in implicit conversion}} | |
| f(y); | |
| } | |
| void functioncall2(int x, int y) { | |
| if (x < 0) | |
| f(x); // expected-warning {{Loss of sign in implicit conversion}} | |
| f(y); | |
| f(x); // expected-warning {{Loss of sign in implicit conversion}} | |
| } | |
| void dontwarn1(unsigned U, signed S) { | |
| U8 = S; // It might be known that S is always 0x00-0xff. | |
| S8 = U; // It might be known that U is always 0x00-0xff. | |
| U8 = -1; // Explicit conversion. | |
| S8 = ~0U; // Explicit conversion. | |
| if (U > 300) | |
| U8 &= U; // No loss of precision since there is &=. | |
| } | |
| void dontwarn2(unsigned int U) { | |
| if (U <= 4294967295) { | |
| } | |
| if (U <= (2147483647 * 2U + 1U)) { | |
| } | |
| } | |
| void dontwarn3(int X) { | |
| S8 = X ? 'a' : 'b'; | |
| } | |
| // don't warn for macros | |
| #define DOSTUFF ({ unsigned X = 1000; U8 = X; }) | |
| void dontwarn4(void) { | |
| DOSTUFF; | |
| } | |
| void dontwarn5(void) { | |
| unsigned char c1 = 'A'; | |
| c1 = (c1 >= 'A' && c1 <= 'Z') ? c1 - 'A' + 'a' : c1; | |
| unsigned char c2 = 0; | |
| c2 = (c2 >= 'A' && c2 <= 'Z') ? c2 - 'A' + 'a' : c2; | |
| unsigned char c3 = 'Z'; | |
| c3 = (c3 >= 'A' && c3 <= 'Z') ? c3 - 'A' + 'a' : c3; | |
| unsigned char c4 = 'a'; | |
| c4 = (c4 >= 'A' && c4 <= 'Z') ? c4 - 'A' + 'a' : c4; | |
| unsigned char c5 = '@'; | |
| c5 = (c5 >= 'A' && c5 <= 'Z') ? c5 - 'A' + 'a' : c5; | |
| } | |
| void dontwarn6(void) { | |
| int x = ~0; | |
| unsigned y = ~0; | |
| } | |
| void dontwarn7(unsigned x) { | |
| if (x == (unsigned)-1) { | |
| } | |
| } | |
| void dontwarn8(void) { | |
| unsigned x = (unsigned)-1; | |
| } | |
| unsigned dontwarn9(void) { | |
| return ~0; | |
| } | |
| char dontwarn10(long long x) { | |
| long long y = 42; | |
| y += x; | |
| return y == 42; | |
| } | |
| // C library functions, handled via unix.StdCLibraryFunctions | |
| int isascii(int c); | |
| void libraryFunction1(void) { | |
| char kb2[5]; | |
| int X = 1000; | |
| if (isascii(X)) { | |
| kb2[0] = X; // no-warning | |
| } | |
| } | |
| typedef struct FILE {} FILE; int getc(FILE *stream); | |
| # define EOF (-1) | |
| char reply_string[8192]; | |
| FILE *cin; | |
| extern int dostuff(void); | |
| int libraryFunction2(void) { | |
| int c, n; | |
| int dig; | |
| char *cp = reply_string; | |
| int pflag = 0; | |
| int code; | |
| for (;;) { | |
| dig = n = code = 0; | |
| while ((c = getc(cin)) != '\n') { | |
| if (dig < 4 && dostuff()) | |
| code = code * 10 + (c - '0'); | |
| if (!pflag && code == 227) | |
| pflag = 1; | |
| if (n == 0) | |
| n = c; | |
| if (c == EOF) | |
| return(4); | |
| if (cp < &reply_string[sizeof(reply_string) - 1]) | |
| *cp++ = c; // no-warning | |
| } | |
| } | |
| } | |
| double floating_point(long long a, int b) { | |
| if (a > 1LL << 55) { | |
| double r = a; // expected-warning {{Loss of precision}} | |
| return r; | |
| } else if (b > 1 << 25) { | |
| float f = b; // expected-warning {{Loss of precision}} | |
| return f; | |
| } | |
| return 137; | |
| } | |
| double floating_point2(void) { | |
| int a = 1 << 24; | |
| long long b = 1LL << 53; | |
| float f = a; // no-warning | |
| double d = b; // no-warning | |
| return d - f; | |
| } | |
| int floating_point_3(unsigned long long a) { | |
| double b = a; // no-warning | |
| return 42; | |
| } |