xref: /llvm-project/clang/test/CodeGenCXX/catch-implicit-integer-truncations.cpp (revision e3b64eb31c0e9a9f1ac4891b834d71532e545cad)
1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
2 // RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE
3 // RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE
4 // RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SANITIZE
5 
6 extern "C" { // Disable name mangling.
7 
8 // ========================================================================== //
9 // Check that explicit cast does not interfere with implicit conversion
10 // ========================================================================== //
11 // These contain one implicit truncating conversion, and one explicit truncating cast.
12 // We want to make sure that we still diagnose the implicit conversion.
13 
14 // Implicit truncation after explicit truncation.
15 // CHECK-LABEL: @explicit_cast_interference0
explicit_cast_interference0(unsigned int c)16 unsigned char explicit_cast_interference0(unsigned int c) {
17   // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize
18   // CHECK-SANITIZE: call
19   // CHECK-SANITIZE-NOT: call
20   // CHECK: }
21   return (unsigned short)c;
22 }
23 
24 // Implicit truncation before explicit truncation.
25 // CHECK-LABEL: @explicit_cast_interference1
explicit_cast_interference1(unsigned int c)26 unsigned char explicit_cast_interference1(unsigned int c) {
27   // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize
28   // CHECK-SANITIZE: call
29   // CHECK-SANITIZE-NOT: call
30   // CHECK: }
31   unsigned short b;
32   return (unsigned char)(b = c);
33 }
34 
35 // ========================================================================== //
36 // The expected true-negatives.
37 // ========================================================================== //
38 
39 // Explicit truncating casts.
40 // ========================================================================== //
41 
42 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
explicit_unsigned_int_to_unsigned_char(unsigned int src)43 unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) {
44   // CHECK-SANITIZE-NOT: call
45   // CHECK: }
46   return (unsigned char)src;
47 }
48 
49 // CHECK-LABEL: @explicit_signed_int_to_unsigned_char
explicit_signed_int_to_unsigned_char(signed int src)50 unsigned char explicit_signed_int_to_unsigned_char(signed int src) {
51   // CHECK-SANITIZE-NOT: call
52   // CHECK: }
53   return (unsigned char)src;
54 }
55 
56 // CHECK-LABEL: @explicit_unsigned_int_to_signed_char
explicit_unsigned_int_to_signed_char(unsigned int src)57 signed char explicit_unsigned_int_to_signed_char(unsigned int src) {
58   // CHECK-SANITIZE-NOT: call
59   // CHECK: }
60   return (signed char)src;
61 }
62 
63 // CHECK-LABEL: @explicit_signed_int_to_signed_char
explicit_signed_int_to_signed_char(signed int src)64 signed char explicit_signed_int_to_signed_char(signed int src) {
65   // CHECK-SANITIZE-NOT: call
66   // CHECK: }
67   return (signed char)src;
68 }
69 
70 // Explicit NOP casts.
71 // ========================================================================== //
72 
73 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
explicit_unsigned_int_to_unsigned_int(unsigned int src)74 unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {
75   // CHECK-SANITIZE-NOT: call
76   // CHECK: }
77   return (unsigned int)src;
78 }
79 
80 // CHECK-LABEL: @explicit_signed_int_to_signed_int
explicit_signed_int_to_signed_int(signed int src)81 signed int explicit_signed_int_to_signed_int(signed int src) {
82   // CHECK-SANITIZE-NOT: call
83   // CHECK: }
84   return (signed int)src;
85 }
86 
87 // CHECK-LABEL: @explicit_unsigned_char_to_signed_char
explicit_unsigned_char_to_signed_char(unsigned char src)88 unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) {
89   // CHECK-SANITIZE-NOT: call
90   // CHECK: }
91   return (unsigned char)src;
92 }
93 
94 // CHECK-LABEL: @explicit_signed_char_to_signed_char
explicit_signed_char_to_signed_char(signed char src)95 signed char explicit_signed_char_to_signed_char(signed char src) {
96   // CHECK-SANITIZE-NOT: call
97   // CHECK: }
98   return (signed char)src;
99 }
100 
101 // Explicit functional truncating casts.
102 // ========================================================================== //
103 
104 using UnsignedChar = unsigned char;
105 using SignedChar = signed char;
106 using UnsignedInt = unsigned int;
107 using SignedInt = signed int;
108 
109 // CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_char
explicit_functional_unsigned_int_to_unsigned_char(unsigned int src)110 unsigned char explicit_functional_unsigned_int_to_unsigned_char(unsigned int src) {
111   // CHECK-SANITIZE-NOT: call
112   // CHECK: }
113   return UnsignedChar(src);
114 }
115 
116 // CHECK-LABEL: @explicit_functional_signed_int_to_unsigned_char
explicit_functional_signed_int_to_unsigned_char(signed int src)117 unsigned char explicit_functional_signed_int_to_unsigned_char(signed int src) {
118   // CHECK-SANITIZE-NOT: call
119   // CHECK: }
120   return UnsignedChar(src);
121 }
122 
123 // CHECK-LABEL: @explicit_functional_unsigned_int_to_signed_char
explicit_functional_unsigned_int_to_signed_char(unsigned int src)124 signed char explicit_functional_unsigned_int_to_signed_char(unsigned int src) {
125   // CHECK-SANITIZE-NOT: call
126   // CHECK: }
127   return SignedChar(src);
128 }
129 
130 // CHECK-LABEL: @explicit_functional_signed_int_to_signed_char
explicit_functional_signed_int_to_signed_char(signed int src)131 signed char explicit_functional_signed_int_to_signed_char(signed int src) {
132   // CHECK-SANITIZE-NOT: call
133   // CHECK: }
134   return SignedChar(src);
135 }
136 
137 // Explicit functional NOP casts.
138 // ========================================================================== //
139 
140 // CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_int
explicit_functional_unsigned_int_to_unsigned_int(unsigned int src)141 unsigned int explicit_functional_unsigned_int_to_unsigned_int(unsigned int src) {
142   // CHECK-SANITIZE-NOT: call
143   // CHECK: }
144   return UnsignedInt(src);
145 }
146 
147 // CHECK-LABEL: @explicit_functional_signed_int_to_signed_int
explicit_functional_signed_int_to_signed_int(signed int src)148 signed int explicit_functional_signed_int_to_signed_int(signed int src) {
149   // CHECK-SANITIZE-NOT: call
150   // CHECK: }
151   return SignedInt(src);
152 }
153 
154 // CHECK-LABEL: @explicit_functional_unsigned_char_to_signed_char
explicit_functional_unsigned_char_to_signed_char(unsigned char src)155 unsigned char explicit_functional_unsigned_char_to_signed_char(unsigned char src) {
156   // CHECK-SANITIZE-NOT: call
157   // CHECK: }
158   return UnsignedChar(src);
159 }
160 
161 // CHECK-LABEL: @explicit_functional_signed_char_to_signed_char
explicit_functional_signed_char_to_signed_char(signed char src)162 signed char explicit_functional_signed_char_to_signed_char(signed char src) {
163   // CHECK-SANITIZE-NOT: call
164   // CHECK: }
165   return SignedChar(src);
166 }
167 
168 // Explicit C++-style casts truncating casts.
169 // ========================================================================== //
170 
171 // CHECK-LABEL: @explicit_cppstyleunsigned_int_to_unsigned_char
explicit_cppstyleunsigned_int_to_unsigned_char(unsigned int src)172 unsigned char explicit_cppstyleunsigned_int_to_unsigned_char(unsigned int src) {
173   // CHECK-SANITIZE-NOT: call
174   // CHECK: }
175   return static_cast<unsigned char>(src);
176 }
177 
178 // CHECK-LABEL: @explicit_cppstylesigned_int_to_unsigned_char
explicit_cppstylesigned_int_to_unsigned_char(signed int src)179 unsigned char explicit_cppstylesigned_int_to_unsigned_char(signed int src) {
180   // CHECK-SANITIZE-NOT: call
181   // CHECK: }
182   return static_cast<unsigned char>(src);
183 }
184 
185 // CHECK-LABEL: @explicit_cppstyleunsigned_int_to_signed_char
explicit_cppstyleunsigned_int_to_signed_char(unsigned int src)186 signed char explicit_cppstyleunsigned_int_to_signed_char(unsigned int src) {
187   // CHECK-SANITIZE-NOT: call
188   // CHECK: }
189   return static_cast<signed char>(src);
190 }
191 
192 // CHECK-LABEL: @explicit_cppstylesigned_int_to_signed_char
explicit_cppstylesigned_int_to_signed_char(signed int src)193 signed char explicit_cppstylesigned_int_to_signed_char(signed int src) {
194   // CHECK-SANITIZE-NOT: call
195   // CHECK: }
196   return static_cast<signed char>(src);
197 }
198 
199 // Explicit C++-style casts NOP casts.
200 // ========================================================================== //
201 
202 // CHECK-LABEL: @explicit_cppstyleunsigned_int_to_unsigned_int
explicit_cppstyleunsigned_int_to_unsigned_int(unsigned int src)203 unsigned int explicit_cppstyleunsigned_int_to_unsigned_int(unsigned int src) {
204   // CHECK-SANITIZE-NOT: call
205   // CHECK: }
206   return static_cast<unsigned int>(src);
207 }
208 
209 // CHECK-LABEL: @explicit_cppstylesigned_int_to_signed_int
explicit_cppstylesigned_int_to_signed_int(signed int src)210 signed int explicit_cppstylesigned_int_to_signed_int(signed int src) {
211   // CHECK-SANITIZE-NOT: call
212   // CHECK: }
213   return static_cast<signed int>(src);
214 }
215 
216 // CHECK-LABEL: @explicit_cppstyleunsigned_char_to_signed_char
explicit_cppstyleunsigned_char_to_signed_char(unsigned char src)217 unsigned char explicit_cppstyleunsigned_char_to_signed_char(unsigned char src) {
218   // CHECK-SANITIZE-NOT: call
219   // CHECK: }
220   return static_cast<unsigned char>(src);
221 }
222 
223 // CHECK-LABEL: @explicit_cppstylesigned_char_to_signed_char
explicit_cppstylesigned_char_to_signed_char(signed char src)224 signed char explicit_cppstylesigned_char_to_signed_char(signed char src) {
225   // CHECK-SANITIZE-NOT: call
226   // CHECK: }
227   return static_cast<signed char>(src);
228 }
229 
230 } // extern "C"
231 
232 // ---------------------------------------------------------------------------//
233 // A problematic true-negative involving simple C++ code.
234 // The problem is tha the NoOp ExplicitCast is directly within MaterializeTemporaryExpr(),
235 // so a special care is neeeded.
236 // See https://reviews.llvm.org/D48958#1161345
237 template <typename a>
b(a c,const a & d)238 a b(a c, const a &d) {
239   if (d)
240     ;
241   return c;
242 }
243 
244 extern "C" { // Disable name mangling.
245 
246 // CHECK-LABEL: @false_positive_with_MaterializeTemporaryExpr
false_positive_with_MaterializeTemporaryExpr()247 int false_positive_with_MaterializeTemporaryExpr() {
248   // CHECK-SANITIZE-NOT: call{{.*}}ubsan
249   // CHECK: }
250   int e = b<unsigned>(4, static_cast<unsigned>(4294967296));
251   return e;
252 }
253 
254 // ---------------------------------------------------------------------------//
255 
256 } // extern "C"
257