1 // RUN: %clang_analyze_cc1 -Wno-conversion -Wno-tautological-constant-compare -analyzer-checker=core,alpha.core.Conversion -verify %s
2 
3 unsigned char U8;
4 signed char S8;
5 
6 void assign(unsigned U, signed S) {
7   if (S < -10)
8     U8 = S; // expected-warning {{Loss of sign in implicit conversion}}
9   if (U > 300)
10     S8 = U; // expected-warning {{Loss of precision in implicit conversion}}
11   if (S > 10)
12     U8 = S; // no-warning
13   if (U < 200)
14     S8 = U; // no-warning
15 }
16 
17 void addAssign() {
18   unsigned long L = 1000;
19   int I = -100;
20   U8 += L; // expected-warning {{Loss of precision in implicit conversion}}
21   L += I; // no-warning
22 }
23 
24 void subAssign() {
25   unsigned long L = 1000;
26   int I = -100;
27   U8 -= L; // expected-warning {{Loss of precision in implicit conversion}}
28   L -= I; // no-warning
29 }
30 
31 void mulAssign() {
32   unsigned long L = 1000;
33   int I = -1;
34   U8 *= L; // expected-warning {{Loss of precision in implicit conversion}}
35   L *= I;  // expected-warning {{Loss of sign in implicit conversion}}
36   I = 10;
37   L *= I; // no-warning
38 }
39 
40 void divAssign() {
41   unsigned long L = 1000;
42   int I = -1;
43   U8 /= L; // no-warning
44   L /= I; // expected-warning {{Loss of sign in implicit conversion}}
45 }
46 
47 void remAssign() {
48   unsigned long L = 1000;
49   int I = -1;
50   U8 %= L; // no-warning
51   L %= I; // expected-warning {{Loss of sign in implicit conversion}}
52 }
53 
54 void andAssign() {
55   unsigned long L = 1000;
56   int I = -1;
57   U8 &= L; // no-warning
58   L &= I; // expected-warning {{Loss of sign in implicit conversion}}
59 }
60 
61 void orAssign() {
62   unsigned long L = 1000;
63   int I = -1;
64   U8 |= L; // expected-warning {{Loss of precision in implicit conversion}}
65   L |= I;  // expected-warning {{Loss of sign in implicit conversion}}
66 }
67 
68 void xorAssign() {
69   unsigned long L = 1000;
70   int I = -1;
71   U8 ^= L; // expected-warning {{Loss of precision in implicit conversion}}
72   L ^= I;  // expected-warning {{Loss of sign in implicit conversion}}
73 }
74 
75 void init1() {
76   long long A = 1LL << 60;
77   short X = A; // expected-warning {{Loss of precision in implicit conversion}}
78 }
79 
80 void relational(unsigned U, signed S) {
81   if (S > 10) {
82     if (U < S) { // no-warning
83     }
84   }
85   if (S < -10) {
86     if (U < S) { // expected-warning {{Loss of sign in implicit conversion}}
87     }
88   }
89 }
90 
91 void multiplication(unsigned U, signed S) {
92   if (S > 5)
93     S = U * S; // no-warning
94   if (S < -10)
95     S = U * S; // expected-warning {{Loss of sign}}
96 }
97 
98 void division(unsigned U, signed S) {
99   if (S > 5)
100     S = U / S; // no-warning
101   if (S < -10)
102     S = U / S; // expected-warning {{Loss of sign}}
103 }
104 
105 void dontwarn1(unsigned U, signed S) {
106   U8 = S; // It might be known that S is always 0x00-0xff.
107   S8 = U; // It might be known that U is always 0x00-0xff.
108 
109   U8 = -1;  // Explicit conversion.
110   S8 = ~0U; // Explicit conversion.
111   if (U > 300)
112     U8 &= U; // No loss of precision since there is &=.
113 }
114 
115 void dontwarn2(unsigned int U) {
116   if (U <= 4294967295) {
117   }
118   if (U <= (2147483647 * 2U + 1U)) {
119   }
120 }
121 
122 void dontwarn3(int X) {
123   S8 = X ? 'a' : 'b';
124 }
125 
126 // don't warn for macros
127 #define DOSTUFF ({ unsigned X = 1000; U8 = X; })
128 void dontwarn4() {
129   DOSTUFF;
130 }
131 
132 // don't warn for calculations
133 // seen some fp. For instance:  c2 = (c2 >= 'A' && c2 <= 'Z') ? c2 - 'A' + 'a' : c2;
134 // there is a todo in the checker to handle calculations
135 void dontwarn5() {
136   signed S = -32;
137   U8 = S + 10;
138 }
139 
140 
141 // false positives..
142 
143 int isascii(int c);
144 void falsePositive1() {
145   char kb2[5];
146   int X = 1000;
147   if (isascii(X)) {
148     // FIXME: should not warn here:
149     kb2[0] = X; // expected-warning {{Loss of precision}}
150   }
151 }
152 
153 
154 typedef struct FILE {} FILE; int getc(FILE *stream);
155 # define EOF (-1)
156 char reply_string[8192];
157 FILE *cin;
158 extern int dostuff (void);
159 int falsePositive2() {
160   int c, n;
161   int dig;
162   char *cp = reply_string;
163   int pflag = 0;
164   int code;
165 
166   for (;;) {
167     dig = n = code = 0;
168     while ((c = getc(cin)) != '\n') {
169       if (dig < 4 && dostuff())
170         code = code * 10 + (c - '0');
171       if (!pflag && code == 227)
172         pflag = 1;
173       if (n == 0)
174         n = c;
175       if (c == EOF)
176         return(4);
177       if (cp < &reply_string[sizeof(reply_string) - 1])
178         // FIXME: should not warn here:
179         *cp++ = c; // expected-warning {{Loss of precision}}
180     }
181   }
182 }
183 
184