602 lines · cpp
1// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \2// RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s3 4// RUN: %clang_cc1 %s -x c++ -std=c++20 -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 %s7 8// RUN: %clang_cc1 %s -x c++ -std=c++20 -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 %s11 12// RUN: %clang_cc1 %s -x c++ -std=c++20 -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 %s16 17// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \18// RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s19 20// RUN: %clang_cc1 %s -x c++ -std=c++20 -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 %s23 24// RUN: %clang_cc1 %s -x c++ -std=c++20 -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 %s27 28// RUN: %clang_cc1 %s -x c++ -std=c++20 -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 %s32 33#include <ptrauth.h>34 35namespace test1 {36 37#define authenticated(a...) ptrauth_cxx_vtable_pointer(a)38 39struct NoExplicitAuth {40 virtual ~NoExplicitAuth();41 virtual void f();42 virtual void g();43};44 45struct authenticated(no_authentication, no_address_discrimination, no_extra_discrimination) ExplicitlyDisableAuth {46 virtual ~ExplicitlyDisableAuth();47 virtual void f();48 virtual void g();49};50 51struct authenticated(default_key, address_discrimination, default_extra_discrimination) ExplicitAddressDiscrimination {52 virtual ~ExplicitAddressDiscrimination();53 virtual void f();54 virtual void g();55};56 57struct authenticated(default_key, no_address_discrimination, default_extra_discrimination) ExplicitNoAddressDiscrimination {58 virtual ~ExplicitNoAddressDiscrimination();59 virtual void f();60 virtual void g();61};62 63struct authenticated(default_key, default_address_discrimination, no_extra_discrimination) ExplicitNoExtraDiscrimination {64 virtual ~ExplicitNoExtraDiscrimination();65 virtual void f();66 virtual void g();67};68 69struct authenticated(default_key, default_address_discrimination, type_discrimination) ExplicitTypeDiscrimination {70 virtual ~ExplicitTypeDiscrimination();71 virtual void f();72 virtual void g();73};74 75struct authenticated(default_key, default_address_discrimination, custom_discrimination, 42424) ExplicitCustomDiscrimination {76 virtual ~ExplicitCustomDiscrimination();77 virtual void f();78 virtual void g();79};80 81// CHECK: @_ZTVN5test19ConstEvalE = external unnamed_addr constant { [3 x ptr] }, align 882// CHECK: @_ZN5test12ceE = global %{{.*}} { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test19ConstEvalE, i32 0, i32 0, i32 2), i32 2, i64 0, ptr @_ZN5test12ceE) }, align 883// CHECK: @_ZTVN5test116ConstEvalDerivedE = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTIN5test116ConstEvalDerivedE, ptr ptrauth (ptr @_ZN5test19ConstEval1fEv, i32 0, i64 26259, ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test116ConstEvalDerivedE, i32 0, i32 0, i32 2))] },{{.*}}align 884// CHECK: @_ZN5test13cedE = global { ptr } { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test116ConstEvalDerivedE, i32 0, i32 0, i32 2), i32 2, i64 0, ptr @_ZN5test13cedE) }, align 885 86struct authenticated(default_key, address_discrimination, no_extra_discrimination) ConstEval {87 consteval ConstEval() {}88 virtual void f();89};90 91// clang used to bail out with error message "could not emit constant value abstractly".92ConstEval ce;93 94struct ConstEvalDerived : public ConstEval {95public:96 consteval ConstEvalDerived() {}97};98 99// clang used to emit an undef initializer.100ConstEvalDerived ced;101 102template <typename T>103struct SubClass : T {104 virtual void g();105 virtual T *h();106};107 108template <typename T>109SubClass<T> *make_subclass(T *);110 111struct authenticated(default_key, address_discrimination, type_discrimination) BasicStruct {112 virtual ~BasicStruct();113};114 115template <typename T>116struct PrimaryBasicStruct : BasicStruct, T {};117template <typename T>118struct PrimaryBasicStruct<T> *make_multiple_primary(T *);119 120template <typename T>121struct VirtualSubClass : virtual T {122 virtual void g();123 virtual T *h();124};125template <typename T>126struct VirtualPrimaryStruct : virtual T, VirtualSubClass<T> {};127template <typename T>128struct VirtualPrimaryStruct<T> *make_virtual_primary(T *);129 130extern "C" {131 132// CHECK: @TVDisc_NoExplicitAuth = global i32 [[DISC_DEFAULT:49565]], align 4133int TVDisc_NoExplicitAuth = ptrauth_string_discriminator("_ZTVN5test114NoExplicitAuthE");134 135// CHECK: @TVDisc_ExplicitlyDisableAuth = global i32 [[DISC_DISABLED:24369]], align 4136int TVDisc_ExplicitlyDisableAuth = ptrauth_string_discriminator("_ZTVN5test121ExplicitlyDisableAuthE");137 138// CHECK: @TVDisc_ExplicitAddressDiscrimination = global i32 [[DISC_ADDR:56943]], align 4139int TVDisc_ExplicitAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitAddressDiscriminationE");140 141// CHECK: @TVDisc_ExplicitNoAddressDiscrimination = global i32 [[DISC_NO_ADDR:6022]], align 4142int TVDisc_ExplicitNoAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test131ExplicitNoAddressDiscriminationE");143 144// CHECK: @TVDisc_ExplicitNoExtraDiscrimination = global i32 [[DISC_NO_EXTRA:9072]], align 4145int TVDisc_ExplicitNoExtraDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitNoExtraDiscriminationE");146 147// CHECK: @TVDisc_ExplicitTypeDiscrimination = global i32 [[DISC_TYPE:6177]], align 4148int TVDisc_ExplicitTypeDiscrimination = ptrauth_string_discriminator("_ZTVN5test126ExplicitTypeDiscriminationE");149 150 151// CHECK-LABEL: define{{.*}} void @test_default(ptr noundef {{%.*}}) {{#.*}} {152// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8153// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8154//155// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64156// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)157//158// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64159// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])160//161// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64162// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64163// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])164//165// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64166// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])167// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64168// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])169void test_default(NoExplicitAuth *a) {170 a->f();171}172 173// CHECK-LABEL: define{{.*}} void @test_disabled(ptr noundef {{%.*}}) {{#.*}} {174// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8175// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8176// CHECK-NOT: call i64 @llvm.ptrauth.auth177void test_disabled(ExplicitlyDisableAuth *a) {178 a->f();179}180 181// CHECK-LABEL: define{{.*}} void @test_addr_disc(ptr noundef {{%.*}}) {{#.*}} {182// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8183// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8184//185// NODISC: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64186// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64187// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])188//189// TYPE: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64190// TYPE: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])191// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64192// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])193//194// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64195// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64196// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])197//198// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64199// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])200// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64201// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])202void test_addr_disc(ExplicitAddressDiscrimination *a) {203 a->f();204}205 206// CHECK-LABEL: define{{.*}} void @test_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} {207// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8208// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8209//210// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64211// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)212//213// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64214// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])215//216// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64217// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)218//219// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64220// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])221void test_no_addr_disc(ExplicitNoAddressDiscrimination *a) {222 a->f();223}224 225// CHECK-LABEL: define{{.*}} void @test_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} {226// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8227// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8228//229// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64230// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)231//232// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64233// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)234//235// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64236// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64237// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])238//239// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64240// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64241// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])242void test_no_extra_disc(ExplicitNoExtraDiscrimination *a) {243 a->f();244}245 246// CHECK-LABEL: define{{.*}} void @test_type_disc(ptr noundef {{%.*}}) {{#.*}} {247// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8248// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8249//250// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64251// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])252//253// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64254// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])255//256// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64257// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])258// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64259// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])260//261// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64262// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])263// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64264// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])265void test_type_disc(ExplicitTypeDiscrimination *a) {266 a->f();267}268 269// CHECK-LABEL: define{{.*}} void @test_custom_disc(ptr noundef {{%.*}}) {{#.*}} {270// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8271// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8272//273// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64274// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)275//276// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64277// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)278//279// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64280// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)281// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64282// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])283//284// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64285// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)286// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64287// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])288void test_custom_disc(ExplicitCustomDiscrimination *a) {289 a->f();290}291 292//293// Test some simple single inheritance cases.294// Codegen should be the same as the simple cases above once we have a vtable.295//296 297// CHECK-LABEL: define{{.*}} void @test_subclass_default(ptr noundef {{%.*}}) {{#.*}} {298// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass299// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8300//301// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64302// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)303//304// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64305// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])306//307// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64308// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64309// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])310//311// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64312// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])313// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64314// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])315void test_subclass_default(NoExplicitAuth *a) {316 make_subclass(a)->f();317}318 319// CHECK-LABEL: define{{.*}} void @test_subclass_disabled(ptr noundef {{%.*}}) {{#.*}} {320// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass321// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8322// CHECK-NOT: call i64 @llvm.ptrauth.auth323void test_subclass_disabled(ExplicitlyDisableAuth *a) {324 make_subclass(a)->f();325}326 327// CHECK-LABEL: define{{.*}} void @test_subclass_addr_disc(ptr noundef {{%.*}}) {{#.*}} {328// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass329// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8330//331// NODISC: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64332// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64333// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])334//335// TYPE: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64336// TYPE: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])337// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64338// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])339//340// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64341// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64342// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])343//344// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64345// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]])346// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64347// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])348void test_subclass_addr_disc(ExplicitAddressDiscrimination *a) {349 make_subclass(a)->f();350}351 352// CHECK-LABEL: define{{.*}} void @test_subclass_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} {353// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass354// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8355//356// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64357// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)358//359// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64360// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])361//362// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64363// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)364//365// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64366// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]])367void test_subclass_no_addr_disc(ExplicitNoAddressDiscrimination *a) {368 make_subclass(a)->f();369}370 371// CHECK-LABEL: define{{.*}} void @test_subclass_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} {372// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass373// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8374//375// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64376// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)377//378// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64379// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)380//381// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64382// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64383// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])384//385// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64386// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64387// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])388void test_subclass_no_extra_disc(ExplicitNoExtraDiscrimination *a) {389 make_subclass(a)->f();390}391 392// CHECK-LABEL: define{{.*}} void @test_subclass_type_disc(ptr noundef {{%.*}}) {{#.*}} {393// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass394// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8395//396// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64397// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])398//399// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64400// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]])401//402// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64403// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])404// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64405// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])406//407// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64408// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]])409// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64410// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])411void test_subclass_type_disc(ExplicitTypeDiscrimination *a) {412 make_subclass(a)->f();413}414 415// CHECK-LABEL: define{{.*}} void @test_subclass_custom_disc(ptr noundef {{%.*}}) {{#.*}} {416// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass417// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8418//419// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64420// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)421//422// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64423// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)424//425// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64426// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)427// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64428// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])429//430// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64431// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)432// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64433// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])434void test_subclass_custom_disc(ExplicitCustomDiscrimination *a) {435 make_subclass(a)->f();436}437 438 439//440// Test some simple multiple inheritance cases.441// Codegen should be the same as the simple cases above once we have a vtable.442//443 444// CHECK-LABEL: define{{.*}} void @test_multiple_default(ptr noundef {{%.*}}) {{#.*}} {445// CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary446// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8447// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8448//449// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64450// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)451//452// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64453// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])454//455// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64456// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64457// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])458//459// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64460// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])461// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64462// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])463void test_multiple_default(NoExplicitAuth *a) {464 make_multiple_primary(a)->f();465}466 467// CHECK-LABEL: define{{.*}} void @test_multiple_disabled(ptr noundef {{%.*}}) {{#.*}} {468// CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary469// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8470// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8471// CHECK-NOT: call i64 @llvm.ptrauth.auth472void test_multiple_disabled(ExplicitlyDisableAuth *a) {473 make_multiple_primary(a)->f();474}475 476// CHECK-LABEL: define{{.*}} void @test_multiple_custom_disc(ptr noundef {{%.*}}) {{#.*}} {477// CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary478// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8479// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8480//481// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64482// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)483//484// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64485// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)486//487// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64488// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)489// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64490// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])491//492// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64493// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)494// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64495// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])496void test_multiple_custom_disc(ExplicitCustomDiscrimination *a) {497 make_multiple_primary(a)->f();498}499 500//501// Test some virtual inheritance cases.502// Codegen should be the same as the simple cases above once we have a vtable,503// but twice for vtt/vtable. The names in the vtt version have "VTT" prefixes.504//505 506// CHECK-LABEL: define{{.*}} void @test_virtual_default(ptr noundef {{%.*}}) {{#.*}} {507// CHECK: [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary508// CHECK: [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8509//510// NODISC: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64511// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 0)512//513// TYPE: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64514// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])515//516// ADDR: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64517// ADDR: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64518// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[VTTADDRI64]])519//520// BOTH: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64521// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 [[DISC_DEFAULT]])522// BOTH: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64523// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]])524 525// CHECK: [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr526// CHECK: [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48527// CHECK: [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]]528// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]]529// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8530//531// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64532// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0)533//534// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64535// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]])536//537// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64538// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64539// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]])540//541// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64542// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]])543// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64544// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])545void test_virtual_default(NoExplicitAuth *a) {546 make_virtual_primary(a)->f();547}548 549// CHECK-LABEL: define{{.*}} void @test_virtual_disabled(ptr noundef {{%.*}}) {{#.*}} {550// CHECK-NOT: call i64 @llvm.ptrauth.auth551void test_virtual_disabled(ExplicitlyDisableAuth *a) {552 make_virtual_primary(a)->f();553}554 555// CHECK-LABEL: define{{.*}} void @test_virtual_custom_disc(ptr noundef {{%.*}}) {{#.*}} {556// CHECK: [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary557// CHECK: [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8558//559// NODISC: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64560// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424)561//562// TYPE: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64563// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424)564//565// ADDR: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64566// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424)567// ADDR: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64568// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]])569//570// BOTH: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64571// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424)572// BOTH: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64573// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]])574 575// CHECK: [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr576// CHECK: [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48577// CHECK: [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]]578// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]]579// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8580//581// NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64582// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)583//584// TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64585// TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424)586//587// ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64588// ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)589// ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64590// ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])591//592// BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64593// BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424)594// BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64595// BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]])596void test_virtual_custom_disc(ExplicitCustomDiscrimination *a) {597 make_virtual_primary(a)->f();598}599 600} // extern "C"601} // namespace test1602