brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.4 KiB · e9436f1 Raw
504 lines · cpp
1// 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 %s2// 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 %s3// 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 %s4// 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-PROT5// 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-PROT6// 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-PROT7 8// 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 %s9// 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 %s10// 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 %s11// 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-PROT12// 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-PROT13// 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-PROT14 15 16// CHECK: @gmethod0 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1:35591]]) to i64), i64 0 }, align 817// CHECK: @gmethod1 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011nonvirtual5Ev, i32 0, i64 [[TYPEDISC0:22163]]) to i64), i64 0 }, align 818// CHECK: @gmethod2 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, align 819 20// 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 821// 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 822// 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 823// 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 824 25// CHECK: @_ZN22testNoexceptConversion6mfptr1E = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3:.*]]) to i64), i64 0 },26// CHECK: @_ZN22testNoexceptConversion6mfptr2E = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S16virtual_noexceptEv_vfpthunk_, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 },27// CHECK: @_ZN22testNoexceptConversion15mfptr3_noexceptE = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 },28 29// CHECK: @_ZTV5Base0 = unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI5Base0,30// CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual1Ev, i32 0, i64 55600, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 2)),31// CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual3Ev, i32 0, i64 53007, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 3)),32// 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 833 34typedef __SIZE_TYPE__ size_t;35 36namespace std {37template <typename _Ep>38class initializer_list {39  const _Ep *__begin_;40  size_t __size_;41 42  initializer_list(const _Ep *__b, size_t __s);43};44} // namespace std45 46struct Base0 {47  void nonvirtual0();48  virtual void virtual1();49  virtual void virtual3();50  virtual void virtual_variadic(int, ...);51};52 53struct A0 {54  int d[4];55};56 57struct A1 {58  int d[8];59};60 61struct __attribute__((trivial_abi)) TrivialS {62  TrivialS(const TrivialS &);63  ~TrivialS();64  int p[4];65};66 67struct Derived0 : Base0 {68  void virtual1() override;69  void nonvirtual5();70  virtual void virtual6();71  virtual A0 return_agg();72  virtual A1 sret();73  virtual void trivial_abi(TrivialS);74};75 76struct Base1 {77  virtual void virtual7();78};79 80struct Derived1 : Base0, Base1 {81  void virtual1() override;82  void virtual7() override;83};84 85typedef void (Base0::*MethodTy0)();86#if __cplusplus >= 201703L87typedef void (Base0::*NoExceptMethodTy0)() noexcept;88#endif89typedef void (Base0::*VariadicMethodTy0)(int, ...);90typedef void (Derived0::*MethodTy1)();91 92struct Class0 {93  MethodTy1 m0;94};95 96// CHECK: define{{.*}} void @_ZN5Base08virtual1Ev(97 98// CHECK: define{{.*}} void @_Z5test0v()99// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8100// CHECK-NEXT: %[[VARMETHOD1:.*]] = alloca { i64, i64 }, align 8101// CHECK-NEXT: %[[METHOD2:.*]] = alloca { i64, i64 }, align 8102// CHECK-NEXT: %[[METHOD3:.*]] = alloca { i64, i64 }, align 8103// CHECK-NEXT: %[[METHOD4:.*]] = alloca { i64, i64 }, align 8104// CHECK-NEXT: %[[METHOD5:.*]] = alloca { i64, i64 }, align 8105// CHECK-NEXT: %[[METHOD6:.*]] = alloca { i64, i64 }, align 8106// CHECK-NEXT: %[[METHOD7:.*]] = alloca { i64, i64 }, align 8107// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8108// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8109// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual3Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8110// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base016virtual_variadicEiz_vfpthunk_, i32 0, i64 34368) to i64), i64 0 }, ptr %[[VARMETHOD1]], align 8111// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8112// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8113// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual3Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8114// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011nonvirtual5Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8115// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived08virtual6Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8116// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived010return_aggEv_vfpthunk_, i32 0, i64 64418) to i64), i64 0 }, ptr %[[METHOD3]], align 8117// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived04sretEv_vfpthunk_, i32 0, i64 28187) to i64), i64 0 }, ptr %[[METHOD4]], align 8118// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_, i32 0, i64 8992) to i64), i64 0 }, ptr %[[METHOD5]], align 8119// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base18virtual7Ev_vfpthunk_, i32 0, i64 [[TYPEDISC2:61596]]) to i64), i64 0 }, ptr %[[METHOD6]], align 8120// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived18virtual7Ev_vfpthunk_, i32 0, i64 25206) to i64), i64 0 }, ptr %[[METHOD7]], align 8121// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 25206) to i64), i64 0 }, ptr %[[METHOD7]], align 8122// CHECK: ret void123 124// CHECK: define linkonce_odr hidden void @_ZN5Base08virtual1Ev_vfpthunk_(ptr noundef %[[THIS:.*]])125// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8126// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8127// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8128// CHECK-NEXT: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8129// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8130// CHECK-NEXT: %[[V2:.*]] = ptrtoint ptr %[[VTABLE]] to i64131// CHECK-NEXT: %[[V3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V2]], i32 2, i64 0)132// CHECK-NEXT: %[[V4:.*]] = inttoptr i64 %[[V3]] to ptr133// CHECK-NEXT: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V4]], i64 0134// CHECK-NEXT: %[[V5:.*]] = load ptr, ptr %[[VFN]], align 8135// CHECK-NEXT: %[[V6:.*]] = ptrtoint ptr %[[VFN]] to i64136// CHECK-NEXT: %[[V7:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V6]], i64 55600)137// CHECK-NEXT: musttail call void %[[V5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V0]]) [ "ptrauth"(i32 0, i64 %[[V7]]) ]138// CHECK-NEXT: ret void139 140// CHECK: define linkonce_odr hidden void @_ZN5Base08virtual3Ev_vfpthunk_(ptr noundef %{{.*}})141// CHECK: load ptr, ptr %{{.*}}, align 8142// CHECK: load ptr, ptr %{{.*}}, align 8143// CHECK: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}, align 8144// CHECK: %[[V2:.*]] = ptrtoint ptr %[[VTABLE]] to i64145// CHECK: %[[V3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V2]], i32 2, i64 0)146// CHECK: %[[V4:.*]] = inttoptr i64 %[[V3]] to ptr147// CHECK: getelementptr inbounds ptr, ptr %[[V4]], i64 1148// CHECK: call i64 @llvm.ptrauth.blend(i64 %{{.*}}, i64 53007)149 150// CHECK: define linkonce_odr hidden void @_ZN5Base016virtual_variadicEiz_vfpthunk_(ptr noundef %[[THIS:.*]], i32 noundef %0, ...)151// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8152// CHECK-NEXT: %[[_ADDR:.*]] = alloca i32, align 4153// CHECK-NEXT: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8154// CHECK: store i32 %0, ptr %[[_ADDR]], align 4155// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8156// CHECK-NEXT: %[[V1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8157// CHECK-NEXT: %[[V2:.*]] = load i32, ptr %[[_ADDR]], align 4158// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8159// CHECK-NEXT: %[[V4:.*]] = ptrtoint ptr %[[VTABLE]] to i64160// CHECK-NEXT: %[[V5:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V4]], i32 2, i64 0)161// CHECK-NEXT: %[[V6:.*]] = inttoptr i64 %[[V5]] to ptr162// CHECK-NEXT: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V6]], i64 2163// CHECK-NEXT: %[[V7:.*]] = load ptr, ptr %[[VFN]], align 8164// CHECK-NEXT: %[[V8:.*]] = ptrtoint ptr %[[VFN]] to i64165// CHECK-NEXT: %[[V9:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V8]], i64 7464)166// 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]]) ]167// CHECK-NEXT: ret void168 169// CHECK: define linkonce_odr hidden void @_ZN8Derived08virtual6Ev_vfpthunk_(ptr noundef %[[THIS:.*]])170// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8171// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8172// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8173// CHECK: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8174// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8175// CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64176// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)177// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr178// CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V3]], i64 3 179// CHECK: %[[V5:.*]] = ptrtoint ptr %[[VFN]] to i64180// CHECK: call i64 @llvm.ptrauth.blend(i64 %[[V5]], i64 55535)181 182// Check that the return value of the musttail call isn't copied to a temporary.183 184// CHECK: define linkonce_odr hidden [2 x i64] @_ZN8Derived010return_aggEv_vfpthunk_(ptr noundef %{{.*}})185// CHECK: %[[CALL:.*]] = musttail call [2 x i64] %{{.*}}(ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) [ "ptrauth"(i32 0, i64 %{{.*}}) ]186// CHECK-NEXT: ret [2 x i64] %[[CALL]]187 188// Check that the sret pointer passed to the caller is forwarded to the musttail189// call.190 191// CHECK: define linkonce_odr hidden void @_ZN8Derived04sretEv_vfpthunk_(ptr dead_on_unwind noalias writable sret(%struct.A1) align 4 %[[AGG_RESULT:.*]], ptr noundef %{{.*}})192// 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 %{{.*}}) ]193// CHECK-NEXT: ret void194 195// Check that the thunk function doesn't destruct the trivial_abi argument.196 197// CHECK: define linkonce_odr hidden void @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_(ptr noundef %{{.*}}, [2 x i64] %{{.*}})198// NODEBUG-NOT: call199// CHECK: call i64 @llvm.ptrauth.auth(200// NODEBUG-NOT: call201// CHECK: call i64 @llvm.ptrauth.blend(202// NODEBUG-NOT: call203// CHECK: musttail call void204// CHECK-NEXT: ret void205 206// CHECK: define linkonce_odr hidden void @_ZN5Base18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]])207// CHECK: entry:208// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8209// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8210// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8211// CHECK: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8212// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8213// CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64214// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)215// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr216// CHECK: getelementptr inbounds ptr, ptr %[[V3]], i64 0217 218// CHECK: define linkonce_odr hidden void @_ZN8Derived18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]])219// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8220// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8221// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8222// CHECK: load ptr, ptr %[[THIS_ADDR]], align 8223// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8224// CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64225// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)226// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr227// CHECK: getelementptr inbounds ptr, ptr %[[V3]], i64 3228 229void Base0::virtual1() {}230 231void test0() {232  MethodTy0 method0;233  method0 = &Base0::nonvirtual0;234  method0 = &Base0::virtual1;235  method0 = &Base0::virtual3;236 237  VariadicMethodTy0 varmethod1;238  varmethod1 = &Base0::virtual_variadic;239 240  MethodTy1 method2;241  method2 = &Derived0::nonvirtual0;242  method2 = &Derived0::virtual1;243  method2 = &Derived0::virtual3;244  method2 = &Derived0::nonvirtual5;245  method2 = &Derived0::virtual6;246 247  A0 (Derived0::*method3)();248  method3 = &Derived0::return_agg;249 250  A1 (Derived0::*method4)();251  method4 = &Derived0::sret;252 253  void (Derived0::*method5)(TrivialS);254  method5 = &Derived0::trivial_abi;255 256  void (Base1::*method6)();257  method6 = &Base1::virtual7;258 259  void (Derived1::*method7)();260  method7 = &Derived1::virtual7;261  method7 = &Derived1::virtual1;262}263 264// CHECK: define{{.*}} void @_Z5test1P5Base0MS_FvvE(ptr noundef %[[A0:.*]], [2 x i64] %[[A1_COERCE:.*]])265// CHECK: %[[A1:.*]] = alloca { i64, i64 }, align 8266// CHECK: %[[A0_ADDR:.*]] = alloca ptr, align 8267// CHECK: %[[A1_ADDR:.*]] = alloca { i64, i64 }, align 8268// CHECK: store [2 x i64] %[[A1_COERCE]], ptr %[[A1]], align 8269// CHECK: %[[A11:.*]] = load { i64, i64 }, ptr %[[A1]], align 8270// CHECK: store ptr %[[A0]], ptr %[[A0_ADDR]], align 8271// CHECK: store { i64, i64 } %[[A11]], ptr %[[A1_ADDR]], align 8272// CHECK: %[[V1:.*]] = load ptr, ptr %[[A0_ADDR]], align 8273// CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[A1_ADDR]], align 8274// CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1275// CHECK: %[[MEMPTR_ADJ_SHIFTED:.*]] = ashr i64 %[[MEMPTR_ADJ]], 1276// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 %[[MEMPTR_ADJ_SHIFTED]]277// CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0278// CHECK: %[[V5:.*]] = and i64 %[[MEMPTR_ADJ]], 1279// CHECK: %[[MEMPTR_ISVIRTUAL:.*]] = icmp ne i64 %[[V5]], 0280// CHECK: br i1 %[[MEMPTR_ISVIRTUAL]]281 282// CHECK:  %[[VTABLE:.*]] = load ptr, ptr %[[V4]], align 8283// CHECK:  %[[V7:.*]] = ptrtoint ptr %[[VTABLE]] to i64284// CHECK:  %[[V8:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V7]], i32 2, i64 0)285// CHECK:  %[[V9:.*]] = inttoptr i64 %[[V8]] to ptr286// DARWIN: %[[V10:.*]] = trunc i64 %[[MEMPTR_PTR]] to i32287// DARWIN: %[[V11:.*]] = zext i32 %[[V10]] to i64288// DARWIN: %[[V12:.*]] = getelementptr i8, ptr %[[V9]], i64 %[[V11]]289// ELF:    %[[V12:.*]] = getelementptr i8, ptr %[[V9]], i64 %[[MEMPTR_PTR]]290// CHECK:  %[[MEMPTR_VIRTUALFN:.*]] = load ptr, ptr %[[V12]], align 8291// CHECK:  br292 293// CHECK: %[[MEMPTR_NONVIRTUALFN:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr294// CHECK: br295 296// CHECK: %[[V14:.*]] = phi ptr [ %[[MEMPTR_VIRTUALFN]], {{.*}} ], [ %[[MEMPTR_NONVIRTUALFN]], {{.*}} ]297// CHECK: %[[V15:.*]] = phi i64 [ 0, {{.*}} ], [ [[TYPEDISC0]], {{.*}} ]298// CHECK: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V4]]) [ "ptrauth"(i32 0, i64 %[[V15]]) ]299// CHECK: ret void300 301void test1(Base0 *a0, MethodTy0 a1) {302  (a0->*a1)();303}304 305// CXX17: define{{.*}} void @_Z14test1_noexceptP5Base0MS_DoFvvE(306// CXX17: %[[V14:.*]] = phi ptr [ %{{.*}}, {{.*}} ], [ %{{.*}}, {{.*}} ]307// CXX17: %[[V15:.*]] = phi i64 [ 0, {{.*}} ], [ [[TYPEDISC0]], {{.*}} ]308// CXX17: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) {{.*}}[ "ptrauth"(i32 0, i64 %[[V15]]) ]309#if __cplusplus >= 201703L310void test1_noexcept(Base0 *a0, NoExceptMethodTy0 a1) {311  (a0->*a1)();312}313#endif314 315// CHECK: define{{.*}} void @_Z15testConversion0M5Base0FvvEM8Derived0FvvE([2 x i64] %[[METHOD0_COERCE:.*]], [2 x i64] %[[METHOD1_COERCE:.*]])316// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8317// CHECK: %[[METHOD1:.*]] = alloca { i64, i64 }, align 8318// CHECK: %[[METHOD0_ADDR:.*]] = alloca { i64, i64 }, align 8319// CHECK: %[[METHOD1_ADDR:.*]] = alloca { i64, i64 }, align 8320// CHECK: store [2 x i64] %[[METHOD0_COERCE]], ptr %[[METHOD0]], align 8321// CHECK: %[[METHOD01:.*]] = load { i64, i64 }, ptr %[[METHOD0]], align 8322// CHECK: store [2 x i64] %[[METHOD1_COERCE]], ptr %[[METHOD1]], align 8323// CHECK: %[[METHOD12:.*]] = load { i64, i64 }, ptr %[[METHOD1]], align 8324// CHECK: store { i64, i64 } %[[METHOD01]], ptr %[[METHOD0_ADDR]], align 8325// CHECK: store { i64, i64 } %[[METHOD12]], ptr %[[METHOD1_ADDR]], align 8326// CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[METHOD0_ADDR]], align 8327// CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0328// CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1329// CHECK: %[[V3:.*]] = and i64 %[[MEMPTR_ADJ]], 1330// CHECK: %[[IS_VIRTUAL_OFFSET:.*]] = icmp ne i64 %[[V3]], 0331// CHECK: br i1 %[[IS_VIRTUAL_OFFSET]]332 333// CHECK: %[[V4:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr334// CHECK: %[[V5:.*]] = icmp ne ptr %[[V4]], null335// CHECK: br i1 %[[V5]]336 337// CHECK: %[[V6:.*]] = ptrtoint ptr %[[V4]] to i64338// CHECK: %[[V7:.*]] = call i64 @llvm.ptrauth.resign(i64 %[[V6]], i32 0, i64 [[TYPEDISC0]], i32 0, i64 [[TYPEDISC1]])339// CHECK: %[[V8:.*]] = inttoptr i64 %[[V7]] to ptr340// CHECK: br341 342// CHECK: %[[V9:.*]] = phi ptr [ null, {{.*}} ], [ %[[V8]], {{.*}} ]343// CHECK: %[[V1:.*]] = ptrtoint ptr %[[V9]] to i64344// CHECK: %[[V11:.*]] = insertvalue { i64, i64 } %[[V2]], i64 %[[V1]], 0345// CHECK: br346 347// CHECK: %[[V12:.*]] = phi { i64, i64 } [ %[[V2]], {{.*}} ], [ %[[V11]], {{.*}} ]348// CHECK: store { i64, i64 } %[[V12]], ptr %[[METHOD1_ADDR]], align 8349// CHECK: ret void350 351void testConversion0(MethodTy0 method0, MethodTy1 method1) {352  method1 = method0;353}354 355// CHECK: define{{.*}} void @_Z15testConversion1M5Base0FvvE(356// CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC0]], i32 0, i64 [[TYPEDISC1]])357 358void testConversion1(MethodTy0 method0) {359  MethodTy1 method1 = reinterpret_cast<MethodTy1>(method0);360}361 362// CHECK: define{{.*}} void @_Z15testConversion2M8Derived0FvvE(363// CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC1]], i32 0, i64 [[TYPEDISC0]])364 365void testConversion2(MethodTy1 method1) {366  MethodTy0 method0 = static_cast<MethodTy0>(method1);367}368 369// CHECK: define{{.*}} void @_Z15testConversion3M8Derived0FvvE(370// CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC1]], i32 0, i64 [[TYPEDISC0]])371 372void testConversion3(MethodTy1 method1) {373  MethodTy0 method0 = reinterpret_cast<MethodTy0>(method1);374}375 376// No need to call @llvm.ptrauth.resign if the source member function377// pointer is a constant.378 379// CHECK: define{{.*}} void @_Z15testConversion4v(380// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8381// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8382// CHECK: ret void383 384void testConversion4() {385  MethodTy0 method0 = reinterpret_cast<MethodTy0>(&Derived0::virtual1);386}387 388// This code used to crash.389namespace testNonVirtualThunk {390  struct R {};391 392  struct B0 {393    virtual void bar();394  };395 396  struct B1 {397    virtual R foo();398  };399 400  struct D : B0, B1 {401    virtual R foo();402  };403 404  D d;405}406 407// CHECK: define internal void @_ZN22TestAnonymousNamespace12_GLOBAL__N_11S3fooEv_vfpthunk_(408 409namespace TestAnonymousNamespace {410namespace {411struct S {412  virtual void foo(){};413};414} // namespace415 416void test() {417  auto t = &S::foo;418}419} // namespace TestAnonymousNamespace420 421MethodTy1 gmethod0 = reinterpret_cast<MethodTy1>(&Base0::nonvirtual0);422MethodTy0 gmethod1 = reinterpret_cast<MethodTy0>(&Derived0::nonvirtual5);423MethodTy0 gmethod2 = reinterpret_cast<MethodTy0>(&Derived0::virtual1);424 425// CHECK-LABEL: define{{.*}} void @_Z13testArrayInitv()426// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p0, ptr align 8 @__const._Z13testArrayInitv.p0, i64 16, i1 false)427// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p1, ptr align 8 @__const._Z13testArrayInitv.p1, i64 16, i1 false)428// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c0, ptr align 8 @__const._Z13testArrayInitv.c0, i64 16, i1 false)429// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c1, ptr align 8 @__const._Z13testArrayInitv.c1, i64 16, i1 false)430// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %{{.*}} align 8431// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %{{.*}}, align 8432 433void initList(std::initializer_list<MethodTy1>);434 435void testArrayInit() {436  MethodTy1 p0[] = {&Base0::nonvirtual0};437  MethodTy1 p1[] = {&Base0::virtual1};438  Class0 c0{&Base0::nonvirtual0};439  Class0 c1{&Base0::virtual1};440  initList({&Base0::nonvirtual0});441  initList({&Base0::virtual1});442}443 444 445 446// STACK-PROT: define {{.*}}_vfpthunk{{.*}}[[ATTRS:#[0-9]+]]447// STACK-PROT: attributes [[ATTRS]] =448// STACK-PROT-NOT: ssp449// STACK-PROT-NOT: sspstrong450// STACK-PROT-NOT: sspreq451// STACK-PROT-NEXT: attributes452 453// CHECK: define{{.*}} void @_Z15testConvertNullv(454// CHECK: %[[T:.*]] = alloca { i64, i64 },455// store { i64, i64 } zeroinitializer, { i64, i64 }* %[[T]],456 457void testConvertNull() {458  VariadicMethodTy0 t = (VariadicMethodTy0)(MethodTy0{});459}460 461namespace testNoexceptConversion {462 463// CHECK-LABEL: define internal void @__cxx_global_var_init()464// CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8465// CHECK: store { i64, i64 } %[[V0]], ptr @_ZN22testNoexceptConversion6mfptr4E, align 8466 467// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test0Ev()468// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8469// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, ptr %[[P0]], align 8,470 471// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test1Ev()472// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8473// 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 475// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test2Ev()476// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8477// CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8478// CHECK: store { i64, i64 } %[[V0]], ptr %[[P0]], align 8,479 480struct S {481  void nonvirtual_noexcept() noexcept;482  virtual void virtual_noexcept() noexcept;483};484 485void (S::*mfptr0_noexcept)() noexcept;486void (S::*mfptr1)() = &S::nonvirtual_noexcept;487void (S::*mfptr2)() = &S::virtual_noexcept;488void (S::*mfptr3_noexcept)() noexcept = &S::nonvirtual_noexcept;489void (S::*mfptr4)() = mfptr0_noexcept;490 491void test0() {492  void (S::*p0)() = &S::nonvirtual_noexcept;493}494 495void test1() {496  void (S::*p0)() = &S::virtual_noexcept;497}498 499void test2() {500  void (S::*p0)() = mfptr0_noexcept;501}502 503}504