xref: /llvm-project/clang/test/Analysis/conversion.c (revision c202a17d024068c70364116f2d06535d79535b30)
1 // RUN: %clang_analyze_cc1 %s \
2 // RUN:   -Wno-conversion -Wno-tautological-constant-compare \
3 // RUN:   -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions,alpha.core.Conversion \
4 // RUN:   -verify
5 
6 unsigned char U8;
7 signed char S8;
8 
assign(unsigned U,signed S)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 
addAssign(void)20 void addAssign(void) {
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 
subAssign(void)27 void subAssign(void) {
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 
mulAssign(void)34 void mulAssign(void) {
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 
divAssign(void)43 void divAssign(void) {
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 
remAssign(void)50 void remAssign(void) {
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 
andAssign(void)57 void andAssign(void) {
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 
orAssign(void)64 void orAssign(void) {
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 
xorAssign(void)71 void xorAssign(void) {
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 
init1(void)78 void init1(void) {
79   long long A = 1LL << 60;
80   short X = A; // expected-warning {{Loss of precision in implicit conversion}}
81 }
82 
relational(unsigned U,signed S)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 
multiplication(unsigned U,signed S)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 
division(unsigned U,signed S)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 
f(unsigned x)108 void f(unsigned x) {}
g(unsigned x)109 void g(unsigned x) {}
110 
functioncall1(void)111 void functioncall1(void) {
112   long x = -1;
113   int y = 0;
114   f(x); // expected-warning {{Loss of sign in implicit conversion}}
115   f(y);
116 }
117 
functioncall2(int x,int y)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 
dontwarn1(unsigned U,signed S)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 
dontwarn2(unsigned int U)135 void dontwarn2(unsigned int U) {
136   if (U <= 4294967295) {
137   }
138   if (U <= (2147483647 * 2U + 1U)) {
139   }
140 }
141 
dontwarn3(int X)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; })
dontwarn4(void)148 void dontwarn4(void) {
149   DOSTUFF;
150 }
151 
dontwarn5(void)152 void dontwarn5(void) {
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 
dontwarn6(void)165 void dontwarn6(void) {
166   int x = ~0;
167   unsigned y = ~0;
168 }
169 
dontwarn7(unsigned x)170 void dontwarn7(unsigned x) {
171   if (x == (unsigned)-1) {
172   }
173 }
174 
dontwarn8(void)175 void dontwarn8(void) {
176   unsigned x = (unsigned)-1;
177 }
178 
dontwarn9(void)179 unsigned dontwarn9(void) {
180   return ~0;
181 }
182 
dontwarn10(long long x)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 unix.StdCLibraryFunctions
191 
192 int isascii(int c);
libraryFunction1(void)193 void libraryFunction1(void) {
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);
libraryFunction2(void)207 int libraryFunction2(void) {
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 
floating_point(long long a,int b)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 
floating_point2(void)242 double floating_point2(void) {
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 
floating_point_3(unsigned long long a)250 int floating_point_3(unsigned long long a) {
251   double b = a; // no-warning
252   return 42;
253 }
254