| // RUN: %clang_analyze_cc1 -Wno-conversion -Wno-tautological-constant-compare -analyzer-checker=core,alpha.core.Conversion -verify %s |
| |
| 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() { |
| unsigned long L = 1000; |
| int I = -100; |
| U8 += L; // expected-warning {{Loss of precision in implicit conversion}} |
| L += I; // no-warning |
| } |
| |
| void subAssign() { |
| unsigned long L = 1000; |
| int I = -100; |
| U8 -= L; // expected-warning {{Loss of precision in implicit conversion}} |
| L -= I; // no-warning |
| } |
| |
| void mulAssign() { |
| 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() { |
| unsigned long L = 1000; |
| int I = -1; |
| U8 /= L; // no-warning |
| L /= I; // expected-warning {{Loss of sign in implicit conversion}} |
| } |
| |
| void remAssign() { |
| unsigned long L = 1000; |
| int I = -1; |
| U8 %= L; // no-warning |
| L %= I; // expected-warning {{Loss of sign in implicit conversion}} |
| } |
| |
| void andAssign() { |
| unsigned long L = 1000; |
| int I = -1; |
| U8 &= L; // no-warning |
| L &= I; // expected-warning {{Loss of sign in implicit conversion}} |
| } |
| |
| void orAssign() { |
| 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() { |
| 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() { |
| 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 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() { |
| DOSTUFF; |
| } |
| |
| // don't warn for calculations |
| // seen some fp. For instance: c2 = (c2 >= 'A' && c2 <= 'Z') ? c2 - 'A' + 'a' : c2; |
| // there is a todo in the checker to handle calculations |
| void dontwarn5() { |
| signed S = -32; |
| U8 = S + 10; |
| } |
| |
| |
| // false positives.. |
| |
| int isascii(int c); |
| void falsePositive1() { |
| char kb2[5]; |
| int X = 1000; |
| if (isascii(X)) { |
| // FIXME: should not warn here: |
| kb2[0] = X; // expected-warning {{Loss of precision}} |
| } |
| } |
| |
| |
| typedef struct FILE {} FILE; int getc(FILE *stream); |
| # define EOF (-1) |
| char reply_string[8192]; |
| FILE *cin; |
| extern int dostuff (void); |
| int falsePositive2() { |
| 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]) |
| // FIXME: should not warn here: |
| *cp++ = c; // expected-warning {{Loss of precision}} |
| } |
| } |
| } |
| |