https://github.com/chbessonova updated 
https://github.com/llvm/llvm-project/pull/205808

>From fdbe147c426edba3ae155e3ed79b8e88f0391450 Mon Sep 17 00:00:00 2001
From: Kristina Bessonova <[email protected]>
Date: Fri, 19 Jun 2026 18:08:22 +0200
Subject: [PATCH 1/2] [PAC][clang] Implement address/type discrimination for
 VTT vtable pointers

Add support for address and type discrimination for vtable pointers stored
in VTTs under the `-fptrauth-vtt-vtable-pointer-discrimination` option.
This option is not enabled by default on any target and works in
combination with `-fptrauth-vtable-pointer-address-discrimination` and/or
`-fptrauth-vtable-pointer-type-discrimination`.

For address discrimination, the address of the corresponding VTT entry is
used as the discriminator.

The type discriminator is computed similarly to the one used for vtable
pointers stored in objects, but is based on the vtable type rather than
its base type.
---
 clang/include/clang/Basic/Features.def        |  1 +
 clang/include/clang/Basic/LangOptions.def     |  1 +
 clang/include/clang/Options/Options.td        |  2 +
 clang/lib/CodeGen/CGPointerAuth.cpp           | 37 +++++--
 clang/lib/CodeGen/CGVTT.cpp                   | 35 +++++--
 clang/lib/CodeGen/CodeGenFunction.h           |  3 +
 clang/lib/CodeGen/ItaniumCXXABI.cpp           | 19 +++-
 clang/lib/Driver/ToolChains/Clang.cpp         |  3 +
 clang/lib/Frontend/CompilerInvocation.cpp     | 15 ++-
 .../test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp | 99 +++++++++++++++++++
 clang/test/Driver/aarch64-ptrauth.c           | 10 +-
 11 files changed, 196 insertions(+), 29 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp

diff --git a/clang/include/clang/Basic/Features.def 
b/clang/include/clang/Basic/Features.def
index 2f7741ff74f9b..d848b92afe93d 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -156,6 +156,7 @@ FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
 FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
 FEATURE(ptrauth_vtable_pointer_address_discrimination, 
LangOpts.PointerAuthVTPtrAddressDiscrimination)
 FEATURE(ptrauth_vtable_pointer_type_discrimination, 
LangOpts.PointerAuthVTPtrTypeDiscrimination)
+FEATURE(ptrauth_vtt_vtable_pointer_discrimination, 
LangOpts.PointerAuthVTTVTPtrDiscrimination)
 FEATURE(ptrauth_type_info_vtable_pointer_discrimination, 
LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
 FEATURE(ptrauth_member_function_pointer_type_discrimination, 
LangOpts.PointerAuthCalls)
 FEATURE(ptrauth_signed_block_descriptors, 
LangOpts.PointerAuthBlockDescriptorPointers)
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index d68784b7efbcd..2c153e0c125f9 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -125,6 +125,7 @@ LANGOPT(PointerAuthIndirectGotos, 1, 0, NotCompatible, 
"indirect gotos pointer a
 LANGOPT(PointerAuthAuthTraps, 1, 0, NotCompatible, "pointer authentication 
failure traps")
 LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, NotCompatible, 
"incorporate address discrimination in authenticated vtable pointers")
 LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, NotCompatible, "incorporate 
type discrimination in authenticated vtable pointers")
+LANGOPT(PointerAuthVTTVTPtrDiscrimination, 1, 0, NotCompatible, "incorporate 
discrimination in authenticated vtable pointers in VTTs")
 LANGOPT(PointerAuthTypeInfoVTPtrDiscrimination, 1, 0, NotCompatible, 
"incorporate type and address discrimination in authenticated vtable pointers 
for std::type_info")
 LANGOPT(PointerAuthFunctionTypeDiscrimination, 1, 0, Benign,
         "Use type discrimination when signing function pointers")
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 3c2091013d152..403faf460e8a0 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4972,6 +4972,8 @@ defm ptrauth_vtable_pointer_address_discrimination :
   OptInCC1FFlag<"ptrauth-vtable-pointer-address-discrimination", "Enable 
address discrimination of vtable pointers">;
 defm ptrauth_vtable_pointer_type_discrimination :
   OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type 
discrimination of vtable pointers">;
+defm ptrauth_vtt_vtable_pointer_discrimination :
+  OptInCC1FFlag<"ptrauth-vtt-vtable-pointer-discrimination", "Apply the same 
vtable pointer discrimination scheme to VTT entries as to object vtable 
pointers">;
 defm ptrauth_type_info_vtable_pointer_discrimination :
   OptInCC1FFlag<"ptrauth-type-info-vtable-pointer-discrimination", "Enable 
type and address discrimination of vtable pointer of std::type_info">;
 defm ptrauth_function_pointer_type_discrimination : 
OptInCC1FFlag<"ptrauth-function-pointer-type-discrimination",
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp 
b/clang/lib/CodeGen/CGPointerAuth.cpp
index 28d3289dfe04f..0af3140404339 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -14,6 +14,7 @@
 #include "CGCXXABI.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "clang/Basic/PointerAuthOptions.h"
 #include "clang/CodeGen/CodeGenABITypes.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -121,20 +122,38 @@ CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo(
   if (!Schema)
     return CGPointerAuthInfo();
 
-  llvm::Value *Discriminator =
-      CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType);
+  llvm::ConstantInt *Discriminator =
+      Schema.getOtherDiscrimination() == 
PointerAuthSchema::Discrimination::None
+          ? nullptr
+          : CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl,
+                                                 SchemaType);
+
+  return EmitPointerAuthInfo(Schema, StorageAddress, Discriminator);
+}
+
+CGPointerAuthInfo
+CodeGenFunction::EmitPointerAuthInfo(const PointerAuthSchema &Schema,
+                                     llvm::Value *StorageAddress,
+                                     llvm::ConstantInt *ExtraDiscriminator) {
+  if (!Schema)
+    return CGPointerAuthInfo();
 
+  PointerAuthSchema::Discrimination ExtraDiscKind =
+      Schema.getOtherDiscrimination();
+  assert(
+      (ExtraDiscKind == PointerAuthSchema::Discrimination::None ||
+       ExtraDiscriminator) &&
+      "extra discrimination is requested but no discriminator gets provided");
+
+  llvm::Value *Discriminator = ExtraDiscriminator;
   if (Schema.isAddressDiscriminated()) {
     assert(StorageAddress &&
            "address not provided for address-discriminated schema");
-
-    if (Discriminator)
-      Discriminator =
-          EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator);
-    else
-      Discriminator = Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
+    Discriminator =
+        ExtraDiscKind != PointerAuthSchema::Discrimination::None
+            ? EmitPointerAuthBlendDiscriminator(StorageAddress, Discriminator)
+            : Builder.CreatePtrToInt(StorageAddress, IntPtrTy);
   }
-
   return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
                            Schema.isIsaPointer(),
                            Schema.authenticatesNullValues(), Discriminator);
diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp
index 989a07d09d50e..0249156acde23 100644
--- a/clang/lib/CodeGen/CGVTT.cpp
+++ b/clang/lib/CodeGen/CGVTT.cpp
@@ -55,18 +55,17 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
   }
 
   SmallVector<llvm::Constant *, 8> VTTComponents;
-  for (const VTTComponent *i = Builder.getVTTComponents().begin(),
-                          *e = Builder.getVTTComponents().end(); i != e; ++i) {
-    const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
-    llvm::GlobalVariable *VTable = VTables[i->VTableIndex];
+  for (const auto &[Idx, C] : llvm::enumerate(Builder.getVTTComponents())) {
+    const VTTVTable &VTTVT = Builder.getVTTVTables()[C.VTableIndex];
+    llvm::GlobalVariable *VTable = VTables[C.VTableIndex];
     VTableLayout::AddressPointLocation AddressPoint;
     if (VTTVT.getBase() == RD) {
       // Just get the address point for the regular vtable.
       AddressPoint =
           getItaniumVTableContext().getVTableLayout(RD).getAddressPoint(
-              i->VTableBase);
+              C.VTableBase);
     } else {
-      AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
+      AddressPoint = VTableAddressPoints[C.VTableIndex].lookup(C.VTableBase);
       assert(AddressPoint.AddressPointIndex != 0 &&
              "Did not find ctor vtable address point!");
     }
@@ -92,10 +91,26 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
          VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
 
      if (const auto &Schema =
-             CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers)
-       Init = CGM.getConstantSignedPointer(Init, Schema, nullptr, GlobalDecl(),
-                                           QualType());
-
+             CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) {
+       llvm::Constant *AddressDesc =
+           Schema.isAddressDiscriminated()
+               ? llvm::ConstantExpr::getGetElementPtr(
+                     VTT->getType(), VTT,
+                     llvm::ConstantInt::get(CGM.Int32Ty, Idx))
+               : nullptr;
+       if (Schema.getOtherDiscrimination() ==
+           PointerAuthSchema::Discrimination::Type) {
+         auto *TypeDesc = llvm::ConstantInt::get(
+             CGM.IntPtrTy,
+             CGM.getContext().getPointerAuthVTablePointerDiscriminator(
+                 VTTVT.getBase()));
+         Init = CGM.getConstantSignedPointer(Init, Schema.getKey(), 
AddressDesc,
+                                             TypeDesc);
+       } else {
+         Init = CGM.getConstantSignedPointer(Init, Schema, AddressDesc,
+                                             GlobalDecl(), QualType());
+       }
+     }
      VTTComponents.push_back(Init);
   }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 6d0718c243812..c590551c2b9ac 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4659,6 +4659,9 @@ class CodeGenFunction : public CodeGenTypeCache {
   /// Create the discriminator from the storage address and the entity hash.
   llvm::Value *EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress,
                                                  llvm::Value *Discriminator);
+  CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema,
+                                        llvm::Value *StorageAddress,
+                                        llvm::ConstantInt *Discriminator);
   CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema,
                                         llvm::Value *StorageAddress,
                                         GlobalDecl SchemaDecl,
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index b4b3284f752ae..da3f29d8820cb 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -29,6 +29,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Basic/PointerAuthOptions.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalValue.h"
@@ -2221,13 +2222,21 @@ llvm::Value 
*ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
       CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
                                     CGF.getPointerAlign());
 
-  if (auto &Schema = 
CGF.CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) {
-    CGPointerAuthInfo PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTT,
-                                                            GlobalDecl(),
-                                                            QualType());
+  if (auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) {
+    CGPointerAuthInfo PointerAuth;
+    if (Schema.getOtherDiscrimination() ==
+        PointerAuthSchema::Discrimination::Type) {
+      auto *TypeDesc = llvm::ConstantInt::get(
+          CGM.IntPtrTy,
+          CGM.getContext().getPointerAuthVTablePointerDiscriminator(
+              VTableClass));
+      PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTT, TypeDesc);
+    } else {
+      PointerAuth =
+          CGF.EmitPointerAuthInfo(Schema, VTT, GlobalDecl(), QualType());
+    }
     AP = CGF.EmitPointerAuthAuth(PointerAuth, AP);
   }
-
   return AP;
 }
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 418d540895681..518f10c92a373 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1728,6 +1728,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
     Args.addOptInFlag(
         CmdArgs, options::OPT_fptrauth_vtable_pointer_type_discrimination,
         options::OPT_fno_ptrauth_vtable_pointer_type_discrimination);
+    Args.addOptInFlag(
+        CmdArgs, options::OPT_fptrauth_vtt_vtable_pointer_discrimination,
+        options::OPT_fno_ptrauth_vtt_vtable_pointer_discrimination);
     Args.addOptInFlag(
         CmdArgs, options::OPT_fptrauth_type_info_vtable_pointer_discrimination,
         options::OPT_fno_ptrauth_type_info_vtable_pointer_discrimination);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index dfde7b756dbff..8b6548f35b491 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1480,8 +1480,15 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
       Opts.CXXTypeInfoVTablePointer =
           PointerAuthSchema(Key::ASDA, false, Discrimination::None);
 
-    Opts.CXXVTTVTablePointers =
-        PointerAuthSchema(Key::ASDA, false, Discrimination::None);
+    if (LangOpts.PointerAuthVTTVTPtrDiscrimination)
+      Opts.CXXVTTVTablePointers = PointerAuthSchema(
+          Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
+          LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
+                                                      : Discrimination::None);
+    else
+      Opts.CXXVTTVTablePointers =
+          PointerAuthSchema(Key::ASDA, false, Discrimination::None);
+
     Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers =
         PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);
     Opts.CXXMemberFunctionPointers =
@@ -3592,6 +3599,8 @@ static void GeneratePointerAuthArgs(const LangOptions 
&Opts,
     GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
   if (Opts.PointerAuthVTPtrTypeDiscrimination)
     GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
+  if (Opts.PointerAuthVTTVTPtrDiscrimination)
+    GenerateArg(Consumer, OPT_fptrauth_vtt_vtable_pointer_discrimination);
   if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)
     GenerateArg(Consumer, 
OPT_fptrauth_type_info_vtable_pointer_discrimination);
   if (Opts.PointerAuthFunctionTypeDiscrimination)
@@ -3625,6 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, 
ArgList &Args,
       Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
   Opts.PointerAuthVTPtrTypeDiscrimination =
       Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
+  Opts.PointerAuthVTTVTPtrDiscrimination =
+      Args.hasArg(OPT_fptrauth_vtt_vtable_pointer_discrimination);
   Opts.PointerAuthTypeInfoVTPtrDiscrimination =
       Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);
   Opts.PointerAuthFunctionTypeDiscrimination =
diff --git a/clang/test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp 
b/clang/test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp
new file mode 100644
index 0000000000000..1a81946dd3241
--- /dev/null
+++ b/clang/test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp
@@ -0,0 +1,99 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-pauthtest 
-fptrauth-calls -disable-llvm-passes \
+// RUN:     -emit-llvm -O0 -o - | FileCheck --check-prefixes=CHECK,DEFAULT %s
+// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-pauthtest 
-fptrauth-calls -fptrauth-vtt-vtable-pointer-discrimination \
+// RUN:     -disable-llvm-passes -emit-llvm -O0 -o - | FileCheck 
--check-prefixes=CHECK,DEFAULT %s
+// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-pauthtest 
-fptrauth-calls -fptrauth-vtt-vtable-pointer-discrimination \
+// RUN:     -fptrauth-vtable-pointer-address-discrimination 
-disable-llvm-passes -emit-llvm -O0 -o - | FileCheck 
--check-prefixes=CHECK,ADDRESS %s
+// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-pauthtest 
-fptrauth-calls -fptrauth-vtt-vtable-pointer-discrimination \
+// RUN:     -fptrauth-vtable-pointer-type-discrimination -disable-llvm-passes 
-emit-llvm -O0 -o - | FileCheck --check-prefixes=CHECK,TYPE %s
+// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-pauthtest 
-fptrauth-calls -fptrauth-vtt-vtable-pointer-discrimination \
+// RUN:     -fptrauth-vtable-pointer-address-discrimination 
-fptrauth-vtable-pointer-type-discrimination       \
+// RUN:     -disable-llvm-passes -emit-llvm -O0 -o - | FileCheck 
--check-prefixes=CHECK,ADDRESSTYPE %s
+
+// CHECK:      @_ZTT1D = linkonce_odr unnamed_addr constant [4 x ptr] [
+// DEFAULT-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2), 
+// DEFAULT-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2), 
+// DEFAULT-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2), 
+// DEFAULT-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2)]
+
+// ADDRESS-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 0, ptr @_ZTT1D), 
+// ADDRESS-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2, i64 0, ptr 
getelementptr (ptr, ptr @_ZTT1D, i32 1)), 
+// ADDRESS-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2, i64 0, ptr 
getelementptr (ptr, ptr @_ZTT1D, i32 2)), 
+// ADDRESS-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 0, ptr getelementptr 
(ptr, ptr @_ZTT1D, i32 3))]
+
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 46475), 
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2, i64 62866), 
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2, i64 62866), 
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 46475)]
+
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 46475, ptr 
@_ZTT1D),
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2, i64 62866, ptr 
getelementptr (ptr, ptr @_ZTT1D, i32 1)),
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTC1D0_1A, i32 0, i32 0, i32 4), i32 2, i64 62866, ptr 
getelementptr (ptr, ptr @_ZTT1D, i32 2)),
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 46475, ptr 
getelementptr (ptr, ptr @_ZTT1D, i32 3))]
+
+// CHECK:      @_ZTT1A = linkonce_odr unnamed_addr constant [2 x ptr] [
+// DEFAULT-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2), 
+// DEFAULT-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2)]
+
+// ADDRESS-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 0, ptr @_ZTT1A), 
+// ADDRESS-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 
x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 0, ptr getelementptr 
(ptr, ptr @_ZTT1A, i32 1))]
+
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 62866),
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 62866)]
+
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 62866, ptr 
@_ZTT1A),
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 62866, ptr 
getelementptr (ptr, ptr @_ZTT1A, i32 1))]
+
+// CHECK-LABEL: @_ZN1AC2Ev
+// CHECK:       %vtt.addr = alloca ptr, align 8
+// CHECK:       store ptr %vtt, ptr %vtt.addr, align 8
+// CHECK:       [[VTT:%.*]] = load ptr, ptr %vtt.addr, align 8
+// CHECK:       [[VTABLE:%.*]] = load ptr, ptr [[VTT]], align 8
+// ADDRESS:     [[VTABLE_ADDR:%.*]] = ptrtoint ptr [[VTT]] to i64
+// ADDRESSTYPE: [[VTABLE_ADDR:%.*]] = ptrtoint ptr [[VTT]] to i64
+// ADDRESSTYPE: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 
[[VTABLE_ADDR]], i64 62866)
+// CHECK:       [[VTABLEi64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
+// DEFAULT:     call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 0)
+// ADDRESS:     call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 
[[VTABLE_ADDR]])
+// TYPE:        call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 
62866)
+// ADDRESSTYPE: call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 
[[DISC]])
+
+// CHECK:       [[VTTOFFSET:%.*]]  = getelementptr inbounds ptr, ptr [[VTT]], 
i64 1
+// CHECK:       [[VTABLE2:%.*]] = load ptr, ptr [[VTTOFFSET]], align 8
+// ADDRESS:     [[VTABLE2_ADDR:%.*]] = ptrtoint ptr [[VTTOFFSET]] to i64
+// ADDRESSTYPE: [[VTABLE2_ADDR:%.*]] = ptrtoint ptr [[VTTOFFSET]] to i64
+// ADDRESSTYPE: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 
[[VTABLE2_ADDR]], i64 62866)
+// CHECK:       [[VTABLE2i64:%.*]] = ptrtoint ptr [[VTABLE2]] to i64
+// DEFAULT:     call i64 @llvm.ptrauth.auth(i64 [[VTABLE2i64]], i32 2, i64 0)
+// ADDRESS:     call i64 @llvm.ptrauth.auth(i64 [[VTABLE2i64]], i32 2, i64 
[[VTABLE2_ADDR]])
+// TYPE:        call i64 @llvm.ptrauth.auth(i64 [[VTABLE2i64]], i32 2, i64 
62866)
+// ADDRESSTYPE: call i64 @llvm.ptrauth.auth(i64 [[VTABLE2i64]], i32 2, i64 
[[DISC]])
+
+// CHECK-LABEL: @_ZN1DC2Ev
+// CHECK:   %vtt.addr = alloca ptr, align 8
+// CHECK:   store ptr %vtt, ptr %vtt.addr, align 8
+// CHECK:   [[VTT:%.*]] = load ptr, ptr %vtt.addr, align 8
+// CHECK:   [[VTTOFFSET:%.*]] = getelementptr inbounds ptr, ptr [[VTT]], i64 1
+// CHECK:   call void @_ZN1AC2Ev(ptr noundef nonnull align 8 
dereferenceable(8) %this1, ptr noundef [[VTTOFFSET]])
+// CHECK:   [[VTABLE:%.*]] = load ptr, ptr [[VTT]], align 8
+// ADDRESS: [[VTABLE_ADDR:%.*]] = ptrtoint ptr [[VTT]] to i64
+// CHECK:   [[VTABLEi64:%.*]] = ptrtoint ptr [[VTABLE]] to i64
+// DEFAULT: call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 0)
+// ADDRESS: call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 
[[VTABLE_ADDR]])
+// TYPE:    call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 46475)
+
+struct V {
+    virtual void f();
+};
+
+struct A : virtual V {
+    A();
+};
+
+struct D : A {
+    D();
+};
+
+A::A() {}
+D::D() {}
diff --git a/clang/test/Driver/aarch64-ptrauth.c 
b/clang/test/Driver/aarch64-ptrauth.c
index a67e98fdda714..1a2050b941f4f 100644
--- a/clang/test/Driver/aarch64-ptrauth.c
+++ b/clang/test/Driver/aarch64-ptrauth.c
@@ -12,6 +12,7 @@
 // RUN:   -fno-ptrauth-auth-traps -fptrauth-auth-traps \
 // RUN:   -fno-ptrauth-vtable-pointer-address-discrimination 
-fptrauth-vtable-pointer-address-discrimination \
 // RUN:   -fno-ptrauth-vtable-pointer-type-discrimination 
-fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fno-ptrauth-vtt-vtable-pointer-discrimination 
-fptrauth-vtt-vtable-pointer-discrimination \
 // RUN:   -fno-ptrauth-type-info-vtable-pointer-discrimination 
-fptrauth-type-info-vtable-pointer-discrimination \
 // RUN:   -fno-ptrauth-indirect-gotos -fptrauth-indirect-gotos \
 // RUN:   -fno-ptrauth-init-fini -fptrauth-init-fini \
@@ -26,6 +27,7 @@
 // RUN:   -fno-ptrauth-auth-traps -fptrauth-auth-traps \
 // RUN:   -fno-ptrauth-vtable-pointer-address-discrimination 
-fptrauth-vtable-pointer-address-discrimination \
 // RUN:   -fno-ptrauth-vtable-pointer-type-discrimination 
-fptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fno-ptrauth-vtt-vtable-pointer-discrimination 
-fptrauth-vtt-vtable-pointer-discrimination \
 // RUN:   -fno-ptrauth-type-info-vtable-pointer-discrimination 
-fptrauth-type-info-vtable-pointer-discrimination \
 // RUN:   -fno-ptrauth-indirect-gotos -fptrauth-indirect-gotos \
 // RUN:   -fno-ptrauth-init-fini -fptrauth-init-fini \
@@ -33,7 +35,7 @@
 // RUN:   -fno-ptrauth-elf-got -fptrauth-elf-got \
 // RUN:   -fno-aarch64-jump-table-hardening -faarch64-jump-table-hardening \
 // RUN:   %s 2>&1 | FileCheck %s --check-prefix=ALL-LINUX-PAUTHABI
-// ALL-LINUX-PAUTHABI: "-cc1"{{.*}} "-fptrauth-intrinsics" "-fptrauth-calls" 
"-fptrauth-returns" "-fptrauth-auth-traps" 
"-fptrauth-vtable-pointer-address-discrimination" 
"-fptrauth-vtable-pointer-type-discrimination" 
"-fptrauth-type-info-vtable-pointer-discrimination" "-fptrauth-indirect-gotos" 
"-fptrauth-init-fini" "-fptrauth-init-fini-address-discrimination" 
"-fptrauth-elf-got"{{.*}} "-faarch64-jump-table-hardening"
+// ALL-LINUX-PAUTHABI: "-cc1"{{.*}} "-fptrauth-intrinsics" "-fptrauth-calls" 
"-fptrauth-returns" "-fptrauth-auth-traps" 
"-fptrauth-vtable-pointer-address-discrimination" 
"-fptrauth-vtable-pointer-type-discrimination" 
"-fptrauth-vtt-vtable-pointer-discrimination" 
"-fptrauth-type-info-vtable-pointer-discrimination" "-fptrauth-indirect-gotos" 
"-fptrauth-init-fini" "-fptrauth-init-fini-address-discrimination" 
"-fptrauth-elf-got"{{.*}} "-faarch64-jump-table-hardening"
 
 // RUN: %clang -### -c --target=aarch64-linux \
 // RUN:   -fno-aarch64-jump-table-hardening -faarch64-jump-table-hardening \
@@ -93,14 +95,16 @@
 //// Non-pauthtest ABI.
 // RUN: not %clang -### -c --target=aarch64-linux -fptrauth-intrinsics 
-fptrauth-calls -fptrauth-returns -fptrauth-auth-traps \
 // RUN:   -fptrauth-vtable-pointer-address-discrimination 
-fptrauth-vtable-pointer-type-discrimination \
-// RUN:   -fptrauth-type-info-vtable-pointer-discrimination 
-fptrauth-indirect-gotos -fptrauth-init-fini \
-// RUN:   -fptrauth-init-fini-address-discrimination -fptrauth-elf-got %s 2>&1 
| FileCheck %s --check-prefix=ERR1
+// RUN:   -fptrauth-vtt-vtable-pointer-discrimination 
-fptrauth-type-info-vtable-pointer-discrimination \
+// RUN:   -fptrauth-indirect-gotos -fptrauth-init-fini 
-fptrauth-init-fini-address-discrimination \
+// RUN:   -fptrauth-elf-got %s 2>&1 | FileCheck %s --check-prefix=ERR1
 // ERR1:      error: unsupported option '-fptrauth-intrinsics' for target 
'{{.*}}'
 // ERR1-NEXT: error: unsupported option '-fptrauth-calls' for target '{{.*}}'
 // ERR1-NEXT: error: unsupported option '-fptrauth-returns' for target '{{.*}}'
 // ERR1-NEXT: error: unsupported option '-fptrauth-auth-traps' for target 
'{{.*}}'
 // ERR1-NEXT: error: unsupported option 
'-fptrauth-vtable-pointer-address-discrimination' for target '{{.*}}'
 // ERR1-NEXT: error: unsupported option 
'-fptrauth-vtable-pointer-type-discrimination' for target '{{.*}}'
+// ERR1-NEXT: error: unsupported option 
'-fptrauth-vtt-vtable-pointer-discrimination' for target '{{.*}}'
 // ERR1-NEXT: error: unsupported option 
'-fptrauth-type-info-vtable-pointer-discrimination' for target '{{.*}}'
 // ERR1-NEXT: error: unsupported option '-fptrauth-indirect-gotos' for target 
'{{.*}}'
 // ERR1-NEXT: error: unsupported option '-fptrauth-init-fini' for target 
'{{.*}}'

>From 5b6ae0117d54733c4e6aadb78019b4ec9ffaabe3 Mon Sep 17 00:00:00 2001
From: Kristina Bessonova <[email protected]>
Date: Fri, 26 Jun 2026 11:11:29 +0200
Subject: [PATCH 2/2] Address review comment.

---
 clang/lib/CodeGen/CGPointerAuth.cpp | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp 
b/clang/lib/CodeGen/CGPointerAuth.cpp
index 0af3140404339..2f9c90ab99f40 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -122,13 +122,9 @@ CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo(
   if (!Schema)
     return CGPointerAuthInfo();
 
-  llvm::ConstantInt *Discriminator =
-      Schema.getOtherDiscrimination() == 
PointerAuthSchema::Discrimination::None
-          ? nullptr
-          : CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl,
-                                                 SchemaType);
-
-  return EmitPointerAuthInfo(Schema, StorageAddress, Discriminator);
+  return EmitPointerAuthInfo(
+      Schema, StorageAddress,
+      CGM.getPointerAuthOtherDiscriminator(Schema, SchemaDecl, SchemaType));
 }
 
 CGPointerAuthInfo

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to