xref: /llvm-project/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp (revision a1d77caaabbb5279b734c061dab36b2138ec476d)
1 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \
2 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s
3 
4 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics \
5 // RUN:   -fptrauth-vtable-pointer-type-discrimination \
6 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s
7 
8 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics \
9 // RUN:   -fptrauth-vtable-pointer-address-discrimination \
10 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s
11 
12 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics \
13 // RUN:   -fptrauth-vtable-pointer-type-discrimination \
14 // RUN:   -fptrauth-vtable-pointer-address-discrimination \
15 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s
16 
17 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
18 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s
19 
20 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
21 // RUN:   -fptrauth-vtable-pointer-type-discrimination \
22 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s
23 
24 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
25 // RUN:   -fptrauth-vtable-pointer-address-discrimination \
26 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s
27 
28 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \
29 // RUN:   -fptrauth-vtable-pointer-type-discrimination \
30 // RUN:   -fptrauth-vtable-pointer-address-discrimination \
31 // RUN:   -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s
32 
33 #include <ptrauth.h>
34 
35 namespace test1 {
36 
37 #define authenticated(a...) ptrauth_cxx_vtable_pointer(a)
38 
39 struct NoExplicitAuth {
40   virtual ~NoExplicitAuth();
41   virtual void f();
42   virtual void g();
43 };
44 
45 struct authenticated(no_authentication, no_address_discrimination, no_extra_discrimination) ExplicitlyDisableAuth {
46   virtual ~ExplicitlyDisableAuth();
47   virtual void f();
48   virtual void g();
49 };
50 
51 struct authenticated(default_key, address_discrimination, default_extra_discrimination) ExplicitAddressDiscrimination {
52   virtual ~ExplicitAddressDiscrimination();
53   virtual void f();
54   virtual void g();
55 };
56 
57 struct authenticated(default_key, no_address_discrimination, default_extra_discrimination) ExplicitNoAddressDiscrimination {
58   virtual ~ExplicitNoAddressDiscrimination();
59   virtual void f();
60   virtual void g();
61 };
62 
63 struct authenticated(default_key, default_address_discrimination, no_extra_discrimination) ExplicitNoExtraDiscrimination {
64   virtual ~ExplicitNoExtraDiscrimination();
65   virtual void f();
66   virtual void g();
67 };
68 
69 struct authenticated(default_key, default_address_discrimination, type_discrimination) ExplicitTypeDiscrimination {
70   virtual ~ExplicitTypeDiscrimination();
71   virtual void f();
72   virtual void g();
73 };
74 
75 struct authenticated(default_key, default_address_discrimination, custom_discrimination, 42424) ExplicitCustomDiscrimination {
76   virtual ~ExplicitCustomDiscrimination();
77   virtual void f();
78   virtual void g();
79 };
80 
81 template <typename T>
82 struct SubClass : T {
83   virtual void g();
84   virtual T *h();
85 };
86 
87 template <typename T>
88 SubClass<T> *make_subclass(T *);
89 
90 struct authenticated(default_key, address_discrimination, type_discrimination) BasicStruct {
91   virtual ~BasicStruct();
92 };
93 
94 template <typename T>
95 struct PrimaryBasicStruct : BasicStruct, T {};
96 template <typename T>
97 struct PrimaryBasicStruct<T> *make_multiple_primary(T *);
98 
99 template <typename T>
100 struct VirtualSubClass : virtual T {
101   virtual void g();
102   virtual T *h();
103 };
104 template <typename T>
105 struct VirtualPrimaryStruct : virtual T, VirtualSubClass<T> {};
106 template <typename T>
107 struct VirtualPrimaryStruct<T> *make_virtual_primary(T *);
108 
109 extern "C" {
110 
111 // CHECK: @TVDisc_NoExplicitAuth = global i32 [[DISC_DEFAULT:49565]], align 4
112 int TVDisc_NoExplicitAuth = ptrauth_string_discriminator("_ZTVN5test114NoExplicitAuthE");
113 
114 // CHECK: @TVDisc_ExplicitlyDisableAuth = global i32 [[DISC_DISABLED:24369]], align 4
115 int TVDisc_ExplicitlyDisableAuth = ptrauth_string_discriminator("_ZTVN5test121ExplicitlyDisableAuthE");
116 
117 // CHECK: @TVDisc_ExplicitAddressDiscrimination = global i32 [[DISC_ADDR:56943]], align 4
118 int TVDisc_ExplicitAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitAddressDiscriminationE");
119 
120 // CHECK: @TVDisc_ExplicitNoAddressDiscrimination = global i32 [[DISC_NO_ADDR:6022]], align 4
121 int TVDisc_ExplicitNoAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test131ExplicitNoAddressDiscriminationE");
122 
123 // CHECK: @TVDisc_ExplicitNoExtraDiscrimination = global i32 [[DISC_NO_EXTRA:9072]], align 4
124 int TVDisc_ExplicitNoExtraDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitNoExtraDiscriminationE");
125 
126 // CHECK: @TVDisc_ExplicitTypeDiscrimination = global i32 [[DISC_TYPE:6177]], align 4
127 int TVDisc_ExplicitTypeDiscrimination = ptrauth_string_discriminator("_ZTVN5test126ExplicitTypeDiscriminationE");
128 
129 
130 // CHECK-LABEL: define{{.*}} void @test_default(ptr noundef {{%.*}}) {{#.*}} {
131 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
132 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
133 //
134 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
135 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
136 //
137 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
138 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])
139 //
140 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
141 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
142 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
143 //
144 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
145 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])
146 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
147 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
148 void test_default(NoExplicitAuth *a) {
149   a->f();
150 }
151 
152 // CHECK-LABEL: define{{.*}} void @test_disabled(ptr noundef {{%.*}}) {{#.*}} {
153 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
154 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
155 // CHECK-NOT:     call i64 @llvm.ptrauth.auth
156 void test_disabled(ExplicitlyDisableAuth *a) {
157   a->f();
158 }
159 
160 // CHECK-LABEL: define{{.*}} void @test_addr_disc(ptr noundef {{%.*}}) {{#.*}} {
161 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
162 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
163 //
164 // NODISC:        [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
165 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
166 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
167 //
168 // TYPE:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
169 // TYPE:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])
170 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
171 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
172 //
173 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
174 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
175 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
176 //
177 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
178 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])
179 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
180 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
181 void test_addr_disc(ExplicitAddressDiscrimination *a) {
182   a->f();
183 }
184 
185 // CHECK-LABEL: define{{.*}} void @test_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} {
186 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
187 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
188 //
189 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
190 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
191 //
192 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
193 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])
194 //
195 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
196 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
197 //
198 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
199 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])
200 void test_no_addr_disc(ExplicitNoAddressDiscrimination *a) {
201   a->f();
202 }
203 
204 // CHECK-LABEL: define{{.*}} void @test_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} {
205 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
206 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
207 //
208 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
209 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
210 //
211 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
212 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
213 //
214 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
215 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
216 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
217 //
218 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
219 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
220 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
221 void test_no_extra_disc(ExplicitNoExtraDiscrimination *a) {
222   a->f();
223 }
224 
225 // CHECK-LABEL: define{{.*}} void @test_type_disc(ptr noundef {{%.*}}) {{#.*}} {
226 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
227 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
228 //
229 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
230 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])
231 //
232 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
233 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])
234 //
235 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
236 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])
237 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
238 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
239 //
240 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
241 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])
242 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
243 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
244 void test_type_disc(ExplicitTypeDiscrimination *a) {
245   a->f();
246 }
247 
248 // CHECK-LABEL: define{{.*}} void @test_custom_disc(ptr noundef {{%.*}}) {{#.*}} {
249 // CHECK:         [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8
250 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
251 //
252 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
253 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
254 //
255 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
256 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
257 //
258 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
259 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
260 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
261 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
262 //
263 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
264 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
265 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
266 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
267 void test_custom_disc(ExplicitCustomDiscrimination *a) {
268   a->f();
269 }
270 
271 //
272 // Test some simple single inheritance cases.
273 // Codegen should be the same as the simple cases above once we have a vtable.
274 //
275 
276 // CHECK-LABEL: define{{.*}} void @test_subclass_default(ptr noundef {{%.*}}) {{#.*}} {
277 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
278 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
279 //
280 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
281 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
282 //
283 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
284 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])
285 //
286 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
287 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
288 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
289 //
290 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
291 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])
292 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
293 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
294 void test_subclass_default(NoExplicitAuth *a) {
295   make_subclass(a)->f();
296 }
297 
298 // CHECK-LABEL: define{{.*}} void @test_subclass_disabled(ptr noundef {{%.*}}) {{#.*}} {
299 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
300 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
301 // CHECK-NOT:     call i64 @llvm.ptrauth.auth
302 void test_subclass_disabled(ExplicitlyDisableAuth *a) {
303   make_subclass(a)->f();
304 }
305 
306 // CHECK-LABEL: define{{.*}} void @test_subclass_addr_disc(ptr noundef {{%.*}}) {{#.*}} {
307 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
308 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
309 //
310 // NODISC:        [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
311 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
312 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
313 //
314 // TYPE:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
315 // TYPE:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])
316 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
317 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
318 //
319 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
320 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
321 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
322 //
323 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
324 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])
325 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
326 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
327 void test_subclass_addr_disc(ExplicitAddressDiscrimination *a) {
328   make_subclass(a)->f();
329 }
330 
331 // CHECK-LABEL: define{{.*}} void @test_subclass_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} {
332 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
333 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
334 //
335 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
336 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
337 //
338 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
339 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])
340 //
341 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
342 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
343 //
344 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
345 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])
346 void test_subclass_no_addr_disc(ExplicitNoAddressDiscrimination *a) {
347   make_subclass(a)->f();
348 }
349 
350 // CHECK-LABEL: define{{.*}} void @test_subclass_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} {
351 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
352 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
353 //
354 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
355 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
356 //
357 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
358 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
359 //
360 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
361 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
362 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
363 //
364 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
365 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
366 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
367 void test_subclass_no_extra_disc(ExplicitNoExtraDiscrimination *a) {
368   make_subclass(a)->f();
369 }
370 
371 // CHECK-LABEL: define{{.*}} void @test_subclass_type_disc(ptr noundef {{%.*}}) {{#.*}} {
372 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
373 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
374 //
375 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
376 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])
377 //
378 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
379 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])
380 //
381 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
382 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])
383 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
384 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
385 //
386 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
387 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])
388 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
389 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
390 void test_subclass_type_disc(ExplicitTypeDiscrimination *a) {
391   make_subclass(a)->f();
392 }
393 
394 // CHECK-LABEL: define{{.*}} void @test_subclass_custom_disc(ptr noundef {{%.*}}) {{#.*}} {
395 // CHECK:         [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass
396 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
397 //
398 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
399 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
400 //
401 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
402 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
403 //
404 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
405 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
406 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
407 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
408 //
409 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
410 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
411 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
412 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
413 void test_subclass_custom_disc(ExplicitCustomDiscrimination *a) {
414   make_subclass(a)->f();
415 }
416 
417 
418 //
419 // Test some simple multiple inheritance cases.
420 // Codegen should be the same as the simple cases above once we have a vtable.
421 //
422 
423 // CHECK-LABEL: define{{.*}} void @test_multiple_default(ptr noundef {{%.*}}) {{#.*}} {
424 // CHECK:         [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary
425 // CHECK:         [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8
426 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
427 //
428 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
429 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
430 //
431 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
432 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])
433 //
434 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
435 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
436 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
437 //
438 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
439 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])
440 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
441 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
442 void test_multiple_default(NoExplicitAuth *a) {
443   make_multiple_primary(a)->f();
444 }
445 
446 // CHECK-LABEL: define{{.*}} void @test_multiple_disabled(ptr noundef {{%.*}}) {{#.*}} {
447 // CHECK:         [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary
448 // CHECK:         [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8
449 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
450 // CHECK-NOT:     call i64 @llvm.ptrauth.auth
451 void test_multiple_disabled(ExplicitlyDisableAuth *a) {
452   make_multiple_primary(a)->f();
453 }
454 
455 // CHECK-LABEL: define{{.*}} void @test_multiple_custom_disc(ptr noundef {{%.*}}) {{#.*}} {
456 // CHECK:         [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary
457 // CHECK:         [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8
458 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
459 //
460 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
461 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
462 //
463 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
464 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
465 //
466 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
467 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
468 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
469 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
470 //
471 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
472 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
473 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
474 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
475 void test_multiple_custom_disc(ExplicitCustomDiscrimination *a) {
476   make_multiple_primary(a)->f();
477 }
478 
479 //
480 // Test some virtual inheritance cases.
481 // Codegen should be the same as the simple cases above once we have a vtable,
482 // but twice for vtt/vtable.  The names in the vtt version have "VTT" prefixes.
483 //
484 
485 // CHECK-LABEL: define{{.*}} void @test_virtual_default(ptr noundef {{%.*}}) {{#.*}} {
486 // CHECK:         [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary
487 // CHECK:         [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8
488 //
489 // NODISC:        [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
490 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 0)
491 //
492 // TYPE:          [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
493 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])
494 //
495 // ADDR:          [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64
496 // ADDR:          [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
497 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[VTTADDRI64]])
498 //
499 // BOTH:          [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64
500 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 [[DISC_DEFAULT]])
501 // BOTH:          [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
502 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]])
503 
504 // CHECK:         [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr
505 // CHECK:         [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48
506 // CHECK:         [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]]
507 // CHECK:         [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]]
508 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
509 //
510 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
511 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)
512 //
513 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
514 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])
515 //
516 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
517 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
518 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])
519 //
520 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
521 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])
522 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
523 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
524 void test_virtual_default(NoExplicitAuth *a) {
525   make_virtual_primary(a)->f();
526 }
527 
528 // CHECK-LABEL: define{{.*}} void @test_virtual_disabled(ptr noundef {{%.*}}) {{#.*}} {
529 // CHECK-NOT:     call i64 @llvm.ptrauth.auth
530 void test_virtual_disabled(ExplicitlyDisableAuth *a) {
531   make_virtual_primary(a)->f();
532 }
533 
534 // CHECK-LABEL: define{{.*}} void @test_virtual_custom_disc(ptr noundef {{%.*}}) {{#.*}} {
535 // CHECK:         [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary
536 // CHECK:         [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8
537 //
538 // NODISC:        [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
539 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424)
540 //
541 // TYPE:          [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
542 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424)
543 //
544 // ADDR:          [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64
545 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424)
546 // ADDR:          [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
547 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]])
548 //
549 // BOTH:          [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64
550 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424)
551 // BOTH:          [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64
552 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]])
553 
554 // CHECK:         [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr
555 // CHECK:         [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48
556 // CHECK:         [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]]
557 // CHECK:         [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]]
558 // CHECK:         [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8
559 //
560 // NODISC:        [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
561 // NODISC:        [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
562 //
563 // TYPE:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
564 // TYPE:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)
565 //
566 // ADDR:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
567 // ADDR:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
568 // ADDR:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
569 // ADDR:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
570 //
571 // BOTH:          [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64
572 // BOTH:          [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)
573 // BOTH:          [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
574 // BOTH:          [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])
575 void test_virtual_custom_disc(ExplicitCustomDiscrimination *a) {
576   make_virtual_primary(a)->f();
577 }
578 
579 } // extern "C"
580 } // namespace test1
581