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

>From c58bb45a896c2e4cc02700af751feb553034c412 Mon Sep 17 00:00:00 2001
From: Kristina Bessonova <[email protected]>
Date: Fri, 19 Jun 2026 18:08:22 +0200
Subject: [PATCH] [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`.

Explicit user control over the signing schema for VTT entries is not
currently supported.

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 primary base. To distinguish VTT entries from object vtable pointers,
the discriminator is derived from the vtable mangling with an appended
`_VTT` suffix.
---
 clang/include/clang/AST/ASTContext.h          |   4 +-
 clang/include/clang/Basic/Features.def        |   1 +
 clang/include/clang/Basic/LangOptions.def     |   1 +
 clang/include/clang/Options/Options.td        |   2 +
 clang/lib/AST/ASTContext.cpp                  |   5 +-
 clang/lib/CodeGen/CGPointerAuth.cpp           |  30 ++++--
 clang/lib/CodeGen/CGVTT.cpp                   |  27 +++--
 clang/lib/CodeGen/CodeGenFunction.h           |   3 +
 clang/lib/CodeGen/CodeGenModule.h             |  14 +--
 clang/lib/CodeGen/ItaniumCXXABI.cpp           |  10 +-
 clang/lib/Driver/ToolChains/Clang.cpp         |   3 +
 clang/lib/Driver/ToolChains/Linux.cpp         |   5 +
 clang/lib/Frontend/CompilerInvocation.cpp     |  15 ++-
 .../test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp | 102 ++++++++++++++++++
 clang/test/Driver/aarch64-ptrauth.c           |  14 ++-
 clang/test/Preprocessor/ptrauth_feature.c     |  33 ++++--
 16 files changed, 216 insertions(+), 53 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 7ed6509c3c16c..bc2ba9f3d9c91 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1515,8 +1515,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   /// Return the "other" discriminator used for the pointer auth schema used 
for
   /// vtable pointers in instances of the requested type.
-  uint16_t
-  getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD);
+  uint16_t getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD,
+                                                    bool IsVTTEntry = false);
 
   /// Return the "other" type-specific discriminator for the given type.
   uint16_t getPointerAuthTypeDiscriminator(QualType T);
diff --git a/clang/include/clang/Basic/Features.def 
b/clang/include/clang/Basic/Features.def
index f0a9c4889ea2d..cfd5bf69f938c 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 1fb491a54a278..2240c9d506ff3 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -126,6 +126,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 77c93db0079d5..967f057d12e38 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4991,6 +4991,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/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 2228811546c0f..a5aa05279db1e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3363,13 +3363,16 @@ QualType ASTContext::removeAddrSpaceQualType(QualType 
T) const {
 }
 
 uint16_t
-ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD) {
+ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD,
+                                                     bool IsVTTEntry) {
   assert(RD->isPolymorphic() &&
          "Attempted to get vtable pointer discriminator on a monomorphic 
type");
   std::unique_ptr<MangleContext> MC(createMangleContext());
   SmallString<256> Str;
   llvm::raw_svector_ostream Out(Str);
   MC->mangleCXXVTable(RD, Out);
+  if (IsVTTEntry)
+    Out << "_VTT";
   return llvm::getPointerAuthStableSipHash(Str);
 }
 
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp 
b/clang/lib/CodeGen/CGPointerAuth.cpp
index 28d3289dfe04f..0fbc889836399 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -561,18 +561,24 @@ llvm::Constant 
*CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD,
 }
 
 std::optional<PointerAuthQualifier>
-CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) {
-  auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers;
+CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass,
+                                              bool IsVTTEntry) {
+  auto DefaultAuthentication =
+      IsVTTEntry ? getCodeGenOpts().PointerAuth.CXXVTTVTablePointers
+                 : getCodeGenOpts().PointerAuth.CXXVTablePointers;
   if (!DefaultAuthentication)
     return std::nullopt;
   const CXXRecordDecl *PrimaryBase =
       Context.baseForVTableAuthentication(ThisClass);
+  const CXXRecordDecl *TypeDiscriminatorClass =
+      IsVTTEntry ? ThisClass : PrimaryBase;
 
   unsigned Key = DefaultAuthentication.getKey();
   bool AddressDiscriminated = DefaultAuthentication.isAddressDiscriminated();
   auto DefaultDiscrimination = DefaultAuthentication.getOtherDiscrimination();
   unsigned TypeBasedDiscriminator =
-      Context.getPointerAuthVTablePointerDiscriminator(PrimaryBase);
+      Context.getPointerAuthVTablePointerDiscriminator(TypeDiscriminatorClass,
+                                                       IsVTTEntry);
   unsigned Discriminator;
   if (DefaultDiscrimination == PointerAuthSchema::Discrimination::Type) {
     Discriminator = TypeBasedDiscriminator;
@@ -583,8 +589,11 @@ CodeGenModule::computeVTPointerAuthentication(const 
CXXRecordDecl *ThisClass) {
     assert(DefaultDiscrimination == PointerAuthSchema::Discrimination::None);
     Discriminator = 0;
   }
-  if (auto ExplicitAuthentication =
-          PrimaryBase->getAttr<VTablePointerAuthenticationAttr>()) {
+  auto ExplicitAuthentication =
+      PrimaryBase->getAttr<VTablePointerAuthenticationAttr>();
+
+  // TODO: enable explicit authentication path for VTT vtable entries.
+  if (!IsVTTEntry && ExplicitAuthentication) {
     auto ExplicitAddressDiscrimination =
         ExplicitAuthentication->getAddressDiscrimination();
     auto ExplicitDiscriminator =
@@ -642,11 +651,12 @@ CodeGenModule::getVTablePointerAuthentication(const 
CXXRecordDecl *Record) {
   return Authentication;
 }
 
-std::optional<CGPointerAuthInfo>
-CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF,
-                                        const CXXRecordDecl *Record,
-                                        llvm::Value *StorageAddress) {
-  auto Authentication = getVTablePointerAuthentication(Record);
+std::optional<CGPointerAuthInfo> CodeGenModule::getVTablePointerAuthInfo(
+    CodeGenFunction *CGF, const CXXRecordDecl *Record,
+    llvm::Value *StorageAddress, bool IsVTTEntry) {
+  auto Authentication = IsVTTEntry
+                            ? computeVTPointerAuthentication(Record, 
IsVTTEntry)
+                            : getVTablePointerAuthentication(Record);
   if (!Authentication)
     return std::nullopt;
 
diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp
index 989a07d09d50e..caf51d10a4080 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!");
     }
@@ -91,11 +90,17 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
      llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
          VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
 
-     if (const auto &Schema =
-             CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers)
-       Init = CGM.getConstantSignedPointer(Init, Schema, nullptr, GlobalDecl(),
-                                           QualType());
-
+     if (auto PAuthQual = CGM.computeVTPointerAuthentication(
+             VTTVT.getBase(), /*IsVTTEntry=*/true)) {
+       llvm::Constant *Address = nullptr;
+       if (PAuthQual->isAddressDiscriminated())
+         Address = llvm::ConstantExpr::getGetElementPtr(
+             VTT->getType(), VTT, llvm::ConstantInt::get(CGM.Int32Ty, Idx));
+       auto *Discriminator = llvm::ConstantInt::get(
+           CGM.IntPtrTy, PAuthQual->getExtraDiscriminator());
+       Init = CGM.getConstantSignedPointer(Init, PAuthQual->getKey(), Address,
+                                           Discriminator);
+     }
      VTTComponents.push_back(Init);
   }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index e7c24f1f36f1e..af2107dbbb920 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4668,6 +4668,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/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index 0abd75ccb0551..ed14244ea0457 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -718,8 +718,6 @@ class CodeGenModule : public CodeGenTypeCache {
 
   llvm::DenseMap<const CXXRecordDecl *, std::optional<PointerAuthQualifier>>
       VTablePtrAuthInfos;
-  std::optional<PointerAuthQualifier>
-  computeVTPointerAuthentication(const CXXRecordDecl *ThisClass);
 
   AtomicOptions AtomicOpts;
 
@@ -1160,14 +1158,18 @@ class CodeGenModule : public CodeGenTypeCache {
                                    GlobalDecl SchemaDecl, QualType SchemaType);
 
   uint16_t getPointerAuthDeclDiscriminator(GlobalDecl GD);
-  std::optional<CGPointerAuthInfo>
-  getVTablePointerAuthInfo(CodeGenFunction *Context,
-                           const CXXRecordDecl *Record,
-                           llvm::Value *StorageAddress);
+
+  std::optional<CGPointerAuthInfo> getVTablePointerAuthInfo(
+      CodeGenFunction *Context, const CXXRecordDecl *Record,
+      llvm::Value *StorageAddress, bool IsVTTEntry = false);
 
   std::optional<PointerAuthQualifier>
   getVTablePointerAuthentication(const CXXRecordDecl *thisClass);
 
+  std::optional<PointerAuthQualifier>
+  computeVTPointerAuthentication(const CXXRecordDecl *ThisClass,
+                                 bool IsVTTEntry = false);
+
   CGPointerAuthInfo EmitPointerAuthInfo(const RecordDecl *RD);
 
   // Return whether RTTI information should be emitted for this target.
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index b17478cb7ffde..f16293f4c2658 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"
@@ -2231,13 +2232,10 @@ 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());
-    AP = CGF.EmitPointerAuthAuth(PointerAuth, AP);
+  if (auto PointerAuth = CGM.getVTablePointerAuthInfo(&CGF, VTableClass, VTT,
+                                                      /*IsVTTEntry=*/true)) {
+    AP = CGF.EmitPointerAuthAuth(*PointerAuth, AP);
   }
-
   return AP;
 }
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 961906e02639a..3aea4f4bcb26d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1732,6 +1732,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/Driver/ToolChains/Linux.cpp 
b/clang/lib/Driver/ToolChains/Linux.cpp
index 8d30a5ead3bbb..19d5c707951e3 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -527,6 +527,11 @@ static void handlePAuthABI(const Driver &D, const ArgList 
&DriverArgs,
           options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
     CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");
 
+  if (!DriverArgs.hasArg(
+          options::OPT_fptrauth_vtt_vtable_pointer_discrimination,
+          options::OPT_fno_ptrauth_vtt_vtable_pointer_discrimination))
+    CC1Args.push_back("-fptrauth-vtt-vtable-pointer-discrimination");
+
   if (!DriverArgs.hasArg(
           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 6545307a8c8a7..9daee578ff242 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 =
@@ -3599,6 +3606,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)
@@ -3632,6 +3641,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..1c344d5247eaf
--- /dev/null
+++ b/clang/test/CodeGenCXX/ptrauth-vtable-in-vtt.cpp
@@ -0,0 +1,102 @@
+// 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 820),
+// 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 49118),
+// 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 49118),
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 820)]
+
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 4), i32 2, i64 820, 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 49118, 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 49118, 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 820, 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 49118),
+// TYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) ({ [5 x 
ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 49118)]
+
+// ADDRESSTYPE-SAME: ptr ptrauth (ptr getelementptr inbounds inrange(-32, 8) 
({ [5 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 4), i32 2, i64 49118, 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 49118, 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 49118)
+// 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 
49118)
+// 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 49118)
+// 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 
49118)
+// 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
+// ADDRESSTYPE: [[VTABLE_ADDR:%.*]] = ptrtoint ptr [[VTT]] to i64
+// ADDRESSTYPE: [[DISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 
[[VTABLE_ADDR]], i64 820)
+// 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 820)
+// ADDRESSTYPE: call i64 @llvm.ptrauth.auth(i64 [[VTABLEi64]], i32 2, i64 
[[DISC]])
+
+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..b328ddfe0ac9d 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 \
@@ -57,19 +59,21 @@
 // RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest %s 2>&1 | 
FileCheck %s --check-prefix=PAUTHABI1
 // RUN: %clang -### -c --target=aarch64-linux-pauthtest %s 2>&1 | FileCheck %s 
--check-prefix=PAUTHABI1
 // PAUTHABI1:      "-cc1"{{.*}} "-triple" "aarch64-unknown-linux-pauthtest"
-// PAUTHABI1-SAME: "-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" 
"-faarch64-jump-table-hardening"
+// PAUTHABI1-SAME: "-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" 
"-faarch64-jump-table-hardening"
 // PAUTHABI1-SAME: "-target-abi" "pauthtest"
 // PAUTHABI1-NOT: "-fptrauth-function-pointer-type-discrimination"
 
 // RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest 
-fno-ptrauth-intrinsics \
 // RUN:   -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \
 // RUN:   -fno-ptrauth-vtable-pointer-address-discrimination 
-fno-ptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fno-ptrauth-vtt-vtable-pointer-discrimination \
 // RUN:   -fno-ptrauth-type-info-vtable-pointer-discrimination 
-fno-ptrauth-indirect-gotos \
 // RUN:   -fno-ptrauth-init-fini -fno-ptrauth-init-fini-address-discrimination 
\
 // RUN:   -fno-aarch64-jump-table-hardening %s 2>&1 | FileCheck %s 
--check-prefix=PAUTHABI2
 // RUN: %clang -### -c --target=aarch64-linux-pauthtest 
-fno-ptrauth-intrinsics \
 // RUN:   -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \
 // RUN:   -fno-ptrauth-vtable-pointer-address-discrimination 
-fno-ptrauth-vtable-pointer-type-discrimination \
+// RUN:   -fno-ptrauth-vtt-vtable-pointer-discrimination \
 // RUN:   -fno-ptrauth-type-info-vtable-pointer-discrimination 
-fno-ptrauth-indirect-gotos \
 // RUN:   -fno-ptrauth-init-fini -fno-ptrauth-init-fini-address-discrimination 
\
 // RUN:   -fno-aarch64-jump-table-hardening %s 2>&1 | FileCheck %s 
--check-prefix=PAUTHABI2
@@ -93,14 +97,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 
'{{.*}}'
diff --git a/clang/test/Preprocessor/ptrauth_feature.c 
b/clang/test/Preprocessor/ptrauth_feature.c
index cebea4188415f..c187dd0160355 100644
--- a/clang/test/Preprocessor/ptrauth_feature.c
+++ b/clang/test/Preprocessor/ptrauth_feature.c
@@ -2,37 +2,40 @@
 //// For example, -fptrauth-init-fini will not affect codegen without 
-fptrauth-calls, but the preprocessor feature would be set anyway.
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-intrinsics | \
-// RUN:   FileCheck %s 
--check-prefixes=INTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=INTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-calls | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,CALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,CALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-returns | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,RETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,RETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 
-fptrauth-vtable-pointer-address-discrimination | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
+
+// RUN: %clang_cc1 -E %s -triple=aarch64 
-fptrauth-vtt-vtable-pointer-discrimination | \
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,VTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 
-fptrauth-vtable-pointer-type-discrimination | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 
-fptrauth-type-info-vtable-pointer-discrimination | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,TYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,TYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 
-fptrauth-function-pointer-type-discrimination | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,FUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,FUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-init-fini | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,INITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,INITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 
-fptrauth-init-fini-address-discrimination | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,INITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,INITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-indirect-gotos | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,GOTOS,NOELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,GOTOS,NOELFGOT,NOVTT
 
 // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-elf-got | \
-// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,ELFGOT
+// RUN:   FileCheck %s 
--check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,ELFGOT,NOVTT
 
 #if defined(__PTRAUTH__)
 // INTRIN: has_ptrauth_intrinsics
@@ -83,6 +86,14 @@ void has_ptrauth_vtable_pointer_type_discrimination() {}
 void no_ptrauth_vtable_pointer_type_discrimination() {}
 #endif
 
+#if __has_feature(ptrauth_vtt_vtable_pointer_discrimination)
+// VTT: has_ptrauth_vtt_vtable_pointer_discrimination
+void has_ptrauth_vtt_vtable_pointer_discrimination() {}
+#else
+// NOVTT: no_ptrauth_vtt_vtable_pointer_discrimination
+void no_ptrauth_vtt_vtable_pointer_discrimination() {}
+#endif
+
 #if __has_feature(ptrauth_type_info_vtable_pointer_discrimination)
 // TYPE_INFO_DISCR: has_ptrauth_type_info_vtable_pointer_discrimination
 void has_ptrauth_type_info_vtable_pointer_discrimination() {}

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

Reply via email to