1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
2*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN
3*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL
4f4a2713aSLionel Sambuc
5f4a2713aSLionel Sambuc struct S {
6f4a2713aSLionel Sambuc double d;
7f4a2713aSLionel Sambuc int a, b;
8f4a2713aSLionel Sambuc virtual int f();
9f4a2713aSLionel Sambuc };
10f4a2713aSLionel Sambuc
11*0a6a1f1dSLionel Sambuc // Check that type descriptor global is not modified by ASan.
12*0a6a1f1dSLionel Sambuc // CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" }
13*0a6a1f1dSLionel Sambuc
14*0a6a1f1dSLionel Sambuc // Check that type mismatch handler is not modified by ASan.
15*0a6a1f1dSLionel Sambuc // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} }
16*0a6a1f1dSLionel Sambuc
17f4a2713aSLionel Sambuc struct T : S {};
18f4a2713aSLionel Sambuc
19*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z17reference_binding
reference_binding(int * p,S * q)20f4a2713aSLionel Sambuc void reference_binding(int *p, S *q) {
21f4a2713aSLionel Sambuc // C++ core issue 453: If an lvalue to which a reference is directly bound
22f4a2713aSLionel Sambuc // designates neither an existing object or function of an appropriate type,
23f4a2713aSLionel Sambuc // nor a region of storage of suitable size and alignment to contain an object
24f4a2713aSLionel Sambuc // of the reference's type, the behavior is undefined.
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambuc // CHECK: icmp ne {{.*}}, null
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64
29f4a2713aSLionel Sambuc // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4
30f4a2713aSLionel Sambuc
31f4a2713aSLionel Sambuc // CHECK: %[[PTRINT:.*]] = ptrtoint
32f4a2713aSLionel Sambuc // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3
33f4a2713aSLionel Sambuc // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
34f4a2713aSLionel Sambuc int &r = *p;
35f4a2713aSLionel Sambuc
36f4a2713aSLionel Sambuc // A reference is not required to refer to an object within its lifetime.
37f4a2713aSLionel Sambuc // CHECK-NOT: __ubsan_handle_dynamic_type_cache_miss
38f4a2713aSLionel Sambuc S &r2 = *q;
39f4a2713aSLionel Sambuc }
40f4a2713aSLionel Sambuc
41*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z13member_access
42*0a6a1f1dSLionel Sambuc // CHECK-ASAN-LABEL: @_Z13member_access
member_access(S * p)43f4a2713aSLionel Sambuc void member_access(S *p) {
44f4a2713aSLionel Sambuc // (1a) Check 'p' is appropriately sized and aligned for member access.
45f4a2713aSLionel Sambuc
46f4a2713aSLionel Sambuc // CHECK: icmp ne {{.*}}, null
47f4a2713aSLionel Sambuc
48f4a2713aSLionel Sambuc // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64
49f4a2713aSLionel Sambuc // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24
50f4a2713aSLionel Sambuc
51f4a2713aSLionel Sambuc // CHECK: %[[PTRINT:.*]] = ptrtoint
52f4a2713aSLionel Sambuc // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7
53f4a2713aSLionel Sambuc // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
54f4a2713aSLionel Sambuc
55f4a2713aSLionel Sambuc // (1b) Check that 'p' actually points to an 'S'.
56f4a2713aSLionel Sambuc
57f4a2713aSLionel Sambuc // CHECK: %[[VPTRADDR:.*]] = bitcast {{.*}} to i64*
58f4a2713aSLionel Sambuc // CHECK-NEXT: %[[VPTR:.*]] = load i64* %[[VPTRADDR]]
59f4a2713aSLionel Sambuc //
60f4a2713aSLionel Sambuc // hash_16_bytes:
61f4a2713aSLionel Sambuc //
62f4a2713aSLionel Sambuc // If this number changes, it indicates that either the mangled name of ::S
63f4a2713aSLionel Sambuc // has changed, or that LLVM's hashing function has changed. The latter case
64f4a2713aSLionel Sambuc // is OK if the hashing function is still stable.
65f4a2713aSLionel Sambuc //
66f4a2713aSLionel Sambuc // The two hash values are for 64- and 32-bit Clang binaries, respectively.
67f4a2713aSLionel Sambuc // FIXME: We should produce a 64-bit value either way.
68f4a2713aSLionel Sambuc //
69f4a2713aSLionel Sambuc // CHECK-NEXT: xor i64 {{-4030275160588942838|2562089159}}, %[[VPTR]]
70f4a2713aSLionel Sambuc // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023
71f4a2713aSLionel Sambuc // CHECK-NEXT: lshr i64 {{.*}}, 47
72f4a2713aSLionel Sambuc // CHECK-NEXT: xor i64
73f4a2713aSLionel Sambuc // CHECK-NEXT: xor i64 %[[VPTR]]
74f4a2713aSLionel Sambuc // CHECK-NEXT: mul i64 {{.*}}, -7070675565921424023
75f4a2713aSLionel Sambuc // CHECK-NEXT: lshr i64 {{.*}}, 47
76f4a2713aSLionel Sambuc // CHECK-NEXT: xor i64
77f4a2713aSLionel Sambuc // CHECK-NEXT: %[[HASH:.*]] = mul i64 {{.*}}, -7070675565921424023
78f4a2713aSLionel Sambuc //
79f4a2713aSLionel Sambuc // Check the hash against the table:
80f4a2713aSLionel Sambuc //
81f4a2713aSLionel Sambuc // CHECK-NEXT: %[[IDX:.*]] = and i64 %{{.*}}, 127
82f4a2713aSLionel Sambuc // CHECK-NEXT: getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %[[IDX]]
83f4a2713aSLionel Sambuc // CHECK-NEXT: %[[CACHEVAL:.*]] = load i64*
84f4a2713aSLionel Sambuc // CHECK-NEXT: icmp eq i64 %[[CACHEVAL]], %[[HASH]]
85f4a2713aSLionel Sambuc // CHECK-NEXT: br i1
86f4a2713aSLionel Sambuc
87f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %[[HASH]])
88f4a2713aSLionel Sambuc // CHECK-NOT: unreachable
89f4a2713aSLionel Sambuc // CHECK: {{.*}}:
90f4a2713aSLionel Sambuc
91f4a2713aSLionel Sambuc // (2) Check 'p->b' is appropriately sized and aligned for a load.
92f4a2713aSLionel Sambuc
93f4a2713aSLionel Sambuc // FIXME: Suppress this in the trivial case of a member access, because we
94f4a2713aSLionel Sambuc // know we've just checked the member access expression itself.
95f4a2713aSLionel Sambuc
96f4a2713aSLionel Sambuc // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64
97f4a2713aSLionel Sambuc // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4
98f4a2713aSLionel Sambuc
99f4a2713aSLionel Sambuc // CHECK: %[[PTRINT:.*]] = ptrtoint
100f4a2713aSLionel Sambuc // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3
101f4a2713aSLionel Sambuc // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
102f4a2713aSLionel Sambuc int k = p->b;
103f4a2713aSLionel Sambuc
104f4a2713aSLionel Sambuc // (3a) Check 'p' is appropriately sized and aligned for member function call.
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambuc // CHECK: icmp ne {{.*}}, null
107f4a2713aSLionel Sambuc
108f4a2713aSLionel Sambuc // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64
109f4a2713aSLionel Sambuc // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24
110f4a2713aSLionel Sambuc
111f4a2713aSLionel Sambuc // CHECK: %[[PTRINT:.*]] = ptrtoint
112f4a2713aSLionel Sambuc // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7
113f4a2713aSLionel Sambuc // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
114f4a2713aSLionel Sambuc
115f4a2713aSLionel Sambuc // (3b) Check that 'p' actually points to an 'S'
116f4a2713aSLionel Sambuc
117f4a2713aSLionel Sambuc // CHECK: load i64*
118f4a2713aSLionel Sambuc // CHECK-NEXT: xor i64 {{-4030275160588942838|2562089159}},
119f4a2713aSLionel Sambuc // [...]
120f4a2713aSLionel Sambuc // CHECK: getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %
121f4a2713aSLionel Sambuc // CHECK: br i1
122f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %{{.*}})
123f4a2713aSLionel Sambuc // CHECK-NOT: unreachable
124f4a2713aSLionel Sambuc // CHECK: {{.*}}:
125f4a2713aSLionel Sambuc
126f4a2713aSLionel Sambuc k = p->f();
127f4a2713aSLionel Sambuc }
128f4a2713aSLionel Sambuc
129*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z12lsh_overflow
lsh_overflow(int a,int b)130f4a2713aSLionel Sambuc int lsh_overflow(int a, int b) {
131f4a2713aSLionel Sambuc // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31
132f4a2713aSLionel Sambuc // CHECK-NEXT: br i1 %[[INBOUNDS]]
133f4a2713aSLionel Sambuc
134f4a2713aSLionel Sambuc // CHECK: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]]
135f4a2713aSLionel Sambuc // CHECK-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]]
136f4a2713aSLionel Sambuc
137f4a2713aSLionel Sambuc // This is present for C++11 but not for C: C++ core issue 1457 allows a '1'
138f4a2713aSLionel Sambuc // to be shifted into the sign bit, but not out of it.
139f4a2713aSLionel Sambuc // CHECK-NEXT: %[[SHIFTED_OUT_NOT_SIGN:.*]] = lshr i32 %[[SHIFTED_OUT]], 1
140f4a2713aSLionel Sambuc
141f4a2713aSLionel Sambuc // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT_NOT_SIGN]], 0
142f4a2713aSLionel Sambuc
143f4a2713aSLionel Sambuc // CHECK: %[[VALID:.*]] = phi i1 [ %[[INBOUNDS]], {{.*}} ], [ %[[NO_OVERFLOW]], {{.*}} ]
144f4a2713aSLionel Sambuc // CHECK-NEXT: br i1 %[[VALID]]
145f4a2713aSLionel Sambuc
146f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_shift_out_of_bounds
147f4a2713aSLionel Sambuc // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds
148f4a2713aSLionel Sambuc
149f4a2713aSLionel Sambuc // CHECK: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]]
150f4a2713aSLionel Sambuc // CHECK-NEXT: ret i32 %[[RET]]
151f4a2713aSLionel Sambuc return a << b;
152f4a2713aSLionel Sambuc }
153f4a2713aSLionel Sambuc
154*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z9no_return
no_return()155f4a2713aSLionel Sambuc int no_return() {
156f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_missing_return(i8* bitcast ({{.*}}* @{{.*}} to i8*)) [[NR_NUW:#[0-9]+]]
157f4a2713aSLionel Sambuc // CHECK-NEXT: unreachable
158f4a2713aSLionel Sambuc }
159f4a2713aSLionel Sambuc
160*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z9sour_bool
sour_bool(bool * p)161f4a2713aSLionel Sambuc bool sour_bool(bool *p) {
162f4a2713aSLionel Sambuc // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1
163f4a2713aSLionel Sambuc // CHECK: br i1 %[[OK]]
164f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_load_invalid_value(i8* bitcast ({{.*}}), i64 {{.*}})
165f4a2713aSLionel Sambuc return *p;
166f4a2713aSLionel Sambuc }
167f4a2713aSLionel Sambuc
168f4a2713aSLionel Sambuc enum E1 { e1a = 0, e1b = 127 } e1;
169f4a2713aSLionel Sambuc enum E2 { e2a = -1, e2b = 64 } e2;
170f4a2713aSLionel Sambuc enum E3 { e3a = (1u << 31) - 1 } e3;
171f4a2713aSLionel Sambuc
172*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z14bad_enum_value
bad_enum_value()173f4a2713aSLionel Sambuc int bad_enum_value() {
174f4a2713aSLionel Sambuc // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127
175f4a2713aSLionel Sambuc // CHECK: br i1 %[[E1]]
176f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_load_invalid_value(
177f4a2713aSLionel Sambuc int a = e1;
178f4a2713aSLionel Sambuc
179f4a2713aSLionel Sambuc // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127
180f4a2713aSLionel Sambuc // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128
181f4a2713aSLionel Sambuc // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]]
182f4a2713aSLionel Sambuc // CHECK: br i1 %[[E2]]
183f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_load_invalid_value(
184f4a2713aSLionel Sambuc int b = e2;
185f4a2713aSLionel Sambuc
186f4a2713aSLionel Sambuc // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647
187f4a2713aSLionel Sambuc // CHECK: br i1 %[[E3]]
188f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_load_invalid_value(
189f4a2713aSLionel Sambuc int c = e3;
190f4a2713aSLionel Sambuc return a + b + c;
191f4a2713aSLionel Sambuc }
192f4a2713aSLionel Sambuc
193*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z20bad_downcast_pointer
194*0a6a1f1dSLionel Sambuc // DOWNCAST-NULL-LABEL: @_Z20bad_downcast_pointer
bad_downcast_pointer(S * p)195f4a2713aSLionel Sambuc void bad_downcast_pointer(S *p) {
196f4a2713aSLionel Sambuc // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
197f4a2713aSLionel Sambuc // CHECK: br i1 %[[NONNULL]],
198f4a2713aSLionel Sambuc
199*0a6a1f1dSLionel Sambuc // A null poiner access is guarded without -fsanitize=null.
200*0a6a1f1dSLionel Sambuc // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null
201*0a6a1f1dSLionel Sambuc // DOWNCAST-NULL: br i1 %[[NONNULL]],
202*0a6a1f1dSLionel Sambuc
203f4a2713aSLionel Sambuc // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(
204f4a2713aSLionel Sambuc // CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24
205f4a2713aSLionel Sambuc // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
206f4a2713aSLionel Sambuc // CHECK: %[[E2:.*]] = icmp eq i64 %[[MISALIGN]], 0
207f4a2713aSLionel Sambuc // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]
208f4a2713aSLionel Sambuc // CHECK: br i1 %[[E12]],
209f4a2713aSLionel Sambuc
210f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_type_mismatch
211f4a2713aSLionel Sambuc // CHECK: br label
212f4a2713aSLionel Sambuc
213f4a2713aSLionel Sambuc // CHECK: br i1 %{{.*}},
214f4a2713aSLionel Sambuc
215f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss
216f4a2713aSLionel Sambuc // CHECK: br label
217f4a2713aSLionel Sambuc (void) static_cast<T*>(p);
218f4a2713aSLionel Sambuc }
219f4a2713aSLionel Sambuc
220*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z22bad_downcast_reference
bad_downcast_reference(S & p)221f4a2713aSLionel Sambuc void bad_downcast_reference(S &p) {
222f4a2713aSLionel Sambuc // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null
223f4a2713aSLionel Sambuc // CHECK-NOT: br i1
224*0a6a1f1dSLionel Sambuc
225f4a2713aSLionel Sambuc // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(
226f4a2713aSLionel Sambuc // CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24
227*0a6a1f1dSLionel Sambuc
228f4a2713aSLionel Sambuc // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
229f4a2713aSLionel Sambuc // CHECK: %[[E3:.*]] = icmp eq i64 %[[MISALIGN]], 0
230*0a6a1f1dSLionel Sambuc
231*0a6a1f1dSLionel Sambuc // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]
232f4a2713aSLionel Sambuc // CHECK: %[[E123:.*]] = and i1 %[[E12]], %[[E3]]
233f4a2713aSLionel Sambuc // CHECK: br i1 %[[E123]],
234f4a2713aSLionel Sambuc
235f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_type_mismatch
236f4a2713aSLionel Sambuc // CHECK: br label
237f4a2713aSLionel Sambuc
238f4a2713aSLionel Sambuc // CHECK: br i1 %{{.*}},
239f4a2713aSLionel Sambuc
240f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss
241f4a2713aSLionel Sambuc // CHECK: br label
242f4a2713aSLionel Sambuc (void) static_cast<T&>(p);
243f4a2713aSLionel Sambuc }
244f4a2713aSLionel Sambuc
245*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z11array_index
array_index(const int (& a)[4],int n)246f4a2713aSLionel Sambuc int array_index(const int (&a)[4], int n) {
247f4a2713aSLionel Sambuc // CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4
248f4a2713aSLionel Sambuc // CHECK: br i1 %[[K1_OK]]
249f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
250f4a2713aSLionel Sambuc int k1 = a[n];
251f4a2713aSLionel Sambuc
252f4a2713aSLionel Sambuc // CHECK: %[[R1_OK:.*]] = icmp ule i64 %{{.*}}, 4
253f4a2713aSLionel Sambuc // CHECK: br i1 %[[R1_OK]]
254f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
255f4a2713aSLionel Sambuc const int *r1 = &a[n];
256f4a2713aSLionel Sambuc
257f4a2713aSLionel Sambuc // CHECK: %[[K2_OK:.*]] = icmp ult i64 %{{.*}}, 8
258f4a2713aSLionel Sambuc // CHECK: br i1 %[[K2_OK]]
259f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
260f4a2713aSLionel Sambuc int k2 = ((const int(&)[8])a)[n];
261f4a2713aSLionel Sambuc
262f4a2713aSLionel Sambuc // CHECK: %[[K3_OK:.*]] = icmp ult i64 %{{.*}}, 4
263f4a2713aSLionel Sambuc // CHECK: br i1 %[[K3_OK]]
264f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
265f4a2713aSLionel Sambuc int k3 = n[a];
266f4a2713aSLionel Sambuc
267f4a2713aSLionel Sambuc return k1 + *r1 + k2;
268f4a2713aSLionel Sambuc }
269f4a2713aSLionel Sambuc
270*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z17multi_array_index
multi_array_index(int n,int m)271f4a2713aSLionel Sambuc int multi_array_index(int n, int m) {
272f4a2713aSLionel Sambuc int arr[4][6];
273f4a2713aSLionel Sambuc
274f4a2713aSLionel Sambuc // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6
275f4a2713aSLionel Sambuc // CHECK: br i1 %[[IDX2_OK]]
276f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
277f4a2713aSLionel Sambuc
278f4a2713aSLionel Sambuc // CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4
279f4a2713aSLionel Sambuc // CHECK: br i1 %[[IDX1_OK]]
280f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
281f4a2713aSLionel Sambuc return arr[n][m];
282f4a2713aSLionel Sambuc }
283f4a2713aSLionel Sambuc
284*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z11array_arith
array_arith(const int (& a)[4],int n)285f4a2713aSLionel Sambuc int array_arith(const int (&a)[4], int n) {
286f4a2713aSLionel Sambuc // CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4
287f4a2713aSLionel Sambuc // CHECK: br i1 %[[K1_OK]]
288f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
289f4a2713aSLionel Sambuc const int *k1 = a + n;
290f4a2713aSLionel Sambuc
291f4a2713aSLionel Sambuc // CHECK: %[[K2_OK:.*]] = icmp ule i64 %{{.*}}, 8
292f4a2713aSLionel Sambuc // CHECK: br i1 %[[K2_OK]]
293f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
294f4a2713aSLionel Sambuc const int *k2 = (const int(&)[8])a + n;
295f4a2713aSLionel Sambuc
296f4a2713aSLionel Sambuc return *k1 + *k2;
297f4a2713aSLionel Sambuc }
298f4a2713aSLionel Sambuc
299f4a2713aSLionel Sambuc struct ArrayMembers {
300f4a2713aSLionel Sambuc int a1[5];
301f4a2713aSLionel Sambuc int a2[1];
302f4a2713aSLionel Sambuc };
303*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z18struct_array_index
struct_array_index(ArrayMembers * p,int n)304f4a2713aSLionel Sambuc int struct_array_index(ArrayMembers *p, int n) {
305f4a2713aSLionel Sambuc // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5
306f4a2713aSLionel Sambuc // CHECK: br i1 %[[IDX_OK]]
307f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
308f4a2713aSLionel Sambuc return p->a1[n];
309f4a2713aSLionel Sambuc }
310f4a2713aSLionel Sambuc
311*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z16flex_array_index
flex_array_index(ArrayMembers * p,int n)312f4a2713aSLionel Sambuc int flex_array_index(ArrayMembers *p, int n) {
313f4a2713aSLionel Sambuc // CHECK-NOT: call void @__ubsan_handle_out_of_bounds(
314f4a2713aSLionel Sambuc return p->a2[n];
315f4a2713aSLionel Sambuc }
316f4a2713aSLionel Sambuc
317f4a2713aSLionel Sambuc extern int incomplete[];
318*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z22incomplete_array_index
incomplete_array_index(int n)319f4a2713aSLionel Sambuc int incomplete_array_index(int n) {
320f4a2713aSLionel Sambuc // CHECK-NOT: call void @__ubsan_handle_out_of_bounds(
321f4a2713aSLionel Sambuc return incomplete[n];
322f4a2713aSLionel Sambuc }
323f4a2713aSLionel Sambuc
324f4a2713aSLionel Sambuc typedef __attribute__((ext_vector_type(4))) int V4I;
325*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z12vector_index
vector_index(V4I v,int n)326f4a2713aSLionel Sambuc int vector_index(V4I v, int n) {
327f4a2713aSLionel Sambuc // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4
328f4a2713aSLionel Sambuc // CHECK: br i1 %[[IDX_OK]]
329f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
330f4a2713aSLionel Sambuc return v[n];
331f4a2713aSLionel Sambuc }
332f4a2713aSLionel Sambuc
333*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z12string_index
string_index(int n)334f4a2713aSLionel Sambuc char string_index(int n) {
335f4a2713aSLionel Sambuc // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6
336f4a2713aSLionel Sambuc // CHECK: br i1 %[[IDX_OK]]
337f4a2713aSLionel Sambuc // CHECK: call void @__ubsan_handle_out_of_bounds(
338f4a2713aSLionel Sambuc return "Hello"[n];
339f4a2713aSLionel Sambuc }
340f4a2713aSLionel Sambuc
341f4a2713aSLionel Sambuc class A // align=4
342f4a2713aSLionel Sambuc {
343f4a2713aSLionel Sambuc int a1, a2, a3;
344f4a2713aSLionel Sambuc };
345f4a2713aSLionel Sambuc
346f4a2713aSLionel Sambuc class B // align=8
347f4a2713aSLionel Sambuc {
348f4a2713aSLionel Sambuc long b1, b2;
349f4a2713aSLionel Sambuc };
350f4a2713aSLionel Sambuc
351f4a2713aSLionel Sambuc class C : public A, public B // align=16
352f4a2713aSLionel Sambuc {
353f4a2713aSLionel Sambuc alignas(16) int c1;
354f4a2713aSLionel Sambuc };
355f4a2713aSLionel Sambuc
356f4a2713aSLionel Sambuc // Make sure we check the alignment of the pointer after subtracting any
357f4a2713aSLionel Sambuc // offset. The pointer before subtraction doesn't need to be aligned for
358f4a2713aSLionel Sambuc // the destination type.
359f4a2713aSLionel Sambuc
360f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z16downcast_pointerP1B(%class.B* %b)
downcast_pointer(B * b)361f4a2713aSLionel Sambuc void downcast_pointer(B *b) {
362f4a2713aSLionel Sambuc (void) static_cast<C*>(b);
363f4a2713aSLionel Sambuc // Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...)
364f4a2713aSLionel Sambuc // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8* {{.*}}, i64 -16
365f4a2713aSLionel Sambuc // CHECK-NEXT: [[C:%[0-9]*]] = bitcast i8* [[SUB]] to %class.C*
366f4a2713aSLionel Sambuc // null check goes here
367f4a2713aSLionel Sambuc // CHECK: [[FROM_PHI:%[0-9]*]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}}
368f4a2713aSLionel Sambuc // Objectsize check goes here
369f4a2713aSLionel Sambuc // CHECK: [[C_INT:%[0-9]*]] = ptrtoint %class.C* [[FROM_PHI]] to i64
370f4a2713aSLionel Sambuc // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15
371f4a2713aSLionel Sambuc // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0
372f4a2713aSLionel Sambuc // AND the alignment test with the objectsize test.
373f4a2713aSLionel Sambuc // CHECK-NEXT: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]]
374f4a2713aSLionel Sambuc // CHECK-NEXT: br i1 [[AND]]
375f4a2713aSLionel Sambuc }
376f4a2713aSLionel Sambuc
377*0a6a1f1dSLionel Sambuc // CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* dereferenceable({{[0-9]+}}) %b)
downcast_reference(B & b)378f4a2713aSLionel Sambuc void downcast_reference(B &b) {
379f4a2713aSLionel Sambuc (void) static_cast<C&>(b);
380f4a2713aSLionel Sambuc // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...)
381f4a2713aSLionel Sambuc // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8* {{.*}}, i64 -16
382f4a2713aSLionel Sambuc // CHECK-NEXT: [[C:%[0-9]*]] = bitcast i8* [[SUB]] to %class.C*
383f4a2713aSLionel Sambuc // Objectsize check goes here
384f4a2713aSLionel Sambuc // CHECK: [[C_INT:%[0-9]*]] = ptrtoint %class.C* [[C]] to i64
385f4a2713aSLionel Sambuc // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15
386f4a2713aSLionel Sambuc // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0
387f4a2713aSLionel Sambuc // AND the alignment test with the objectsize test.
388*0a6a1f1dSLionel Sambuc // CHECK: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]]
389f4a2713aSLionel Sambuc // CHECK-NEXT: br i1 [[AND]]
390f4a2713aSLionel Sambuc }
391f4a2713aSLionel Sambuc
392*0a6a1f1dSLionel Sambuc // CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }>
indirect_function_call(void (* p)(int))393f4a2713aSLionel Sambuc void indirect_function_call(void (*p)(int)) {
394f4a2713aSLionel Sambuc // CHECK: [[PTR:%[0-9]*]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>*
395f4a2713aSLionel Sambuc
396f4a2713aSLionel Sambuc // Signature check
397f4a2713aSLionel Sambuc // CHECK-NEXT: [[SIGPTR:%[0-9]*]] = getelementptr <{ i32, i8* }>* [[PTR]], i32 0, i32 0
398f4a2713aSLionel Sambuc // CHECK-NEXT: [[SIG:%[0-9]*]] = load i32* [[SIGPTR]]
399f4a2713aSLionel Sambuc // CHECK-NEXT: [[SIGCMP:%[0-9]*]] = icmp eq i32 [[SIG]], 1413876459
400f4a2713aSLionel Sambuc // CHECK-NEXT: br i1 [[SIGCMP]]
401f4a2713aSLionel Sambuc
402f4a2713aSLionel Sambuc // RTTI pointer check
403f4a2713aSLionel Sambuc // CHECK: [[RTTIPTR:%[0-9]*]] = getelementptr <{ i32, i8* }>* [[PTR]], i32 0, i32 1
404f4a2713aSLionel Sambuc // CHECK-NEXT: [[RTTI:%[0-9]*]] = load i8** [[RTTIPTR]]
405f4a2713aSLionel Sambuc // CHECK-NEXT: [[RTTICMP:%[0-9]*]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*)
406f4a2713aSLionel Sambuc // CHECK-NEXT: br i1 [[RTTICMP]]
407f4a2713aSLionel Sambuc p(42);
408f4a2713aSLionel Sambuc }
409f4a2713aSLionel Sambuc
410*0a6a1f1dSLionel Sambuc namespace UpcastPointerTest {
411*0a6a1f1dSLionel Sambuc struct S {};
412*0a6a1f1dSLionel Sambuc struct T : S { double d; };
413*0a6a1f1dSLionel Sambuc struct V : virtual S {};
414*0a6a1f1dSLionel Sambuc
415*0a6a1f1dSLionel Sambuc // CHECK-LABEL: upcast_pointer
upcast_pointer(T * t)416*0a6a1f1dSLionel Sambuc S* upcast_pointer(T* t) {
417*0a6a1f1dSLionel Sambuc // Check for null pointer
418*0a6a1f1dSLionel Sambuc // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
419*0a6a1f1dSLionel Sambuc // CHECK: br i1 %[[NONNULL]]
420*0a6a1f1dSLionel Sambuc
421*0a6a1f1dSLionel Sambuc // Check alignment
422*0a6a1f1dSLionel Sambuc // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
423*0a6a1f1dSLionel Sambuc // CHECK: icmp eq i64 %[[MISALIGN]], 0
424*0a6a1f1dSLionel Sambuc
425*0a6a1f1dSLionel Sambuc // CHECK: call void @__ubsan_handle_type_mismatch
426*0a6a1f1dSLionel Sambuc return t;
427*0a6a1f1dSLionel Sambuc }
428*0a6a1f1dSLionel Sambuc
429*0a6a1f1dSLionel Sambuc V getV();
430*0a6a1f1dSLionel Sambuc
431*0a6a1f1dSLionel Sambuc // CHECK-LABEL: upcast_to_vbase
upcast_to_vbase()432*0a6a1f1dSLionel Sambuc void upcast_to_vbase() {
433*0a6a1f1dSLionel Sambuc // No need to check for null here, as we have a temporary here.
434*0a6a1f1dSLionel Sambuc
435*0a6a1f1dSLionel Sambuc // CHECK-NOT: br i1
436*0a6a1f1dSLionel Sambuc
437*0a6a1f1dSLionel Sambuc // CHECK: call i64 @llvm.objectsize
438*0a6a1f1dSLionel Sambuc // CHECK: call void @__ubsan_handle_type_mismatch
439*0a6a1f1dSLionel Sambuc // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss
440*0a6a1f1dSLionel Sambuc const S& s = getV();
441*0a6a1f1dSLionel Sambuc }
442*0a6a1f1dSLionel Sambuc }
443*0a6a1f1dSLionel Sambuc
444f4a2713aSLionel Sambuc namespace CopyValueRepresentation {
445f4a2713aSLionel Sambuc // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S3aSERKS0_
446f4a2713aSLionel Sambuc // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value
447f4a2713aSLionel Sambuc // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S4aSEOS0_
448f4a2713aSLionel Sambuc // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value
449f4a2713aSLionel Sambuc // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S5C2ERKS0_
450f4a2713aSLionel Sambuc // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value
451f4a2713aSLionel Sambuc // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S2C2ERKS0_
452f4a2713aSLionel Sambuc // CHECK: __ubsan_handle_load_invalid_value
453f4a2713aSLionel Sambuc // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S1C2ERKS0_
454f4a2713aSLionel Sambuc // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value
455f4a2713aSLionel Sambuc
456f4a2713aSLionel Sambuc struct CustomCopy { CustomCopy(); CustomCopy(const CustomCopy&); };
457f4a2713aSLionel Sambuc struct S1 {
458f4a2713aSLionel Sambuc CustomCopy CC;
459f4a2713aSLionel Sambuc bool b;
460f4a2713aSLionel Sambuc };
461f4a2713aSLionel Sambuc void callee1(S1);
test1()462f4a2713aSLionel Sambuc void test1() {
463f4a2713aSLionel Sambuc S1 s11;
464f4a2713aSLionel Sambuc callee1(s11);
465f4a2713aSLionel Sambuc S1 s12;
466f4a2713aSLionel Sambuc s12 = s11;
467f4a2713aSLionel Sambuc }
468f4a2713aSLionel Sambuc
469f4a2713aSLionel Sambuc static bool some_global_bool;
470f4a2713aSLionel Sambuc struct ExprCopy {
471f4a2713aSLionel Sambuc ExprCopy();
472f4a2713aSLionel Sambuc ExprCopy(const ExprCopy&, bool b = some_global_bool);
473f4a2713aSLionel Sambuc };
474f4a2713aSLionel Sambuc struct S2 {
475f4a2713aSLionel Sambuc ExprCopy EC;
476f4a2713aSLionel Sambuc bool b;
477f4a2713aSLionel Sambuc };
478f4a2713aSLionel Sambuc void callee2(S2);
test2(void)479f4a2713aSLionel Sambuc void test2(void) {
480f4a2713aSLionel Sambuc S2 s21;
481f4a2713aSLionel Sambuc callee2(s21);
482f4a2713aSLionel Sambuc S2 s22;
483f4a2713aSLionel Sambuc s22 = s21;
484f4a2713aSLionel Sambuc }
485f4a2713aSLionel Sambuc
486f4a2713aSLionel Sambuc struct CustomAssign { CustomAssign &operator=(const CustomAssign&); };
487f4a2713aSLionel Sambuc struct S3 {
488f4a2713aSLionel Sambuc CustomAssign CA;
489f4a2713aSLionel Sambuc bool b;
490f4a2713aSLionel Sambuc };
test3()491f4a2713aSLionel Sambuc void test3() {
492f4a2713aSLionel Sambuc S3 x, y;
493f4a2713aSLionel Sambuc x = y;
494f4a2713aSLionel Sambuc }
495f4a2713aSLionel Sambuc
496f4a2713aSLionel Sambuc struct CustomMove {
497f4a2713aSLionel Sambuc CustomMove();
498f4a2713aSLionel Sambuc CustomMove(const CustomMove&&);
499f4a2713aSLionel Sambuc CustomMove &operator=(const CustomMove&&);
500f4a2713aSLionel Sambuc };
501f4a2713aSLionel Sambuc struct S4 {
502f4a2713aSLionel Sambuc CustomMove CM;
503f4a2713aSLionel Sambuc bool b;
504f4a2713aSLionel Sambuc };
test4()505f4a2713aSLionel Sambuc void test4() {
506f4a2713aSLionel Sambuc S4 x, y;
507f4a2713aSLionel Sambuc x = static_cast<S4&&>(y);
508f4a2713aSLionel Sambuc }
509f4a2713aSLionel Sambuc
510f4a2713aSLionel Sambuc struct EnumCustomCopy {
511f4a2713aSLionel Sambuc EnumCustomCopy();
512f4a2713aSLionel Sambuc EnumCustomCopy(const EnumCustomCopy&);
513f4a2713aSLionel Sambuc };
514f4a2713aSLionel Sambuc struct S5 {
515f4a2713aSLionel Sambuc EnumCustomCopy ECC;
516f4a2713aSLionel Sambuc bool b;
517f4a2713aSLionel Sambuc };
518f4a2713aSLionel Sambuc void callee5(S5);
test5()519f4a2713aSLionel Sambuc void test5() {
520f4a2713aSLionel Sambuc S5 s51;
521f4a2713aSLionel Sambuc callee5(s51);
522f4a2713aSLionel Sambuc S5 s52;
523f4a2713aSLionel Sambuc s52 = s51;
524f4a2713aSLionel Sambuc }
525f4a2713aSLionel Sambuc }
526f4a2713aSLionel Sambuc
527f4a2713aSLionel Sambuc // CHECK: attributes [[NR_NUW]] = { noreturn nounwind }
528