Clang Project

clang_source_code/test/CodeGenCXX/catch-implicit-integer-truncations.cpp
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,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER
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,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
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,CHECK-SANITIZE-TRAP
5
6extern "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
16unsigned 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
26unsigned 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
43unsigned 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
50unsigned 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
57signed 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
64signed 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
74unsigned 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
81signed 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
88unsigned 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
95signed 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
104using UnsignedChar = unsigned char;
105using SignedChar = signed char;
106using UnsignedInt = unsigned int;
107using SignedInt = signed int;
108
109// CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_char
110unsigned 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
117unsigned 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
124signed 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
131signed 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
141unsigned 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
148signed 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
155unsigned 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
162signed 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
172unsigned 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
179unsigned 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
186signed 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
193signed 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
203unsigned 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
210signed 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
217unsigned 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
224signed 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
237template <typename a>
238a b(a c, const a &d) {
239  if (d)
240    ;
241  return c;
242}
243
244extern "C" { // Disable name mangling.
245
246// CHECK-LABEL: @false_positive_with_MaterializeTemporaryExpr
247int 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