xref: /llvm-project/clang/test/CodeGenCXX/ptrauth-virtual-function.cpp (revision a1d77caaabbb5279b734c061dab36b2138ec476d)
1 // RUN: %clang_cc1 -triple arm64-apple-ios   -fptrauth-calls -emit-llvm -std=c++11 %s -o - | FileCheck --check-prefixes=CHECK,DARWIN %s
2 // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s -o - | FileCheck --check-prefixes=CHECK,ELF    %s
3 
4 // Check virtual function pointers in vtables are signed.
5 
6 // CHECK: %[[CLASS_B1:.*]] = type { ptr }
7 
8 // CHECK: @_ZTV2B1 = unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI2B1, ptr ptrauth (ptr @_ZN2B12m0Ev, i32 0, i64 58196, ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2B1, i32 0, i32 0, i32 2))] }, align 8
9 
10 // CHECK: @g_B1 = global %class.B1 { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV2B1, i32 0, i32 0, i32 2), i32 2) }, align 8
11 
12 // CHECK: @_ZTV2B0 = unnamed_addr constant { [7 x ptr] } { [7 x ptr] [ptr null, ptr @_ZTI2B0,
13 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV2B0, i32 0, i32 0, i32 2)),
14 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV2B0, i32 0, i32 0, i32 3)),
15 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV2B0, i32 0, i32 0, i32 4)),
16 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B0D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV2B0, i32 0, i32 0, i32 5)),
17 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B0D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV2B0, i32 0, i32 0, i32 6))] }, align 8
18 
19 // CHECK: @_ZTV2D0 = unnamed_addr constant { [9 x ptr] } { [9 x ptr] [ptr null, ptr @_ZTI2D0,
20 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D02m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 2)),
21 // CHECK-SAME: ptr ptrauth (ptr @_ZTch0_h4_N2D02m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 3)),
22 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 4)),
23 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D0D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 5)),
24 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D0D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 6)),
25 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D02m1Ev, i32 0, i64 35045, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 7)),
26 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D02m3Ev, i32 0, i64 10565, ptr getelementptr inbounds ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 8))] }, align 8
27 
28 // CHECK: @_ZTV2D1 = unnamed_addr constant { [8 x ptr] } { [8 x ptr] [ptr null, ptr @_ZTI2D1,
29 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D12m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 2)),
30 // CHECK-SAME: ptr ptrauth (ptr @_ZTch0_h4_N2D12m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 3)),
31 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 4)),
32 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D1D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 5)),
33 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D1D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 6)),
34 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D12m1Ev, i32 0, i64 52864, ptr getelementptr inbounds ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 7))] }, align 8
35 
36 // CHECK: @_ZTV2D2 = unnamed_addr constant { [9 x ptr], [8 x ptr] } { [9 x ptr] [ptr null, ptr @_ZTI2D2,
37 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D22m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 2)),
38 // CHECK-SAME: ptr ptrauth (ptr @_ZTch0_h4_N2D22m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 3)),
39 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 4)),
40 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D2D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 5)),
41 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D2D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 6)),
42 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D22m1Ev, i32 0, i64 35045, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 7)),
43 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D22m3Ev, i32 0, i64 10565, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 8))],
44 // CHECK-SAME: [8 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr @_ZTI2D2,
45 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D22m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 2)),
46 // CHECK-SAME: ptr ptrauth (ptr @_ZTchn16_h4_N2D22m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 3)),
47 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 4)),
48 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D2D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 5)),
49 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D2D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 6)),
50 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D22m1Ev, i32 0, i64 52864, ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 7))] }, align 8
51 
52 // CHECK: @_ZTV2D3 = unnamed_addr constant { [7 x ptr], [7 x ptr], [11 x ptr] } { [7 x ptr] [ptr inttoptr (i64 32 to ptr), ptr null, ptr @_ZTI2D3,
53 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D32m0Ev, i32 0, i64 44578, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 0, i32 3)),
54 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D32m1Ev, i32 0, i64 30766, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 0, i32 4)),
55 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D3D1Ev, i32 0, i64 57279, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 0, i32 5)),
56 // CHECK-SAME: ptr ptrauth (ptr @_ZN2D3D0Ev, i32 0, i64 62452, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 0, i32 6))],
57 // CHECK-SAME: [7 x ptr] [ptr inttoptr (i64 16 to ptr), ptr inttoptr (i64 -16 to ptr), ptr @_ZTI2D3,
58 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D32m0Ev, i32 0, i64 49430, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 1, i32 3)),
59 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D32m1Ev, i32 0, i64 57119, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 1, i32 4)),
60 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D3D1Ev, i32 0, i64 60799, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 1, i32 5)),
61 // CHECK-SAME: ptr ptrauth (ptr @_ZThn16_N2D3D0Ev, i32 0, i64 52565, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 1, i32 6))],
62 // CHECK-SAME: [11 x ptr] [ptr inttoptr (i64 -32 to ptr), ptr null, ptr inttoptr (i64 -32 to ptr), ptr inttoptr (i64 -32 to ptr), ptr inttoptr (i64 -32 to ptr), ptr @_ZTI2D3,
63 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n24_N2D32m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 2, i32 6)),
64 // CHECK-SAME: ptr ptrauth (ptr @_ZTcv0_n32_h4_N2D32m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 2, i32 7)),
65 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 2, i32 8)),
66 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N2D3D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 2, i32 9)),
67 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N2D3D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [7 x ptr], [7 x ptr], [11 x ptr] }, ptr @_ZTV2D3, i32 0, i32 2, i32 10))] }, align 8
68 
69 // CHECK: @_ZTC2D30_2V0 = unnamed_addr constant { [7 x ptr], [11 x ptr] } { [7 x ptr] [ptr inttoptr (i64 32 to ptr), ptr null, ptr @_ZTI2V0,
70 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V02m0Ev, i32 0, i64 44578, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 0, i32 3)),
71 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V02m1Ev, i32 0, i64 30766, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 0, i32 4)),
72 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V0D1Ev, i32 0, i64 57279, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 0, i32 5)),
73 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V0D0Ev, i32 0, i64 62452, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 0, i32 6))],
74 // CHECK-SAME: [11 x ptr] [ptr inttoptr (i64 -32 to ptr), ptr null, ptr inttoptr (i64 -32 to ptr), ptr inttoptr (i64 -32 to ptr), ptr inttoptr (i64 -32 to ptr), ptr @_ZTI2V0,
75 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n24_N2V02m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 1, i32 6)),
76 // CHECK-SAME: ptr ptrauth (ptr @_ZTcv0_n32_h4_N2V02m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 1, i32 7)),
77 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 1, i32 8)),
78 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N2V0D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 1, i32 9)),
79 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N2V0D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D30_2V0, i32 0, i32 1, i32 10))] }, align 8
80 
81 // CHECK: @_ZTC2D316_2V1 = unnamed_addr constant { [7 x ptr], [11 x ptr] } { [7 x ptr] [ptr inttoptr (i64 16 to ptr), ptr null, ptr @_ZTI2V1,
82 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V12m0Ev, i32 0, i64 49430, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 0, i32 3)),
83 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V12m1Ev, i32 0, i64 57119, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 0, i32 4)),
84 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V1D1Ev, i32 0, i64 60799, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 0, i32 5)),
85 // CHECK-SAME: ptr ptrauth (ptr @_ZN2V1D0Ev, i32 0, i64 52565, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 0, i32 6))],
86 // CHECK-SAME: [11 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr null, ptr inttoptr (i64 -16 to ptr), ptr inttoptr (i64 -16 to ptr), ptr inttoptr (i64 -16 to ptr), ptr @_ZTI2V1,
87 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n24_N2V12m0Ev, i32 0, i64 53119, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 1, i32 6)),
88 // CHECK-SAME: ptr ptrauth (ptr @_ZTcv0_n32_h4_N2V12m1Ev, i32 0, i64 15165, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 1, i32 7)),
89 // CHECK-SAME: ptr ptrauth (ptr @_ZN2B02m2Ev, i32 0, i64 43073, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 1, i32 8)),
90 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N2V1D1Ev, i32 0, i64 25525, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 1, i32 9)),
91 // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N2V1D0Ev, i32 0, i64 21295, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC2D316_2V1, i32 0, i32 1, i32 10))] }, align 8
92 
93 
94 struct S0 {
95   int f;
96 };
97 
98 struct S1 {
99   int f;
100 };
101 
102 struct S2 : S0, S1 {
103   int f;
104 };
105 
106 class B0 {
107 public:
108   virtual void m0();
109   virtual S1 *m1();
110   virtual void m2();
111   virtual ~B0();
112   int f;
113 };
114 
115 class B1 {
116 public:
117   virtual void m0();
118 };
119 
120 class D0 : public B0 {
121 public:
122   void m0() override;
123   S2 *m1() override;
124   virtual void m3();
125   int f;
126 };
127 
128 class D1 : public B0 {
129 public:
130   void m0() override;
131   S2 *m1() override;
132   int f;
133 };
134 
135 class D2 : public D0, public D1 {
136 public:
137   void m0() override;
138   S2 *m1() override;
139   void m3() override;
140   int f;
141 };
142 
143 class V0 : public virtual B0 {
144 public:
145   void m0() override;
146   S2 *m1() override;
147   int f;
148 };
149 
150 class V1 : public virtual B0 {
151 public:
152   void m0() override;
153   S2 *m1() override;
154   ~V1();
155   int f;
156 };
157 
158 class D3 : public V0, public V1 {
159 public:
160   void m0() override;
161   S2 *m1() override;
162   int f;
163 };
164 
165 B1 g_B1;
166 
167 void B0::m0() {}
168 
169 void B1::m0() {}
170 
171 void D0::m0() {}
172 
173 void D1::m0() {}
174 
175 void D2::m0() {}
176 
177 void D3::m0() {}
178 
179 V1::~V1() {
180   m1();
181 }
182 
183 // Check sign/authentication of vtable pointers and authentication of virtual
184 // functions.
185 
186 // DARWIN-LABEL: define noundef ptr @_ZN2V1D2Ev(
187 // ELF-LABEL:    define dso_local void @_ZN2V1D2Ev(
188 // CHECK: %[[THIS1:.*]] = load ptr, ptr %{{.*}}
189 // CHECK: %[[T0:[0-9]+]] = load ptr, ptr %{{.*}}
190 // CHECK: %[[T1:[0-9]+]] = ptrtoint ptr %[[T0]] to i64
191 // CHECK: %[[T2:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T1]], i32 2, i64 0)
192 // CHECK: %[[T3:[0-9]+]] = inttoptr i64 %[[T2]] to ptr
193 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[T3]] to i64
194 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 %[[T6]], i32 2, i64 0)
195 // CHECK: %[[SIGNED_VTADDR:[0-9]+]] = inttoptr i64 %[[T7]] to ptr
196 // CHECK: store ptr %[[SIGNED_VTADDR]], ptr %[[THIS1]]
197 
198 // CHECK-LABEL: define{{.*}} void @_Z8testB0m0P2B0(
199 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
200 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
201 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
202 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
203 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 0
204 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
205 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
206 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 53119)
207 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
208 
209 void testB0m0(B0 *a) {
210   a->m0();
211 }
212 
213 // CHECK-LABEL: define{{.*}} void @_Z8testB0m1P2B0(
214 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
215 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
216 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
217 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
218 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 1
219 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
220 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
221 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 15165)
222 // CHECK: call noundef ptr %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
223 
224 void testB0m1(B0 *a) {
225   a->m1();
226 }
227 
228 // CHECK-LABEL: define{{.*}} void @_Z8testB0m2P2B0(
229 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
230 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
231 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
232 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
233 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 2
234 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
235 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
236 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 43073)
237 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
238 
239 void testB0m2(B0 *a) {
240   a->m2();
241 }
242 
243 // CHECK-LABEL: define{{.*}} void @_Z8testD0m0P2D0(
244 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
245 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
246 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
247 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
248 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 0
249 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
250 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
251 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 53119)
252 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(16) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
253 
254 void testD0m0(D0 *a) {
255   a->m0();
256 }
257 
258 // CHECK-LABEL: define{{.*}} void @_Z8testD0m1P2D0(
259 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
260 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
261 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
262 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
263 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 5
264 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
265 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
266 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 35045)
267 // CHECK: call noundef ptr %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(16) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
268 
269 void testD0m1(D0 *a) {
270   a->m1();
271 }
272 
273 // CHECK-LABEL: define{{.*}} void @_Z8testD0m2P2D0(
274 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
275 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
276 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
277 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
278 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 2
279 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
280 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
281 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 43073)
282 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
283 
284 void testD0m2(D0 *a) {
285   a->m2();
286 }
287 
288 // CHECK-LABEL: define{{.*}} void @_Z8testD0m3P2D0(
289 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
290 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
291 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
292 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
293 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 6
294 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
295 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
296 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 10565)
297 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(16) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
298 
299 void testD0m3(D0 *a) {
300   a->m3();
301 }
302 
303 
304 // CHECK-LABEL: define{{.*}} void @_Z8testD1m0P2D1(
305 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
306 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
307 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
308 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
309 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 0
310 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
311 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
312 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 53119)
313 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(16) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
314 
315 void testD1m0(D1 *a) {
316   a->m0();
317 }
318 
319 // CHECK-LABEL: define{{.*}} void @_Z8testD1m1P2D1(
320 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
321 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
322 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
323 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
324 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 5
325 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
326 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
327 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 52864)
328 // CHECK: call noundef ptr %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(16) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
329 
330 void testD1m1(D1 *a) {
331   a->m1();
332 }
333 
334 // CHECK-LABEL: define{{.*}} void @_Z8testD1m2P2D1(
335 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
336 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
337 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
338 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
339 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 2
340 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
341 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
342 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 43073)
343 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
344 
345 void testD1m2(D1 *a) {
346   a->m2();
347 }
348 
349 
350 // CHECK-LABEL: define{{.*}} void @_Z8testD2m0P2D2(
351 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
352 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
353 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
354 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
355 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 0
356 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
357 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
358 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 53119)
359 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(36) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
360 
361 void testD2m0(D2 *a) {
362   a->m0();
363 }
364 
365 // CHECK-LABEL: define{{.*}} void @_Z8testD2m1P2D2(
366 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
367 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
368 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
369 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
370 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 5
371 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
372 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
373 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 35045)
374 // CHECK: call noundef ptr %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(36) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
375 
376 void testD2m1(D2 *a) {
377   a->m1();
378 }
379 
380 // CHECK-LABEL: define{{.*}} void @_Z10testD2m2D0P2D2(
381 // CHECK: call void @_ZN2B02m2Ev(ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}){{$}}
382 
383 void testD2m2D0(D2 *a) {
384   a->D0::m2();
385 }
386 
387 // CHECK-LABEL: define{{.*}} void @_Z10testD2m2D1P2D2(
388 // CHECK: call void @_ZN2B02m2Ev(ptr noundef nonnull align {{[0-9]+}} dereferenceable(12) %{{.*}}){{$}}
389 
390 void testD2m2D1(D2 *a) {
391   a->D1::m2();
392 }
393 
394 // CHECK-LABEL: define{{.*}} void @_Z8testD2m3P2D2(
395 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
396 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
397 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
398 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
399 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 6
400 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
401 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
402 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 10565)
403 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(36) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
404 
405 void testD2m3(D2 *a) {
406   a->m3();
407 }
408 
409 // CHECK-LABEL: define{{.*}} void @_Z8testD3m0P2D3(
410 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
411 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
412 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
413 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
414 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 0
415 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
416 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
417 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 44578)
418 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
419 
420 void testD3m0(D3 *a) {
421   a->m0();
422 }
423 
424 // CHECK-LABEL: define{{.*}} void @_Z8testD3m1P2D3(
425 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %{{.*}}
426 // CHECK: %[[T0:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
427 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T0]], i32 2, i64 0)
428 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
429 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 1
430 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
431 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
432 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 30766)
433 // CHECK: call noundef ptr %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) [ "ptrauth"(i32 0, i64 %[[T7]]) ]
434 
435 void testD3m1(D3 *a) {
436   a->m1();
437 }
438 
439 // CHECK: define{{.*}} void @_Z8testD3m2P2D3(ptr noundef %[[A:.*]])
440 // CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8
441 // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8
442 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8
443 // CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[V0]], align 8
444 // CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64
445 // CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0)
446 // CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr
447 // CHECK: %[[VBASE_OFFSET_PTR:.*]] = getelementptr i8, ptr %[[V3]], i64 -24
448 // CHECK: %[[VBASE_OFFSET:.*]] = load i64, ptr %[[VBASE_OFFSET_PTR]], align 8
449 // CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 %[[VBASE_OFFSET]]
450 // CHECK: %[[VTABLE1:.*]] = load ptr, ptr %[[ADD_PTR]], align 8
451 // CHECK: %[[V4:.*]] = ptrtoint ptr %[[VTABLE1]] to i64
452 // CHECK: %[[V5:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V4]], i32 2, i64 0)
453 // CHECK: %[[V6:.*]] = inttoptr i64 %[[V5]] to ptr
454 // CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V6]], i64 2
455 // CHECK: %[[V7:.*]] = load ptr, ptr %[[VFN]], align 8
456 // CHECK: %[[V8:.*]] = ptrtoint ptr %[[VFN]] to i64
457 // CHECK: %[[V9:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V8]], i64 43073)
458 // CHECK: call void %[[V7]](ptr noundef nonnull align 8 dereferenceable(12) %[[ADD_PTR]]) [ "ptrauth"(i32 0, i64 %[[V9]]) ]
459 
460 void testD3m2(D3 *a) {
461   a->m2();
462 }
463 
464 // CHECK-LABEL: define{{.*}} void @_Z17testD3Destructor0P2D3(
465 // CHECK: load ptr, ptr
466 // CHECK: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}
467 // CHECK: %[[T2:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
468 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T2]], i32 2, i64 0)
469 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
470 // CHECK: %[[VFN:[a-z]+]] = getelementptr inbounds ptr, ptr %[[T4]], i64 3
471 // CHECK: %[[T5:[0-9]+]] = load ptr, ptr %[[VFN]]
472 // CHECK: %[[T6:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
473 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 62452)
474 // CHECK: call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) #{{.*}} [ "ptrauth"(i32 0, i64 %[[T7]]) ]
475 
476 void testD3Destructor0(D3 *a) {
477   delete a;
478 }
479 
480 // CHECK-LABEL: define{{.*}} void @_Z17testD3Destructor1P2D3(
481 // CHECK: %[[T6:.*]] = load ptr, ptr %
482 // CHECK: %[[VTABLE0:[a-z0-9]+]] = load ptr, ptr %
483 // CHECK: %[[T2:[0-9]+]] = ptrtoint ptr %[[VTABLE0]] to i64
484 // CHECK: %[[T3:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T2]], i32 2, i64 0)
485 // CHECK: %[[T4:[0-9]+]] = inttoptr i64 %[[T3]] to ptr
486 // CHECK: %[[COMPLETE_OFFSET_PTR:.*]] = getelementptr inbounds i64, ptr %[[T4]], i64 -2
487 // CHECK: %[[T5:[0-9]+]] = load i64, ptr %[[COMPLETE_OFFSET_PTR]]
488 // CHECK: %[[T7:[0-9]+]] = getelementptr inbounds i8, ptr %[[T6]], i64 %[[T5]]
489 // CHECK: %[[VTABLE1:[a-z0-9]+]] = load ptr, ptr %[[T6]]
490 // CHECK: %[[T9:[0-9]+]] = ptrtoint ptr %[[VTABLE1]] to i64
491 // CHECK: %[[T10:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T9]], i32 2, i64 0)
492 // CHECK: %[[T11:[0-9]+]] = inttoptr i64 %[[T10]] to ptr
493 // CHECK: %[[VFN:[a-z0-9]+]] = getelementptr inbounds ptr, ptr %[[T11]], i64 2
494 // CHECK: %[[T12:[0-9]+]] = load ptr, ptr %[[VFN]]
495 // CHECK: %[[T13:[0-9]+]] = ptrtoint ptr %[[VFN]] to i64
496 // CHECK: %[[T14:[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 %[[T13]], i64 57279)
497 // DARWIN: %call = call noundef ptr %[[T12]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) #{{.*}} [ "ptrauth"(i32 0, i64 %[[T14]]) ]
498 // ELF:    call void %[[T12]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) #{{.*}} [ "ptrauth"(i32 0, i64 %[[T14]]) ]
499 // CHECK: call void @_ZdlPv(ptr noundef %[[T7]])
500 
501 void testD3Destructor1(D3 *a) {
502   ::delete a;
503 }
504 
505 // CHECK-LABEL: define{{.*}} void @_Z17testD3Destructor2P2D3(
506 // CHECK: load ptr, ptr
507 // CHECK: %[[VTABLE:.*]] = load ptr, ptr %
508 // CHECK: %[[T2:.*]] = ptrtoint ptr %[[VTABLE]] to i64
509 // CHECK: %[[T3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[T2]], i32 2, i64 0)
510 // CHECK: %[[T4:.*]] = inttoptr i64 %[[T3]] to ptr
511 // CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[T4]], i64 2
512 // CHECK: %[[T5:.*]] = load ptr, ptr %[[VFN]]
513 // CHECK: %[[T6:.*]] = ptrtoint ptr %[[VFN]] to i64
514 // CHECK: %[[T7:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[T6]], i64 57279)
515 // DARWIN: %call = call noundef ptr %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) #{{.*}} [ "ptrauth"(i32 0, i64 %[[T7]]) ]
516 // ELF:    call void %[[T5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(32) %{{.*}}) #{{.*}} [ "ptrauth"(i32 0, i64 %[[T7]]) ]
517 
518 void testD3Destructor2(D3 *a) {
519   a->~D3();
520 }
521 
522 void materializeConstructors() {
523   B0 B0;
524   B1 B1;
525   D0 D0;
526   D1 D1;
527   D2 D2;
528   D3 D3;
529   V0 V0;
530   V1 V1;
531 }
532 
533 // DARWIN-LABEL: define linkonce_odr noundef ptr @_ZN2B0C2Ev(
534 // ELF-LABEL:    define linkonce_odr void @_ZN2B0C2Ev(
535 // CHECK: %[[THIS:.*]] = load ptr, ptr %
536 // CHECK: %[[T0:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr inbounds inrange(-16, 40) ({ [7 x ptr] }, ptr @_ZTV2B0, i32 0, i32 0, i32 2) to i64), i32 2, i64 0)
537 // CHECK: %[[SIGNED_VTADDR:[0-9]+]] = inttoptr i64 %[[T0]] to ptr
538 // CHECK: store ptr %[[SIGNED_VTADDR]], ptr %[[THIS]]
539 
540 // DARWIN-LABEL: define linkonce_odr noundef ptr @_ZN2D0C2Ev(
541 // ELF-LABEL:    define linkonce_odr void @_ZN2D0C2Ev(
542 // CHECK: %[[T0:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr inbounds inrange(-16, 56) ({ [9 x ptr] }, ptr @_ZTV2D0, i32 0, i32 0, i32 2) to i64), i32 2, i64 0)
543 // CHECK: %[[SIGNED_VTADDR:[0-9]+]] = inttoptr i64 %[[T0]] to ptr
544 // CHECK: store ptr %[[SIGNED_VTADDR]], ptr %[[THIS]]
545 
546 // DARWIN-LABEL: define linkonce_odr noundef ptr @_ZN2D1C2Ev(
547 // ELF-LABEL:    define linkonce_odr void @_ZN2D1C2Ev(
548 // CHECK: %[[T0:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr inbounds inrange(-16, 48) ({ [8 x ptr] }, ptr @_ZTV2D1, i32 0, i32 0, i32 2) to i64), i32 2, i64 0)
549 // CHECK: %[[SIGNED_VTADDR:[0-9]+]] = inttoptr i64 %[[T0]] to ptr
550 // CHECK: store ptr %[[SIGNED_VTADDR]], ptr %[[THIS]]
551 
552 // DARWIN-LABEL: define linkonce_odr noundef ptr @_ZN2D2C2Ev(
553 // ELF-LABEL:    define linkonce_odr void @_ZN2D2C2Ev(
554 // CHECK: %[[SLOT0:.*]] = load ptr, ptr
555 // CHECK: %[[SIGN_VTADDR0:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr inbounds inrange(-16, 56) ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 0, i32 2) to i64), i32 2, i64 0)
556 // CHECK: %[[T1:[0-9]+]] = inttoptr i64 %[[SIGN_VTADDR0]] to ptr
557 // CHECK: store ptr %[[T1]], ptr %[[SLOT0]]
558 // CHECK: %[[T3:[a-z0-9.]+]] = getelementptr inbounds i8, ptr %[[SLOT0]], i64 16
559 // CHECK: %[[SIGN_VTADDR1:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr getelementptr inbounds inrange(-16, 48) ({ [9 x ptr], [8 x ptr] }, ptr @_ZTV2D2, i32 0, i32 1, i32 2) to i64), i32 2, i64 0)
560 // CHECK: %[[T5:[0-9]+]] = inttoptr i64 %[[SIGN_VTADDR1]] to ptr
561 // CHECK: store ptr %[[T5]], ptr %[[T3]]
562 
563 // DARWIN-LABEL: define linkonce_odr noundef ptr @_ZN2V0C2Ev(
564 // ELF-LABEL:    define linkonce_odr void @_ZN2V0C2Ev(
565 // CHECK: %[[THIS1]] = load ptr, ptr %
566 // CHECK: %[[VTT:[a-z0-9]+]] = load ptr, ptr %{{.*}}
567 // CHECK: %[[T0:[0-9]+]] = load ptr, ptr %[[VTT]]
568 // CHECK: %[[T1:[0-9]+]] = ptrtoint ptr %[[T0]] to i64
569 // CHECK: %[[T2:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T1]], i32 2, i64 0)
570 // CHECK: %[[T3:[0-9]+]] = inttoptr i64 %[[T2]] to ptr
571 // CHECK: %[[VTADDR0:[0-9]+]] = ptrtoint ptr %[[T3]] to i64
572 // CHECK: %[[T7:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 %[[VTADDR0]], i32 2, i64 0)
573 // CHECK: %[[SIGN_VTADDR0:[0-9]+]] = inttoptr i64 %[[T7]] to ptr
574 // CHECK: store ptr %[[SIGN_VTADDR0]], ptr %[[SLOT0]]
575 // CHECK: %[[T9:[0-9]+]] = getelementptr inbounds ptr, ptr %[[VTT]], i64 1
576 // CHECK: %[[T10:[0-9]+]] = load ptr, ptr %[[T9]]
577 // CHECK: %[[T11:[0-9]+]] = ptrtoint ptr %[[T10]] to i64
578 // CHECK: %[[T12:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T11]], i32 2, i64 0)
579 // CHECK: %[[T13:[0-9]+]] = inttoptr i64 %[[T12]] to ptr
580 // CHECK: %[[VTABLE:[a-z]+]] = load ptr, ptr %[[THIS1]]
581 // CHECK: %[[T15:[0-9]+]] = ptrtoint ptr %[[VTABLE]] to i64
582 // CHECK: %[[T16:[0-9]+]] = call i64 @llvm.ptrauth.auth(i64 %[[T15]], i32 2, i64 0)
583 // CHECK: %[[T17:[0-9]+]] = inttoptr i64 %[[T16]] to ptr
584 // CHECK: %[[VBASE_OFFSET_PTR:[a-z.]+]] = getelementptr i8, ptr %[[T17]], i64 -24
585 // CHECK: %[[VBASE_OFFSET:[a-z.]+]] = load i64, ptr %[[VBASE_OFFSET_PTR]]
586 // CHECK: %[[T20:[a-z.]+]] = getelementptr inbounds i8, ptr %[[THIS1]], i64 %[[VBASE_OFFSET]]
587 // CHECK: %[[VTADDR1:[0-9]+]] = ptrtoint ptr %[[T13]] to i64
588 // CHECK: %[[T23:[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 %[[VTADDR1]], i32 2, i64 0)
589 // CHECK: %[[SIGN_VTADDR1:[0-9]+]] = inttoptr i64 %[[T23]] to ptr
590 // CHECK: store ptr %[[SIGN_VTADDR1]], ptr %[[T20]]
591