1 | // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s --check-prefixes=CHECK,ALIGN |
2 | // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s --check-prefixes=CHECK,NULL |
3 | // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment,null -DCHECK_LAMBDA | FileCheck %s --check-prefixes=LAMBDA |
4 | |
5 | // CHECK-LABEL: define void @_Z22load_non_null_pointersv |
6 | void load_non_null_pointers() { |
7 | int var; |
8 | var = *&var; |
9 | |
10 | int arr[1]; |
11 | arr[0] = arr[0]; |
12 | |
13 | char c = "foo"[0]; |
14 | |
15 | // CHECK-NOT: and i64 {{.*}}, !nosanitize |
16 | // CHECK-NOT: icmp ne {{.*}}, null, !nosanitize |
17 | // CHECK: ret void |
18 | } |
19 | |
20 | // CHECK-LABEL: define void @_Z31use_us16_aligned_array_elementsv |
21 | void use_us16_aligned_array_elements() { |
22 | static const unsigned short Arr[] = {0, 1, 2}; |
23 | auto use_array = [](const unsigned short(&X)[3]) -> void {}; |
24 | use_array(Arr); |
25 | |
26 | // CHECK-NOT: br i1 true |
27 | // ALIGN-NOT: call void @__ubsan_handle_type_mismatch |
28 | // CHECK: ret void |
29 | } |
30 | |
31 | struct A { |
32 | int foo; |
33 | |
34 | // CHECK-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv |
35 | void do_nothing() { |
36 | // ALIGN: %[[THISINT1:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
37 | // ALIGN: and i64 %[[THISINT1]], 3, !nosanitize |
38 | // NULL: icmp ne %struct.A* %[[THIS1:[a-z0-9]+]], null, !nosanitize |
39 | // NULL: ptrtoint %struct.A* %[[THIS1]] to i64, !nosanitize |
40 | // CHECK: call void @__ubsan_handle_type_mismatch |
41 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
42 | // CHECK: ret void |
43 | } |
44 | |
45 | #ifdef CHECK_LAMBDA |
46 | // LAMBDA-LABEL: define linkonce_odr void @_ZN1A22do_nothing_with_lambdaEv |
47 | void do_nothing_with_lambda() { |
48 | // LAMBDA: icmp ne %struct.A* %[[THIS2:[a-z0-9]+]], null, !nosanitize |
49 | // LAMBDA: %[[THISINT2:[0-9]+]] = ptrtoint %struct.A* %[[THIS2]] to i64, !nosanitize |
50 | // LAMBDA: and i64 %[[THISINT2]], 3, !nosanitize |
51 | // LAMBDA: call void @__ubsan_handle_type_mismatch |
52 | |
53 | auto f = [&] { |
54 | foo = 0; |
55 | }; |
56 | f(); |
57 | |
58 | // LAMBDA-NOT: call void @__ubsan_handle_type_mismatch |
59 | // LAMBDA: ret void |
60 | } |
61 | |
62 | // Check the IR for the lambda: |
63 | // |
64 | // LAMBDA-LABEL: define linkonce_odr void @_ZZN1A22do_nothing_with_lambdaEvENKUlvE_clEv |
65 | // LAMBDA: call void @__ubsan_handle_type_mismatch |
66 | // LAMBDA-NOT: call void @__ubsan_handle_type_mismatch |
67 | // LAMBDA: ret void |
68 | #endif |
69 | |
70 | // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11load_memberEv |
71 | int load_member() { |
72 | // ALIGN: %[[THISINT3:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
73 | // ALIGN: and i64 %[[THISINT3]], 3, !nosanitize |
74 | // NULL: icmp ne %struct.A* %[[THIS3:[a-z0-9]+]], null, !nosanitize |
75 | // NULL: ptrtoint %struct.A* %[[THIS3]] to i64, !nosanitize |
76 | // CHECK: call void @__ubsan_handle_type_mismatch |
77 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
78 | return foo; |
79 | // CHECK: ret i32 |
80 | } |
81 | |
82 | // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11call_methodEv |
83 | int call_method() { |
84 | // ALIGN: %[[THISINT4:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
85 | // ALIGN: and i64 %[[THISINT4]], 3, !nosanitize |
86 | // NULL: icmp ne %struct.A* %[[THIS4:[a-z0-9]+]], null, !nosanitize |
87 | // NULL: ptrtoint %struct.A* %[[THIS4]] to i64, !nosanitize |
88 | // CHECK: call void @__ubsan_handle_type_mismatch |
89 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
90 | return load_member(); |
91 | // CHECK: ret i32 |
92 | } |
93 | |
94 | // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_1Ev |
95 | void assign_member_1() { |
96 | // ALIGN: %[[THISINT5:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
97 | // ALIGN: and i64 %[[THISINT5]], 3, !nosanitize |
98 | // NULL: icmp ne %struct.A* %[[THIS5:[a-z0-9]+]], null, !nosanitize |
99 | // NULL: ptrtoint %struct.A* %[[THIS5]] to i64, !nosanitize |
100 | // CHECK: call void @__ubsan_handle_type_mismatch |
101 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
102 | foo = 0; |
103 | // CHECK: ret void |
104 | } |
105 | |
106 | // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_2Ev |
107 | void assign_member_2() { |
108 | // ALIGN: %[[THISINT6:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
109 | // ALIGN: and i64 %[[THISINT6]], 3, !nosanitize |
110 | // NULL: icmp ne %struct.A* %[[THIS6:[a-z0-9]+]], null, !nosanitize |
111 | // NULL: ptrtoint %struct.A* %[[THIS6]] to i64, !nosanitize |
112 | // CHECK: call void @__ubsan_handle_type_mismatch |
113 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
114 | (__extension__ (this))->foo = 0; |
115 | // CHECK: ret void |
116 | } |
117 | |
118 | // CHECK-LABEL: define linkonce_odr void @_ZNK1A15assign_member_3Ev |
119 | void assign_member_3() const { |
120 | // ALIGN: %[[THISINT7:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
121 | // ALIGN: and i64 %[[THISINT7]], 3, !nosanitize |
122 | // NULL: icmp ne %struct.A* %[[THIS7:[a-z0-9]+]], null, !nosanitize |
123 | // NULL: ptrtoint %struct.A* %[[THIS7]] to i64, !nosanitize |
124 | // CHECK: call void @__ubsan_handle_type_mismatch |
125 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
126 | const_cast<A *>(this)->foo = 0; |
127 | // CHECK: ret void |
128 | } |
129 | |
130 | // CHECK-LABEL: define linkonce_odr i32 @_ZN1A22call_through_referenceERS_ |
131 | static int call_through_reference(A &a) { |
132 | // ALIGN: %[[OBJINT:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize |
133 | // ALIGN: and i64 %[[OBJINT]], 3, !nosanitize |
134 | // ALIGN: call void @__ubsan_handle_type_mismatch |
135 | // NULL-NOT: call void @__ubsan_handle_type_mismatch |
136 | return a.load_member(); |
137 | // CHECK: ret i32 |
138 | } |
139 | |
140 | // CHECK-LABEL: define linkonce_odr i32 @_ZN1A20call_through_pointerEPS_ |
141 | static int call_through_pointer(A *a) { |
142 | // CHECK: call void @__ubsan_handle_type_mismatch |
143 | return a->load_member(); |
144 | // CHECK: ret i32 |
145 | } |
146 | }; |
147 | |
148 | struct B { |
149 | operator A*() const { return nullptr; } |
150 | |
151 | // CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEPS_ |
152 | static int load_member(B *bp) { |
153 | // Check &b before converting it to an A*. |
154 | // CHECK: call void @__ubsan_handle_type_mismatch |
155 | // |
156 | // Check the result of the conversion before using it. |
157 | // NULL: call void @__ubsan_handle_type_mismatch |
158 | // |
159 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
160 | return static_cast<A *>(*bp)->load_member(); |
161 | // CHECK: ret i32 |
162 | } |
163 | }; |
164 | |
165 | struct Base { |
166 | int foo; |
167 | |
168 | virtual int load_member_1() = 0; |
169 | }; |
170 | |
171 | struct Derived : public Base { |
172 | int bar; |
173 | |
174 | // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_2Ev |
175 | int load_member_2() { |
176 | // ALIGN: %[[THISINT8:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize |
177 | // ALIGN: and i64 %[[THISINT8]], 7, !nosanitize |
178 | // ALIGN: call void @__ubsan_handle_type_mismatch |
179 | // NULL: icmp ne %struct.Derived* %[[THIS8:[a-z0-9]+]], null, !nosanitize |
180 | // NULL: ptrtoint %struct.Derived* %[[THIS8]] to i64, !nosanitize |
181 | // CHECK: call void @__ubsan_handle_type_mismatch |
182 | // |
183 | // Check the result of the cast before using it. |
184 | // CHECK: call void @__ubsan_handle_type_mismatch |
185 | // |
186 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
187 | return dynamic_cast<Base *>(this)->load_member_1(); |
188 | // CHECK: ret i32 |
189 | } |
190 | |
191 | // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_3Ev |
192 | int load_member_3() { |
193 | // ALIGN: %[[THISINT9:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize |
194 | // ALIGN: and i64 %[[THISINT9]], 7, !nosanitize |
195 | // ALIGN: call void @__ubsan_handle_type_mismatch |
196 | // ALIGN: call void @__ubsan_handle_type_mismatch |
197 | // NULL: icmp ne %struct.Derived* %[[THIS9:[a-z0-9]+]], null, !nosanitize |
198 | // NULL: ptrtoint %struct.Derived* %[[THIS9]] to i64, !nosanitize |
199 | // CHECK: call void @__ubsan_handle_type_mismatch |
200 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
201 | return reinterpret_cast<Derived *>(static_cast<Base *>(this))->foo; |
202 | // CHECK: ret i32 |
203 | } |
204 | |
205 | // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_1Ev |
206 | int load_member_1() override { |
207 | // ALIGN: %[[THISINT10:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize |
208 | // ALIGN: and i64 %[[THISINT10]], 7, !nosanitize |
209 | // ALIGN: call void @__ubsan_handle_type_mismatch |
210 | // NULL: icmp ne %struct.Derived* %[[THIS10:[a-z0-9]+]], null, !nosanitize |
211 | // NULL: ptrtoint %struct.Derived* %[[THIS10]] to i64, !nosanitize |
212 | // CHECK: call void @__ubsan_handle_type_mismatch |
213 | // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
214 | return foo + bar; |
215 | // CHECK: ret i32 |
216 | } |
217 | }; |
218 | |
219 | void force_irgen() { |
220 | A *a; |
221 | a->do_nothing(); |
222 | #ifdef CHECK_LAMBDA |
223 | a->do_nothing_with_lambda(); |
224 | #endif |
225 | a->load_member(); |
226 | a->call_method(); |
227 | a->assign_member_1(); |
228 | a->assign_member_2(); |
229 | a->assign_member_3(); |
230 | A::call_through_reference(*a); |
231 | A::call_through_pointer(a); |
232 | |
233 | B::load_member(nullptr); |
234 | |
235 | Base *b = new Derived; |
236 | b->load_member_1(); |
237 | |
238 | Derived *d; |
239 | d->load_member_2(); |
240 | d->load_member_3(); |
241 | |
242 | load_non_null_pointers(); |
243 | use_us16_aligned_array_elements(); |
244 | } |
245 | |