// 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; }