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