xref: /llvm-project/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp (revision 485c80e1188192a4bb2a8cbddccdca82a6e33b81)
170c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,DARWIN %s
2*485c80e1SAkira Hatanaka // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++17 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,DARWIN,CXX17 %s
370c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -debug-info-kind=limited -o - %s | FileCheck -check-prefixes=CHECK,DARWIN %s
44dcd91aeSOliver Hunt // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 1 -o - %s | FileCheck %s -check-prefix=STACK-PROT
54dcd91aeSOliver Hunt // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 2 -o - %s | FileCheck %s -check-prefix=STACK-PROT
64dcd91aeSOliver Hunt // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 3 -o - %s | FileCheck %s -check-prefix=STACK-PROT
74dcd91aeSOliver Hunt 
870c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,ELF %s
9*485c80e1SAkira Hatanaka // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++17 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,ELF,CXX17 %s
1070c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -debug-info-kind=limited -o - %s | FileCheck -check-prefixes=CHECK,ELF %s
1170c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 1 -o - %s | FileCheck %s -check-prefix=STACK-PROT
1270c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 2 -o - %s | FileCheck %s -check-prefix=STACK-PROT
1370c6e79eSDaniil Kovalev // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 3 -o - %s | FileCheck %s -check-prefix=STACK-PROT
1470c6e79eSDaniil Kovalev 
154dcd91aeSOliver Hunt 
164dcd91aeSOliver Hunt // CHECK: @gmethod0 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1:35591]]) to i64), i64 0 }, align 8
174dcd91aeSOliver Hunt // CHECK: @gmethod1 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011nonvirtual5Ev, i32 0, i64 [[TYPEDISC0:22163]]) to i64), i64 0 }, align 8
184dcd91aeSOliver Hunt // CHECK: @gmethod2 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, align 8
194dcd91aeSOliver Hunt 
204dcd91aeSOliver Hunt // CHECK: @__const._Z13testArrayInitv.p0 = private unnamed_addr constant [1 x { i64, i64 }] [{ i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 35591) to i64), i64 0 }], align 8
214dcd91aeSOliver Hunt // CHECK: @__const._Z13testArrayInitv.p1 = private unnamed_addr constant [1 x { i64, i64 }] [{ i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 35591) to i64), i64 0 }], align 8
224dcd91aeSOliver Hunt // CHECK: @__const._Z13testArrayInitv.c0 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 35591) to i64), i64 0 } }, align 8
234dcd91aeSOliver Hunt // CHECK: @__const._Z13testArrayInitv.c1 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 35591) to i64), i64 0 } }, align 8
244dcd91aeSOliver Hunt 
25*485c80e1SAkira Hatanaka // CHECK: @_ZN22testNoexceptConversion6mfptr1E = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3:.*]]) to i64), i64 0 },
26*485c80e1SAkira Hatanaka // CHECK: @_ZN22testNoexceptConversion6mfptr2E = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S16virtual_noexceptEv_vfpthunk_, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 },
27*485c80e1SAkira Hatanaka // CHECK: @_ZN22testNoexceptConversion15mfptr3_noexceptE = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 },
28*485c80e1SAkira Hatanaka 
294dcd91aeSOliver Hunt // CHECK: @_ZTV5Base0 = unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI5Base0,
304dcd91aeSOliver Hunt // CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual1Ev, i32 0, i64 55600, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 2)),
314dcd91aeSOliver Hunt // CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual3Ev, i32 0, i64 53007, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 3)),
324dcd91aeSOliver Hunt // CHECK-SAME: ptr ptrauth (ptr @_ZN5Base016virtual_variadicEiz, i32 0, i64 7464, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 4))] }, align 8
334dcd91aeSOliver Hunt 
344dcd91aeSOliver Hunt typedef __SIZE_TYPE__ size_t;
354dcd91aeSOliver Hunt 
364dcd91aeSOliver Hunt namespace std {
374dcd91aeSOliver Hunt template <typename _Ep>
384dcd91aeSOliver Hunt class initializer_list {
394dcd91aeSOliver Hunt   const _Ep *__begin_;
404dcd91aeSOliver Hunt   size_t __size_;
414dcd91aeSOliver Hunt 
424dcd91aeSOliver Hunt   initializer_list(const _Ep *__b, size_t __s);
434dcd91aeSOliver Hunt };
444dcd91aeSOliver Hunt } // namespace std
454dcd91aeSOliver Hunt 
464dcd91aeSOliver Hunt struct Base0 {
474dcd91aeSOliver Hunt   void nonvirtual0();
484dcd91aeSOliver Hunt   virtual void virtual1();
494dcd91aeSOliver Hunt   virtual void virtual3();
504dcd91aeSOliver Hunt   virtual void virtual_variadic(int, ...);
514dcd91aeSOliver Hunt };
524dcd91aeSOliver Hunt 
534dcd91aeSOliver Hunt struct A0 {
544dcd91aeSOliver Hunt   int d[4];
554dcd91aeSOliver Hunt };
564dcd91aeSOliver Hunt 
574dcd91aeSOliver Hunt struct A1 {
584dcd91aeSOliver Hunt   int d[8];
594dcd91aeSOliver Hunt };
604dcd91aeSOliver Hunt 
614dcd91aeSOliver Hunt struct __attribute__((trivial_abi)) TrivialS {
624dcd91aeSOliver Hunt   TrivialS(const TrivialS &);
634dcd91aeSOliver Hunt   ~TrivialS();
644dcd91aeSOliver Hunt   int p[4];
654dcd91aeSOliver Hunt };
664dcd91aeSOliver Hunt 
674dcd91aeSOliver Hunt struct Derived0 : Base0 {
684dcd91aeSOliver Hunt   void virtual1() override;
694dcd91aeSOliver Hunt   void nonvirtual5();
704dcd91aeSOliver Hunt   virtual void virtual6();
714dcd91aeSOliver Hunt   virtual A0 return_agg();
724dcd91aeSOliver Hunt   virtual A1 sret();
734dcd91aeSOliver Hunt   virtual void trivial_abi(TrivialS);
744dcd91aeSOliver Hunt };
754dcd91aeSOliver Hunt 
764dcd91aeSOliver Hunt struct Base1 {
774dcd91aeSOliver Hunt   virtual void virtual7();
784dcd91aeSOliver Hunt };
794dcd91aeSOliver Hunt 
804dcd91aeSOliver Hunt struct Derived1 : Base0, Base1 {
814dcd91aeSOliver Hunt   void virtual1() override;
824dcd91aeSOliver Hunt   void virtual7() override;
834dcd91aeSOliver Hunt };
844dcd91aeSOliver Hunt 
854dcd91aeSOliver Hunt typedef void (Base0::*MethodTy0)();
86*485c80e1SAkira Hatanaka #if __cplusplus >= 201703L
87*485c80e1SAkira Hatanaka typedef void (Base0::*NoExceptMethodTy0)() noexcept;
88*485c80e1SAkira Hatanaka #endif
894dcd91aeSOliver Hunt typedef void (Base0::*VariadicMethodTy0)(int, ...);
904dcd91aeSOliver Hunt typedef void (Derived0::*MethodTy1)();
914dcd91aeSOliver Hunt 
924dcd91aeSOliver Hunt struct Class0 {
934dcd91aeSOliver Hunt   MethodTy1 m0;
944dcd91aeSOliver Hunt };
954dcd91aeSOliver Hunt 
9670c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_ZN5Base08virtual1Ev(
974dcd91aeSOliver Hunt 
9870c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z5test0v()
994dcd91aeSOliver Hunt // CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8
1004dcd91aeSOliver Hunt // CHECK-NEXT: %[[VARMETHOD1:.*]] = alloca { i64, i64 }, align 8
1014dcd91aeSOliver Hunt // CHECK-NEXT: %[[METHOD2:.*]] = alloca { i64, i64 }, align 8
1024dcd91aeSOliver Hunt // CHECK-NEXT: %[[METHOD3:.*]] = alloca { i64, i64 }, align 8
1034dcd91aeSOliver Hunt // CHECK-NEXT: %[[METHOD4:.*]] = alloca { i64, i64 }, align 8
1044dcd91aeSOliver Hunt // CHECK-NEXT: %[[METHOD5:.*]] = alloca { i64, i64 }, align 8
1054dcd91aeSOliver Hunt // CHECK-NEXT: %[[METHOD6:.*]] = alloca { i64, i64 }, align 8
1064dcd91aeSOliver Hunt // CHECK-NEXT: %[[METHOD7:.*]] = alloca { i64, i64 }, align 8
1074dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8
1084dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8
1094dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual3Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8
1104dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base016virtual_variadicEiz_vfpthunk_, i32 0, i64 34368) to i64), i64 0 }, ptr %[[VARMETHOD1]], align 8
1114dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8
1124dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8
1134dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual3Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8
1144dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011nonvirtual5Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8
1154dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived08virtual6Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8
1164dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived010return_aggEv_vfpthunk_, i32 0, i64 64418) to i64), i64 0 }, ptr %[[METHOD3]], align 8
1174dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived04sretEv_vfpthunk_, i32 0, i64 28187) to i64), i64 0 }, ptr %[[METHOD4]], align 8
1184dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_, i32 0, i64 8992) to i64), i64 0 }, ptr %[[METHOD5]], align 8
1194dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base18virtual7Ev_vfpthunk_, i32 0, i64 [[TYPEDISC2:61596]]) to i64), i64 0 }, ptr %[[METHOD6]], align 8
1204dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived18virtual7Ev_vfpthunk_, i32 0, i64 25206) to i64), i64 0 }, ptr %[[METHOD7]], align 8
1214dcd91aeSOliver Hunt // CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 25206) to i64), i64 0 }, ptr %[[METHOD7]], align 8
1224dcd91aeSOliver Hunt // CHECK: ret void
1234dcd91aeSOliver Hunt 
1244dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN5Base08virtual1Ev_vfpthunk_(ptr noundef %[[THIS:.*]])
1254dcd91aeSOliver Hunt // CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8
1264dcd91aeSOliver Hunt // CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8
1274dcd91aeSOliver Hunt // CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
1284dcd91aeSOliver Hunt // CHECK-NEXT: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
1294dcd91aeSOliver Hunt // CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8
1304dcd91aeSOliver Hunt // CHECK-NEXT: %[[V2:.*]] = ptrtoint ptr %[[VTABLE]] to i64
1314dcd91aeSOliver Hunt // CHECK-NEXT: %[[V3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V2]], i32 2, i64 0)
1324dcd91aeSOliver Hunt // CHECK-NEXT: %[[V4:.*]] = inttoptr i64 %[[V3]] to ptr
1334dcd91aeSOliver Hunt // CHECK-NEXT: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V4]], i64 0
1344dcd91aeSOliver Hunt // CHECK-NEXT: %[[V5:.*]] = load ptr, ptr %[[VFN]], align 8
1354dcd91aeSOliver Hunt // CHECK-NEXT: %[[V6:.*]] = ptrtoint ptr %[[VFN]] to i64
1364dcd91aeSOliver Hunt // CHECK-NEXT: %[[V7:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V6]], i64 55600)
1374dcd91aeSOliver Hunt // CHECK-NEXT: musttail call void %[[V5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V0]]) [ "ptrauth"(i32 0, i64 %[[V7]]) ]
1384dcd91aeSOliver Hunt // CHECK-NEXT: ret void
1394dcd91aeSOliver Hunt 
1404dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN5Base08virtual3Ev_vfpthunk_(ptr noundef %{{.*}})
1414dcd91aeSOliver Hunt // CHECK: load ptr, ptr %{{.*}}, align 8
1424dcd91aeSOliver Hunt // CHECK: load ptr, ptr %{{.*}}, align 8
1434dcd91aeSOliver Hunt // CHECK: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}, align 8
1444dcd91aeSOliver Hunt // CHECK: %[[V2:.*]] = ptrtoint ptr %[[VTABLE]] to i64
1454dcd91aeSOliver Hunt // CHECK: %[[V3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V2]], i32 2, i64 0)
1464dcd91aeSOliver Hunt // CHECK: %[[V4:.*]] = inttoptr i64 %[[V3]] to ptr
1474dcd91aeSOliver Hunt // CHECK: getelementptr inbounds ptr, ptr %[[V4]], i64 1
1484dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.blend(i64 %{{.*}}, i64 53007)
1494dcd91aeSOliver Hunt 
1504dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN5Base016virtual_variadicEiz_vfpthunk_(ptr noundef %[[THIS:.*]], i32 noundef %0, ...)
1514dcd91aeSOliver Hunt // CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8
1524dcd91aeSOliver Hunt // CHECK-NEXT: %[[_ADDR:.*]] = alloca i32, align 4
1534dcd91aeSOliver Hunt // CHECK-NEXT: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8
1544dcd91aeSOliver Hunt // CHECK: store i32 %0, ptr %[[_ADDR]], align 4
1554dcd91aeSOliver Hunt // CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
1564dcd91aeSOliver Hunt // CHECK-NEXT: %[[V1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
1574dcd91aeSOliver Hunt // CHECK-NEXT: %[[V2:.*]] = load i32, ptr %[[_ADDR]], align 4
1584dcd91aeSOliver Hunt // CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8
1594dcd91aeSOliver Hunt // CHECK-NEXT: %[[V4:.*]] = ptrtoint ptr %[[VTABLE]] to i64
1604dcd91aeSOliver Hunt // CHECK-NEXT: %[[V5:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V4]], i32 2, i64 0)
1614dcd91aeSOliver Hunt // CHECK-NEXT: %[[V6:.*]] = inttoptr i64 %[[V5]] to ptr
1624dcd91aeSOliver Hunt // CHECK-NEXT: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V6]], i64 2
1634dcd91aeSOliver Hunt // CHECK-NEXT: %[[V7:.*]] = load ptr, ptr %[[VFN]], align 8
1644dcd91aeSOliver Hunt // CHECK-NEXT: %[[V8:.*]] = ptrtoint ptr %[[VFN]] to i64
1654dcd91aeSOliver Hunt // CHECK-NEXT: %[[V9:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V8]], i64 7464)
1664dcd91aeSOliver Hunt // CHECK-NEXT: musttail call void (ptr, i32, ...) %[[V7]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V1]], i32 noundef %[[V2]], ...) [ "ptrauth"(i32 0, i64 %[[V9]]) ]
1674dcd91aeSOliver Hunt // CHECK-NEXT: ret void
1684dcd91aeSOliver Hunt 
1694dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN8Derived08virtual6Ev_vfpthunk_(ptr noundef %[[THIS:.*]])
1704dcd91aeSOliver Hunt // CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8
1714dcd91aeSOliver Hunt // CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8
1724dcd91aeSOliver Hunt // CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
1734dcd91aeSOliver Hunt // CHECK: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
1744dcd91aeSOliver Hunt // CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8
1754dcd91aeSOliver Hunt // CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64
1764dcd91aeSOliver Hunt // CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)
1774dcd91aeSOliver Hunt // CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr
1784dcd91aeSOliver Hunt // CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V3]], i64 3
1794dcd91aeSOliver Hunt // CHECK: %[[V5:.*]] = ptrtoint ptr %[[VFN]] to i64
1804dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.blend(i64 %[[V5]], i64 55535)
1814dcd91aeSOliver Hunt 
1824dcd91aeSOliver Hunt // Check that the return value of the musttail call isn't copied to a temporary.
1834dcd91aeSOliver Hunt 
1844dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden [2 x i64] @_ZN8Derived010return_aggEv_vfpthunk_(ptr noundef %{{.*}})
1854dcd91aeSOliver Hunt // CHECK: %[[CALL:.*]] = musttail call [2 x i64] %{{.*}}(ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) [ "ptrauth"(i32 0, i64 %{{.*}}) ]
1864dcd91aeSOliver Hunt // CHECK-NEXT: ret [2 x i64] %[[CALL]]
1874dcd91aeSOliver Hunt 
1884dcd91aeSOliver Hunt // Check that the sret pointer passed to the caller is forwarded to the musttail
1894dcd91aeSOliver Hunt // call.
1904dcd91aeSOliver Hunt 
1914dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN8Derived04sretEv_vfpthunk_(ptr dead_on_unwind noalias writable sret(%struct.A1) align 4 %[[AGG_RESULT:.*]], ptr noundef %{{.*}})
1924dcd91aeSOliver Hunt // CHECK: musttail call void %{{.*}}(ptr dead_on_unwind writable  sret(%struct.A1) align 4 %[[AGG_RESULT]], ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) [ "ptrauth"(i32 0, i64 %{{.*}}) ]
1934dcd91aeSOliver Hunt // CHECK-NEXT: ret void
1944dcd91aeSOliver Hunt 
1954dcd91aeSOliver Hunt // Check that the thunk function doesn't destruct the trivial_abi argument.
1964dcd91aeSOliver Hunt 
1974dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_(ptr noundef %{{.*}}, [2 x i64] %{{.*}})
1984dcd91aeSOliver Hunt // NODEBUG-NOT: call
1994dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.auth(
2004dcd91aeSOliver Hunt // NODEBUG-NOT: call
2014dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.blend(
2024dcd91aeSOliver Hunt // NODEBUG-NOT: call
2034dcd91aeSOliver Hunt // CHECK: musttail call void
2044dcd91aeSOliver Hunt // CHECK-NEXT: ret void
2054dcd91aeSOliver Hunt 
2064dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN5Base18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]])
2074dcd91aeSOliver Hunt // CHECK: entry:
2084dcd91aeSOliver Hunt // CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8
2094dcd91aeSOliver Hunt // CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8
2104dcd91aeSOliver Hunt // CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
2114dcd91aeSOliver Hunt // CHECK: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
2124dcd91aeSOliver Hunt // CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8
2134dcd91aeSOliver Hunt // CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64
2144dcd91aeSOliver Hunt // CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)
2154dcd91aeSOliver Hunt // CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr
2164dcd91aeSOliver Hunt // CHECK: getelementptr inbounds ptr, ptr %[[V3]], i64 0
2174dcd91aeSOliver Hunt 
2184dcd91aeSOliver Hunt // CHECK: define linkonce_odr hidden void @_ZN8Derived18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]])
2194dcd91aeSOliver Hunt // CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8
2204dcd91aeSOliver Hunt // CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8
2214dcd91aeSOliver Hunt // CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8
2224dcd91aeSOliver Hunt // CHECK: load ptr, ptr %[[THIS_ADDR]], align 8
2234dcd91aeSOliver Hunt // CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8
2244dcd91aeSOliver Hunt // CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64
2254dcd91aeSOliver Hunt // CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)
2264dcd91aeSOliver Hunt // CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr
2274dcd91aeSOliver Hunt // CHECK: getelementptr inbounds ptr, ptr %[[V3]], i64 3
2284dcd91aeSOliver Hunt 
2294dcd91aeSOliver Hunt void Base0::virtual1() {}
2304dcd91aeSOliver Hunt 
2314dcd91aeSOliver Hunt void test0() {
2324dcd91aeSOliver Hunt   MethodTy0 method0;
2334dcd91aeSOliver Hunt   method0 = &Base0::nonvirtual0;
2344dcd91aeSOliver Hunt   method0 = &Base0::virtual1;
2354dcd91aeSOliver Hunt   method0 = &Base0::virtual3;
2364dcd91aeSOliver Hunt 
2374dcd91aeSOliver Hunt   VariadicMethodTy0 varmethod1;
2384dcd91aeSOliver Hunt   varmethod1 = &Base0::virtual_variadic;
2394dcd91aeSOliver Hunt 
2404dcd91aeSOliver Hunt   MethodTy1 method2;
2414dcd91aeSOliver Hunt   method2 = &Derived0::nonvirtual0;
2424dcd91aeSOliver Hunt   method2 = &Derived0::virtual1;
2434dcd91aeSOliver Hunt   method2 = &Derived0::virtual3;
2444dcd91aeSOliver Hunt   method2 = &Derived0::nonvirtual5;
2454dcd91aeSOliver Hunt   method2 = &Derived0::virtual6;
2464dcd91aeSOliver Hunt 
2474dcd91aeSOliver Hunt   A0 (Derived0::*method3)();
2484dcd91aeSOliver Hunt   method3 = &Derived0::return_agg;
2494dcd91aeSOliver Hunt 
2504dcd91aeSOliver Hunt   A1 (Derived0::*method4)();
2514dcd91aeSOliver Hunt   method4 = &Derived0::sret;
2524dcd91aeSOliver Hunt 
2534dcd91aeSOliver Hunt   void (Derived0::*method5)(TrivialS);
2544dcd91aeSOliver Hunt   method5 = &Derived0::trivial_abi;
2554dcd91aeSOliver Hunt 
2564dcd91aeSOliver Hunt   void (Base1::*method6)();
2574dcd91aeSOliver Hunt   method6 = &Base1::virtual7;
2584dcd91aeSOliver Hunt 
2594dcd91aeSOliver Hunt   void (Derived1::*method7)();
2604dcd91aeSOliver Hunt   method7 = &Derived1::virtual7;
2614dcd91aeSOliver Hunt   method7 = &Derived1::virtual1;
2624dcd91aeSOliver Hunt }
2634dcd91aeSOliver Hunt 
26470c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z5test1P5Base0MS_FvvE(ptr noundef %[[A0:.*]], [2 x i64] %[[A1_COERCE:.*]])
2654dcd91aeSOliver Hunt // CHECK: %[[A1:.*]] = alloca { i64, i64 }, align 8
2664dcd91aeSOliver Hunt // CHECK: %[[A0_ADDR:.*]] = alloca ptr, align 8
2674dcd91aeSOliver Hunt // CHECK: %[[A1_ADDR:.*]] = alloca { i64, i64 }, align 8
2684dcd91aeSOliver Hunt // CHECK: store [2 x i64] %[[A1_COERCE]], ptr %[[A1]], align 8
2694dcd91aeSOliver Hunt // CHECK: %[[A11:.*]] = load { i64, i64 }, ptr %[[A1]], align 8
2704dcd91aeSOliver Hunt // CHECK: store ptr %[[A0]], ptr %[[A0_ADDR]], align 8
2714dcd91aeSOliver Hunt // CHECK: store { i64, i64 } %[[A11]], ptr %[[A1_ADDR]], align 8
2724dcd91aeSOliver Hunt // CHECK: %[[V1:.*]] = load ptr, ptr %[[A0_ADDR]], align 8
2734dcd91aeSOliver Hunt // CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[A1_ADDR]], align 8
2744dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1
2754dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_ADJ_SHIFTED:.*]] = ashr i64 %[[MEMPTR_ADJ]], 1
2764dcd91aeSOliver Hunt // CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 %[[MEMPTR_ADJ_SHIFTED]]
2774dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0
2784dcd91aeSOliver Hunt // CHECK: %[[V5:.*]] = and i64 %[[MEMPTR_ADJ]], 1
2794dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_ISVIRTUAL:.*]] = icmp ne i64 %[[V5]], 0
2804dcd91aeSOliver Hunt // CHECK: br i1 %[[MEMPTR_ISVIRTUAL]]
2814dcd91aeSOliver Hunt 
2824dcd91aeSOliver Hunt // CHECK:  %[[VTABLE:.*]] = load ptr, ptr %[[V4]], align 8
2834dcd91aeSOliver Hunt // CHECK:  %[[V7:.*]] = ptrtoint ptr %[[VTABLE]] to i64
2844dcd91aeSOliver Hunt // CHECK:  %[[V8:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V7]], i32 2, i64 0)
2854dcd91aeSOliver Hunt // CHECK:  %[[V9:.*]] = inttoptr i64 %[[V8]] to ptr
28670c6e79eSDaniil Kovalev // DARWIN: %[[V10:.*]] = trunc i64 %[[MEMPTR_PTR]] to i32
28770c6e79eSDaniil Kovalev // DARWIN: %[[V11:.*]] = zext i32 %[[V10]] to i64
28870c6e79eSDaniil Kovalev // DARWIN: %[[V12:.*]] = getelementptr i8, ptr %[[V9]], i64 %[[V11]]
28970c6e79eSDaniil Kovalev // ELF:    %[[V12:.*]] = getelementptr i8, ptr %[[V9]], i64 %[[MEMPTR_PTR]]
2904dcd91aeSOliver Hunt // CHECK:  %[[MEMPTR_VIRTUALFN:.*]] = load ptr, ptr %[[V12]], align 8
2914dcd91aeSOliver Hunt // CHECK:  br
2924dcd91aeSOliver Hunt 
2934dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_NONVIRTUALFN:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr
2944dcd91aeSOliver Hunt // CHECK: br
2954dcd91aeSOliver Hunt 
2964dcd91aeSOliver Hunt // CHECK: %[[V14:.*]] = phi ptr [ %[[MEMPTR_VIRTUALFN]], {{.*}} ], [ %[[MEMPTR_NONVIRTUALFN]], {{.*}} ]
2974dcd91aeSOliver Hunt // CHECK: %[[V15:.*]] = phi i64 [ 0, {{.*}} ], [ [[TYPEDISC0]], {{.*}} ]
2984dcd91aeSOliver Hunt // CHECK: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V4]]) [ "ptrauth"(i32 0, i64 %[[V15]]) ]
2994dcd91aeSOliver Hunt // CHECK: ret void
3004dcd91aeSOliver Hunt 
3014dcd91aeSOliver Hunt void test1(Base0 *a0, MethodTy0 a1) {
3024dcd91aeSOliver Hunt   (a0->*a1)();
3034dcd91aeSOliver Hunt }
3044dcd91aeSOliver Hunt 
305*485c80e1SAkira Hatanaka // CXX17: define{{.*}} void @_Z14test1_noexceptP5Base0MS_DoFvvE(
306*485c80e1SAkira Hatanaka // CXX17: %[[V14:.*]] = phi ptr [ %{{.*}}, {{.*}} ], [ %{{.*}}, {{.*}} ]
307*485c80e1SAkira Hatanaka // CXX17: %[[V15:.*]] = phi i64 [ 0, {{.*}} ], [ [[TYPEDISC0]], {{.*}} ]
308*485c80e1SAkira Hatanaka // CXX17: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) {{.*}}[ "ptrauth"(i32 0, i64 %[[V15]]) ]
309*485c80e1SAkira Hatanaka #if __cplusplus >= 201703L
310*485c80e1SAkira Hatanaka void test1_noexcept(Base0 *a0, NoExceptMethodTy0 a1) {
311*485c80e1SAkira Hatanaka   (a0->*a1)();
312*485c80e1SAkira Hatanaka }
313*485c80e1SAkira Hatanaka #endif
314*485c80e1SAkira Hatanaka 
31570c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z15testConversion0M5Base0FvvEM8Derived0FvvE([2 x i64] %[[METHOD0_COERCE:.*]], [2 x i64] %[[METHOD1_COERCE:.*]])
3164dcd91aeSOliver Hunt // CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8
3174dcd91aeSOliver Hunt // CHECK: %[[METHOD1:.*]] = alloca { i64, i64 }, align 8
3184dcd91aeSOliver Hunt // CHECK: %[[METHOD0_ADDR:.*]] = alloca { i64, i64 }, align 8
3194dcd91aeSOliver Hunt // CHECK: %[[METHOD1_ADDR:.*]] = alloca { i64, i64 }, align 8
3204dcd91aeSOliver Hunt // CHECK: store [2 x i64] %[[METHOD0_COERCE]], ptr %[[METHOD0]], align 8
3214dcd91aeSOliver Hunt // CHECK: %[[METHOD01:.*]] = load { i64, i64 }, ptr %[[METHOD0]], align 8
3224dcd91aeSOliver Hunt // CHECK: store [2 x i64] %[[METHOD1_COERCE]], ptr %[[METHOD1]], align 8
3234dcd91aeSOliver Hunt // CHECK: %[[METHOD12:.*]] = load { i64, i64 }, ptr %[[METHOD1]], align 8
3244dcd91aeSOliver Hunt // CHECK: store { i64, i64 } %[[METHOD01]], ptr %[[METHOD0_ADDR]], align 8
3254dcd91aeSOliver Hunt // CHECK: store { i64, i64 } %[[METHOD12]], ptr %[[METHOD1_ADDR]], align 8
3264dcd91aeSOliver Hunt // CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[METHOD0_ADDR]], align 8
3274dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0
3284dcd91aeSOliver Hunt // CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1
3294dcd91aeSOliver Hunt // CHECK: %[[V3:.*]] = and i64 %[[MEMPTR_ADJ]], 1
3304dcd91aeSOliver Hunt // CHECK: %[[IS_VIRTUAL_OFFSET:.*]] = icmp ne i64 %[[V3]], 0
3314dcd91aeSOliver Hunt // CHECK: br i1 %[[IS_VIRTUAL_OFFSET]]
3324dcd91aeSOliver Hunt 
3334dcd91aeSOliver Hunt // CHECK: %[[V4:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr
3344dcd91aeSOliver Hunt // CHECK: %[[V5:.*]] = icmp ne ptr %[[V4]], null
3354dcd91aeSOliver Hunt // CHECK: br i1 %[[V5]]
3364dcd91aeSOliver Hunt 
3374dcd91aeSOliver Hunt // CHECK: %[[V6:.*]] = ptrtoint ptr %[[V4]] to i64
3384dcd91aeSOliver Hunt // CHECK: %[[V7:.*]] = call i64 @llvm.ptrauth.resign(i64 %[[V6]], i32 0, i64 [[TYPEDISC0]], i32 0, i64 [[TYPEDISC1]])
3394dcd91aeSOliver Hunt // CHECK: %[[V8:.*]] = inttoptr i64 %[[V7]] to ptr
3404dcd91aeSOliver Hunt // CHECK: br
3414dcd91aeSOliver Hunt 
3424dcd91aeSOliver Hunt // CHECK: %[[V9:.*]] = phi ptr [ null, {{.*}} ], [ %[[V8]], {{.*}} ]
3434dcd91aeSOliver Hunt // CHECK: %[[V1:.*]] = ptrtoint ptr %[[V9]] to i64
3444dcd91aeSOliver Hunt // CHECK: %[[V11:.*]] = insertvalue { i64, i64 } %[[V2]], i64 %[[V1]], 0
3454dcd91aeSOliver Hunt // CHECK: br
3464dcd91aeSOliver Hunt 
3474dcd91aeSOliver Hunt // CHECK: %[[V12:.*]] = phi { i64, i64 } [ %[[V2]], {{.*}} ], [ %[[V11]], {{.*}} ]
3484dcd91aeSOliver Hunt // CHECK: store { i64, i64 } %[[V12]], ptr %[[METHOD1_ADDR]], align 8
3494dcd91aeSOliver Hunt // CHECK: ret void
3504dcd91aeSOliver Hunt 
3514dcd91aeSOliver Hunt void testConversion0(MethodTy0 method0, MethodTy1 method1) {
3524dcd91aeSOliver Hunt   method1 = method0;
3534dcd91aeSOliver Hunt }
3544dcd91aeSOliver Hunt 
35570c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z15testConversion1M5Base0FvvE(
3564dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC0]], i32 0, i64 [[TYPEDISC1]])
3574dcd91aeSOliver Hunt 
3584dcd91aeSOliver Hunt void testConversion1(MethodTy0 method0) {
3594dcd91aeSOliver Hunt   MethodTy1 method1 = reinterpret_cast<MethodTy1>(method0);
3604dcd91aeSOliver Hunt }
3614dcd91aeSOliver Hunt 
36270c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z15testConversion2M8Derived0FvvE(
3634dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC1]], i32 0, i64 [[TYPEDISC0]])
3644dcd91aeSOliver Hunt 
3654dcd91aeSOliver Hunt void testConversion2(MethodTy1 method1) {
3664dcd91aeSOliver Hunt   MethodTy0 method0 = static_cast<MethodTy0>(method1);
3674dcd91aeSOliver Hunt }
3684dcd91aeSOliver Hunt 
36970c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z15testConversion3M8Derived0FvvE(
3704dcd91aeSOliver Hunt // CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC1]], i32 0, i64 [[TYPEDISC0]])
3714dcd91aeSOliver Hunt 
3724dcd91aeSOliver Hunt void testConversion3(MethodTy1 method1) {
3734dcd91aeSOliver Hunt   MethodTy0 method0 = reinterpret_cast<MethodTy0>(method1);
3744dcd91aeSOliver Hunt }
3754dcd91aeSOliver Hunt 
3764dcd91aeSOliver Hunt // No need to call @llvm.ptrauth.resign if the source member function
3774dcd91aeSOliver Hunt // pointer is a constant.
3784dcd91aeSOliver Hunt 
37970c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z15testConversion4v(
3804dcd91aeSOliver Hunt // CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8
3814dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8
3824dcd91aeSOliver Hunt // CHECK: ret void
3834dcd91aeSOliver Hunt 
3844dcd91aeSOliver Hunt void testConversion4() {
3854dcd91aeSOliver Hunt   MethodTy0 method0 = reinterpret_cast<MethodTy0>(&Derived0::virtual1);
3864dcd91aeSOliver Hunt }
3874dcd91aeSOliver Hunt 
3884dcd91aeSOliver Hunt // This code used to crash.
3894dcd91aeSOliver Hunt namespace testNonVirtualThunk {
3904dcd91aeSOliver Hunt   struct R {};
3914dcd91aeSOliver Hunt 
3924dcd91aeSOliver Hunt   struct B0 {
3934dcd91aeSOliver Hunt     virtual void bar();
3944dcd91aeSOliver Hunt   };
3954dcd91aeSOliver Hunt 
3964dcd91aeSOliver Hunt   struct B1 {
3974dcd91aeSOliver Hunt     virtual R foo();
3984dcd91aeSOliver Hunt   };
3994dcd91aeSOliver Hunt 
4004dcd91aeSOliver Hunt   struct D : B0, B1 {
4014dcd91aeSOliver Hunt     virtual R foo();
4024dcd91aeSOliver Hunt   };
4034dcd91aeSOliver Hunt 
4044dcd91aeSOliver Hunt   D d;
4054dcd91aeSOliver Hunt }
4064dcd91aeSOliver Hunt 
4074dcd91aeSOliver Hunt // CHECK: define internal void @_ZN22TestAnonymousNamespace12_GLOBAL__N_11S3fooEv_vfpthunk_(
4084dcd91aeSOliver Hunt 
4094dcd91aeSOliver Hunt namespace TestAnonymousNamespace {
4104dcd91aeSOliver Hunt namespace {
4114dcd91aeSOliver Hunt struct S {
4124dcd91aeSOliver Hunt   virtual void foo(){};
4134dcd91aeSOliver Hunt };
4144dcd91aeSOliver Hunt } // namespace
4154dcd91aeSOliver Hunt 
4164dcd91aeSOliver Hunt void test() {
4174dcd91aeSOliver Hunt   auto t = &S::foo;
4184dcd91aeSOliver Hunt }
4194dcd91aeSOliver Hunt } // namespace TestAnonymousNamespace
4204dcd91aeSOliver Hunt 
4214dcd91aeSOliver Hunt MethodTy1 gmethod0 = reinterpret_cast<MethodTy1>(&Base0::nonvirtual0);
4224dcd91aeSOliver Hunt MethodTy0 gmethod1 = reinterpret_cast<MethodTy0>(&Derived0::nonvirtual5);
4234dcd91aeSOliver Hunt MethodTy0 gmethod2 = reinterpret_cast<MethodTy0>(&Derived0::virtual1);
4244dcd91aeSOliver Hunt 
42570c6e79eSDaniil Kovalev // CHECK-LABEL: define{{.*}} void @_Z13testArrayInitv()
4264dcd91aeSOliver Hunt // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p0, ptr align 8 @__const._Z13testArrayInitv.p0, i64 16, i1 false)
4274dcd91aeSOliver Hunt // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p1, ptr align 8 @__const._Z13testArrayInitv.p1, i64 16, i1 false)
4284dcd91aeSOliver Hunt // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c0, ptr align 8 @__const._Z13testArrayInitv.c0, i64 16, i1 false)
4294dcd91aeSOliver Hunt // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c1, ptr align 8 @__const._Z13testArrayInitv.c1, i64 16, i1 false)
4304dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %{{.*}} align 8
4314dcd91aeSOliver Hunt // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %{{.*}}, align 8
4324dcd91aeSOliver Hunt 
4334dcd91aeSOliver Hunt void initList(std::initializer_list<MethodTy1>);
4344dcd91aeSOliver Hunt 
4354dcd91aeSOliver Hunt void testArrayInit() {
4364dcd91aeSOliver Hunt   MethodTy1 p0[] = {&Base0::nonvirtual0};
4374dcd91aeSOliver Hunt   MethodTy1 p1[] = {&Base0::virtual1};
4384dcd91aeSOliver Hunt   Class0 c0{&Base0::nonvirtual0};
4394dcd91aeSOliver Hunt   Class0 c1{&Base0::virtual1};
4404dcd91aeSOliver Hunt   initList({&Base0::nonvirtual0});
4414dcd91aeSOliver Hunt   initList({&Base0::virtual1});
4424dcd91aeSOliver Hunt }
4434dcd91aeSOliver Hunt 
4444dcd91aeSOliver Hunt 
4454dcd91aeSOliver Hunt 
4464dcd91aeSOliver Hunt // STACK-PROT: define {{.*}}_vfpthunk{{.*}}[[ATTRS:#[0-9]+]]
4474dcd91aeSOliver Hunt // STACK-PROT: attributes [[ATTRS]] =
4484dcd91aeSOliver Hunt // STACK-PROT-NOT: ssp
4494dcd91aeSOliver Hunt // STACK-PROT-NOT: sspstrong
4504dcd91aeSOliver Hunt // STACK-PROT-NOT: sspreq
4514dcd91aeSOliver Hunt // STACK-PROT-NEXT: attributes
4524dcd91aeSOliver Hunt 
45370c6e79eSDaniil Kovalev // CHECK: define{{.*}} void @_Z15testConvertNullv(
4544dcd91aeSOliver Hunt // CHECK: %[[T:.*]] = alloca { i64, i64 },
4554dcd91aeSOliver Hunt // store { i64, i64 } zeroinitializer, { i64, i64 }* %[[T]],
4564dcd91aeSOliver Hunt 
4574dcd91aeSOliver Hunt void testConvertNull() {
4584dcd91aeSOliver Hunt   VariadicMethodTy0 t = (VariadicMethodTy0)(MethodTy0{});
4594dcd91aeSOliver Hunt }
460*485c80e1SAkira Hatanaka 
461*485c80e1SAkira Hatanaka namespace testNoexceptConversion {
462*485c80e1SAkira Hatanaka 
463*485c80e1SAkira Hatanaka // CHECK-LABEL: define internal void @__cxx_global_var_init()
464*485c80e1SAkira Hatanaka // CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8
465*485c80e1SAkira Hatanaka // CHECK: store { i64, i64 } %[[V0]], ptr @_ZN22testNoexceptConversion6mfptr4E, align 8
466*485c80e1SAkira Hatanaka 
467*485c80e1SAkira Hatanaka // CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test0Ev()
468*485c80e1SAkira Hatanaka // CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8
469*485c80e1SAkira Hatanaka // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, ptr %[[P0]], align 8,
470*485c80e1SAkira Hatanaka 
471*485c80e1SAkira Hatanaka // CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test1Ev()
472*485c80e1SAkira Hatanaka // CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8
473*485c80e1SAkira Hatanaka // CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S16virtual_noexceptEv_vfpthunk_, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, ptr %[[P0]], align 8,
474*485c80e1SAkira Hatanaka 
475*485c80e1SAkira Hatanaka // CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test2Ev()
476*485c80e1SAkira Hatanaka // CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8
477*485c80e1SAkira Hatanaka // CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8
478*485c80e1SAkira Hatanaka // CHECK: store { i64, i64 } %[[V0]], ptr %[[P0]], align 8,
479*485c80e1SAkira Hatanaka 
480*485c80e1SAkira Hatanaka struct S {
481*485c80e1SAkira Hatanaka   void nonvirtual_noexcept() noexcept;
482*485c80e1SAkira Hatanaka   virtual void virtual_noexcept() noexcept;
483*485c80e1SAkira Hatanaka };
484*485c80e1SAkira Hatanaka 
485*485c80e1SAkira Hatanaka void (S::*mfptr0_noexcept)() noexcept;
486*485c80e1SAkira Hatanaka void (S::*mfptr1)() = &S::nonvirtual_noexcept;
487*485c80e1SAkira Hatanaka void (S::*mfptr2)() = &S::virtual_noexcept;
488*485c80e1SAkira Hatanaka void (S::*mfptr3_noexcept)() noexcept = &S::nonvirtual_noexcept;
489*485c80e1SAkira Hatanaka void (S::*mfptr4)() = mfptr0_noexcept;
490*485c80e1SAkira Hatanaka 
491*485c80e1SAkira Hatanaka void test0() {
492*485c80e1SAkira Hatanaka   void (S::*p0)() = &S::nonvirtual_noexcept;
493*485c80e1SAkira Hatanaka }
494*485c80e1SAkira Hatanaka 
495*485c80e1SAkira Hatanaka void test1() {
496*485c80e1SAkira Hatanaka   void (S::*p0)() = &S::virtual_noexcept;
497*485c80e1SAkira Hatanaka }
498*485c80e1SAkira Hatanaka 
499*485c80e1SAkira Hatanaka void test2() {
500*485c80e1SAkira Hatanaka   void (S::*p0)() = mfptr0_noexcept;
501*485c80e1SAkira Hatanaka }
502*485c80e1SAkira Hatanaka 
503*485c80e1SAkira Hatanaka }
504