1- // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-NOAUTH %s
2- // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-TYPEAUTH %s
3- // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-ADDRESSAUTH %s
4- // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-BOTHAUTH %s
1+ // RUN: %clang_cc1 %s -x c++ -std=c++23 -triple x86_64-apple-darwin10 -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-NOAUTH %s
2+ // RUN: %clang_cc1 %s -x c++ -std=c++23 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-TYPEAUTH %s
3+ // RUN: %clang_cc1 %s -x c++ -std=c++23 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-ADDRESSAUTH %s
4+ // RUN: %clang_cc1 %s -x c++ -std=c++23 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-BOTHAUTH %s
55// FIXME: Assume load should not require -fstrict-vtable-pointers
66
77namespace test1 {
@@ -27,7 +27,16 @@ struct D : virtual A {
2727struct E : D, B {
2828};
2929
30+ template <class A , class B > struct same_type {
31+ static const bool value = false ;
32+ };
33+
34+ template <class A > struct same_type <A, A> {
35+ static const bool value = true ;
36+ };
37+
3038const void *a (A *o) {
39+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
3140 // CHECK-NOAUTH: define ptr @_ZN5test11aEPNS_1AE(ptr %o) #0 {
3241 // CHECK-TYPEAUTH: define ptr @_ZN5test11aEPNS_1AE(ptr %o) #0 {
3342 return __builtin_get_vtable_pointer (o);
@@ -51,6 +60,7 @@ const void *a(A *o) {
5160}
5261
5362const void *b (B *o) {
63+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
5464 // CHECK-TYPEAUTH: define ptr @_ZN5test11bEPNS_1BE(ptr %o) #0 {
5565 // CHECK-NOAUTH: define ptr @_ZN5test11bEPNS_1BE(ptr %o) #0 {
5666 return __builtin_get_vtable_pointer (o);
@@ -72,6 +82,7 @@ const void *b(B *o) {
7282}
7383
7484const void *b_as_A (B *o) {
85+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
7586 // CHECK-NOAUTH: define ptr @_ZN5test16b_as_AEPNS_1BE(ptr %o) #0 {
7687 return __builtin_get_vtable_pointer ((A *)o);
7788 // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8
@@ -92,6 +103,7 @@ const void *b_as_A(B *o) {
92103}
93104
94105const void *c (C *o) {
106+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
95107 // CHECK-NOAUTH: define ptr @_ZN5test11cEPNS_1CE(ptr %o) #0 {
96108 return __builtin_get_vtable_pointer (o);
97109 // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8
@@ -112,6 +124,7 @@ const void *c(C *o) {
112124}
113125
114126const void *c_as_Z (C *o) {
127+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
115128 // CHECK-NOAUTH: define ptr @_ZN5test16c_as_ZEPNS_1CE(ptr %o) #0 {
116129 return __builtin_get_vtable_pointer ((Z *)o);
117130 // CHECK-NOAUTH: %0 = load ptr, ptr %o.addr, align 8
@@ -133,6 +146,7 @@ const void *c_as_Z(C *o) {
133146}
134147
135148const void *c_as_B (C *o) {
149+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
136150 // CHECK-NOAUTH: define ptr @_ZN5test16c_as_BEPNS_1CE(ptr %o) #0 {
137151 return __builtin_get_vtable_pointer ((B *)o);
138152 // CHECK-NOAUTH: %add.ptr = getelementptr inbounds i8, ptr %0, i64 8
@@ -158,6 +172,7 @@ const void *c_as_B(C *o) {
158172}
159173
160174const void *d (D *o) {
175+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
161176 // CHECK-NOAUTH: define ptr @_ZN5test11dEPNS_1DE(ptr %o) #0 {
162177 return __builtin_get_vtable_pointer (o);
163178 // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8
@@ -180,6 +195,7 @@ const void *d(D *o) {
180195}
181196
182197const void *d_as_A (D *o) {
198+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
183199 // CHECK-NOAUTH: define ptr @_ZN5test16d_as_AEPNS_1DE(ptr %o) #0 {
184200 return __builtin_get_vtable_pointer ((A *)o);
185201 // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8
@@ -207,6 +223,7 @@ const void *d_as_A(D *o) {
207223}
208224
209225const void *e (E *o) {
226+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
210227 // CHECK-NOAUTH: define ptr @_ZN5test11eEPNS_1EE(ptr %o) #0 {
211228 return __builtin_get_vtable_pointer (o);
212229 // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8
@@ -229,6 +246,7 @@ const void *e(E *o) {
229246}
230247
231248const void *e_as_B (E *o) {
249+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
232250 // CHECK-NOAUTH: define ptr @_ZN5test16e_as_BEPNS_1EE(ptr %o) #0 {
233251 return __builtin_get_vtable_pointer ((B *)o);
234252 // CHECK-NOAUTH: %add.ptr = getelementptr inbounds i8, ptr %0, i64 8
@@ -253,6 +271,7 @@ const void *e_as_B(E *o) {
253271}
254272
255273const void *e_as_D (E *o) {
274+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (o)), const void *>::value);
256275 // CHECK-NOAUTH: define ptr @_ZN5test16e_as_DEPNS_1EE(ptr %o) #0 {
257276 return __builtin_get_vtable_pointer ((D *)o);
258277 // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8
@@ -274,12 +293,58 @@ const void *e_as_D(E *o) {
274293 // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8
275294}
276295
296+ extern " C" const void *aArrayParameter (A aArray[]) {
297+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (aArray)), const void *>::value);
298+ // CHECK-NOAUTH: [[THIS_OBJ:%.*]] = load ptr, ptr %aArray.addr
299+ // CHECK-NOAUTH: %vtable = load ptr, ptr [[THIS_OBJ]]
300+ // CHECK-TYPEAUTH: [[THIS_OBJ:%.*]] = load ptr, ptr %aArray.addr
301+ // CHECK-TYPEAUTH: %vtable = load ptr, ptr [[THIS_OBJ]]
302+ // CHECK-TYPEAUTH: [[VTABLEI:%.*]] = ptrtoint ptr %vtable to i64
303+ // CHECK-TYPEAUTH: [[AUTHENTICATED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI]], i32 2, i64 48388)
304+ // CHECK-ADDRESSAUTH: [[VTABLE_ADDR:%.*]] = load ptr, ptr %aArray.addr, align 8, !tbaa !2
305+ // CHECK-ADDRESSAUTH: %vtable = load ptr, ptr %0, align 8, !tbaa !7
306+ // CHECK-ADDRESSAUTH: [[VTABLE_ADDRI:%.*]] = ptrtoint ptr [[VTABLE_ADDR]] to i64
307+ // CHECK-ADDRESSAUTH: [[VTABLEI:%.*]] = ptrtoint ptr %vtable to i64
308+ // CHECK-ADDRESSAUTH: [[AUTHENTICATED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI]], i32 2, i64 [[VTABLE_ADDRI]])
309+ // CHECK-BOTHAUTH: [[VTABLE_ADDR:%.*]] = load ptr, ptr %aArray.addr, align 8, !tbaa !2
310+ // CHECK-BOTHAUTH: %vtable = load ptr, ptr [[VTABLE_ADDR]], align 8, !tbaa !7
311+ // CHECK-BOTHAUTH: [[VTABLE_ADDRI:%.*]] = ptrtoint ptr [[VTABLE_ADDR]] to i64
312+ // CHECK-BOTHAUTH: [[VTABLE_DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTABLE_ADDRI]], i64 48388)
313+ // CHECK-BOTHAUTH: [[VTABLE_PTR:%.*]] = ptrtoint ptr %vtable to i64
314+ // CHECK-BOTHAUTH: [[AUTHENTICATED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLE_PTR]], i32 2, i64 [[VTABLE_DISC]])
315+ return __builtin_get_vtable_pointer (aArray);
316+ }
317+
318+ extern " C" const void *aArrayLocal () {
319+ A array[] = { A () };
320+ static_assert (same_type<decltype (__builtin_get_vtable_pointer (array)), const void *>::value);
321+ // CHECK-NOAUTH: [[THIS_OBJ:%.*]] = getelementptr inbounds [1 x %"struct.test1::A"], ptr %array
322+ // CHECK-NOAUTH: %vtable = load ptr, ptr %arraydecay
323+ // CHECK-TYPEAUTH: %arraydecay = getelementptr inbounds [1 x %"struct.test1::A"]
324+ // CHECK-TYPEAUTH: %vtable = load ptr, ptr %arraydecay
325+ // CHECK-TYPEAUTH: [[VTABLEI:%.*]] = ptrtoint ptr %vtable to i64
326+ // CHECK-TYPEAUTH: [[AUTHENTICATED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI]], i32 2, i64 48388)
327+ // CHECK-ADDRESSAUTH: %arraydecay = getelementptr inbounds [1 x %"struct.test1::A"], ptr %array, i64 0, i64 0
328+ // CHECK-ADDRESSAUTH: %vtable = load ptr, ptr %arraydecay, align 8, !tbaa !7
329+ // CHECK-ADDRESSAUTH: [[VTABLE_ADDRI:%.*]] = ptrtoint ptr %arraydecay to i64
330+ // CHECK-ADDRESSAUTH: [[VTABLEI:%.*]] = ptrtoint ptr %vtable to i64
331+ // CHECK-ADDRESSAUTH: [[AUTHENTICATED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI]], i32 2, i64 [[VTABLE_ADDRI]])
332+ // CHECK-BOTHAUTH: %arraydecay = getelementptr inbounds [1 x %"struct.test1::A"], ptr %array, i64 0, i64 0
333+ // CHECK-BOTHAUTH: %vtable = load ptr, ptr %arraydecay, align 8, !tbaa !7
334+ // CHECK-BOTHAUTH: [[VTABLE_ADDRI:%.*]] = ptrtoint ptr %arraydecay to i64
335+ // CHECK-BOTHAUTH: [[VTABLE_DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 %0, i64 48388)
336+ // CHECK-BOTHAUTH: [[VTABLEI:%.*]] = ptrtoint ptr %vtable to i64
337+ // CHECK-BOTHAUTH: [[AUTHENTICATED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI]], i32 2, i64 [[VTABLE_DISC]])
338+ return __builtin_get_vtable_pointer (array);
339+ }
340+
277341void test () {
278342 A aInstance;
279343 B bInstance;
280344 C cInstance;
281345 D dInstance;
282346 E eInstance;
347+ E eArray[] = { E () };
283348 a (&aInstance);
284349 a (&bInstance);
285350 a ((B *)&cInstance);
@@ -300,5 +365,6 @@ void test() {
300365 e (&eInstance);
301366 e_as_B (&eInstance);
302367 e_as_D (&eInstance);
368+ (void )__builtin_get_vtable_pointer (eArray);
303369}
304370} // namespace test1
0 commit comments