llvm-project/clang/test/Analysis/conversion.c

254 lines
5.5 KiB
C

// RUN: %clang_analyze_cc1 %s \
// RUN: -Wno-conversion -Wno-tautological-constant-compare \
// RUN: -analyzer-checker=core,apiModeling,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 apiModeling.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;
}