https://github.com/ojhunt updated 
https://github.com/llvm/llvm-project/pull/143969

>From f47680310ed68a9f8e8cb15bc1cd474740072463 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Thu, 12 Jun 2025 13:17:11 -0700
Subject: [PATCH 1/7] [clang] Fix PointerAuth semantics of
 cpp_trivially_relocatable

This adds a function to ASTContext to query whether a type contains
values with address discriminated pointer auth, and performs the
required semantic checks to ensure correct reporting of relocatablity
in those cases.

For the standardized version, __builtin_is_cpp_trivially_relocatable
this means rejecting unions of types containing address discriminated
values.

For the old deprecated __builtin_is_trivially_relocatable this means
rejecting any type containing an address discriminated value.

This PR does not update the codegen for __builtin_trivially_relocate,
that will be in a follow on PR that is much more complex.
---
 clang/include/clang/AST/ASTContext.h          |   4 +
 clang/lib/AST/ASTContext.cpp                  |  49 +++++++++
 clang/lib/Sema/SemaTypeTraits.cpp             |  14 +--
 .../SemaCXX/cxx2c-trivially-relocatable.cpp   |   1 +
 clang/test/SemaCXX/ptrauth-triviality.cpp     |  10 +-
 .../SemaCXX/trivially-relocatable-ptrauth.cpp | 102 ++++++++++++++++++
 6 files changed, 169 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 8d24d393eab09..826f5257b0463 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -628,10 +628,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
   getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
   void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
                                      CXXRecordDeclRelocationInfo);
+  bool containsAddressDiscriminatedPointerAuth(QualType T);
 
 private:
   llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
       RelocatableClasses;
+  llvm::DenseMap<const RecordDecl *, bool>
+      RecordContainsAddressDiscriminatedPointerAuth;
 
   ImportDecl *FirstLocalImport = nullptr;
   ImportDecl *LastLocalImport = nullptr;
@@ -3668,6 +3671,7 @@ OPT_LIST(V)
   /// authentication policy for the specified record.
   const CXXRecordDecl *
   baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
+  bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
   bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
                                StringRef MangledName);
 
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b51f7622288df..34b540fd36efc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1705,6 +1705,40 @@ void ASTContext::setRelocationInfoForCXXRecord(
   RelocatableClasses.insert({D, Info});
 }
 
+bool ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
+  if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthIntrinsics)
+    return false;
+
+  T = T.getCanonicalType();
+  if (T.hasAddressDiscriminatedPointerAuth())
+    return true;
+  const RecordDecl *RD = T->getAsRecordDecl();
+  if (!RD)
+    return false;
+
+  auto SaveReturn = [this, RD](bool Result) {
+    RecordContainsAddressDiscriminatedPointerAuth.insert({RD, Result});
+    return Result;
+  };
+  if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
+      Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
+    return Existing->second;
+  if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+    if (CXXRD->isPolymorphic() &&
+        hasAddressDiscriminatedVTableAuthentication(CXXRD))
+      return SaveReturn(true);
+    for (auto Base : CXXRD->bases()) {
+      if (containsAddressDiscriminatedPointerAuth(Base.getType()))
+        return SaveReturn(true);
+    }
+  }
+  for (auto *FieldDecl : RD->fields()) {
+    if (containsAddressDiscriminatedPointerAuth(FieldDecl->getType()))
+      return SaveReturn(true);
+  }
+  return SaveReturn(false);
+}
+
 void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
   assert(!Import->getNextLocalImport() &&
          "Import declaration already in the chain");
@@ -15121,6 +15155,21 @@ ASTContext::baseForVTableAuthentication(const 
CXXRecordDecl *ThisClass) {
   return PrimaryBase;
 }
 
+bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
+    const CXXRecordDecl *Class) {
+  assert(Class->isPolymorphic());
+  const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
+  using AuthAttr = VTablePointerAuthenticationAttr;
+  const auto *ExplicitAuth = BaseType->getAttr<AuthAttr>();
+  if (!ExplicitAuth)
+    return LangOpts.PointerAuthVTPtrAddressDiscrimination;
+  AuthAttr::AddressDiscriminationMode AddressDiscrimination =
+      ExplicitAuth->getAddressDiscrimination();
+  if (AddressDiscrimination == AuthAttr::DefaultAddressDiscrimination)
+    return LangOpts.PointerAuthVTPtrAddressDiscrimination;
+  return AddressDiscrimination == AuthAttr::AddressDiscrimination;
+}
+
 bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
                                          StringRef MangledName) {
   auto *Method = cast<CXXMethodDecl>(VirtualMethodDecl.getDecl());
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp 
b/clang/lib/Sema/SemaTypeTraits.cpp
index 1738ab4466001..43af236068655 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -188,15 +188,20 @@ static bool IsEligibleForTrivialRelocation(Sema &SemaRef,
       return false;
   }
 
+  bool IsUnion = D->isUnion();
   for (const FieldDecl *Field : D->fields()) {
-    if (Field->getType()->isDependentType())
+    QualType FieldType = Field->getType();
+    if (FieldType->isDependentType())
       continue;
-    if (Field->getType()->isReferenceType())
+    if (FieldType->isReferenceType())
       continue;
     // ... has a non-static data member of an object type that is not
     // of a trivially relocatable type
     if (!SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))
       return false;
+    if (IsUnion &&
+        SemaRef.Context.containsAddressDiscriminatedPointerAuth(FieldType))
+      return false;
   }
   return !D->hasDeletedDestructor();
 }
@@ -322,9 +327,6 @@ bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
   if (BaseElementType.hasNonTrivialObjCLifetime())
     return false;
 
-  if (BaseElementType.hasAddressDiscriminatedPointerAuth())
-    return false;
-
   if (BaseElementType->isIncompleteType())
     return false;
 
@@ -670,7 +672,7 @@ static bool IsTriviallyRelocatableType(Sema &SemaRef, 
QualType T) {
   if (!BaseElementType->isObjectType())
     return false;
 
-  if (T.hasAddressDiscriminatedPointerAuth())
+  if (SemaRef.getASTContext().containsAddressDiscriminatedPointerAuth(T))
     return false;
 
   if (const auto *RD = BaseElementType->getAsCXXRecordDecl();
diff --git a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp 
b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp
index 9d43994ee7661..7152a5937d9b7 100644
--- a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp
+++ b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++2c -verify %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-intrinsics 
-fptrauth-calls -std=c++2c -verify %s
 
 class Trivial {};
 static_assert(__builtin_is_cpp_trivially_relocatable(Trivial));
diff --git a/clang/test/SemaCXX/ptrauth-triviality.cpp 
b/clang/test/SemaCXX/ptrauth-triviality.cpp
index 60d1b57230f18..6f3650f7ac2e3 100644
--- a/clang/test/SemaCXX/ptrauth-triviality.cpp
+++ b/clang/test/SemaCXX/ptrauth-triviality.cpp
@@ -26,7 +26,7 @@ static_assert(!__is_trivially_assignable(S1, const S1&));
 static_assert(__is_trivially_destructible(S1));
 static_assert(!__is_trivially_copyable(S1));
 static_assert(!__is_trivially_relocatable(S1)); // 
expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(S1));
+static_assert(__builtin_is_cpp_trivially_relocatable(S1));
 static_assert(!__is_trivially_equality_comparable(S1));
 
 static_assert(__is_trivially_constructible(Holder<S1>));
@@ -35,7 +35,7 @@ static_assert(!__is_trivially_assignable(Holder<S1>, const 
Holder<S1>&));
 static_assert(__is_trivially_destructible(Holder<S1>));
 static_assert(!__is_trivially_copyable(Holder<S1>));
 static_assert(!__is_trivially_relocatable(Holder<S1>)); // 
expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(Holder<S1>));
+static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S1>));
 static_assert(!__is_trivially_equality_comparable(Holder<S1>));
 
 struct S2 {
@@ -83,7 +83,7 @@ static_assert(!__is_trivially_constructible(Holder<S3>, const 
Holder<S3>&));
 static_assert(!__is_trivially_assignable(Holder<S3>, const Holder<S3>&));
 static_assert(__is_trivially_destructible(Holder<S3>));
 static_assert(!__is_trivially_copyable(Holder<S3>));
-static_assert(__is_trivially_relocatable(Holder<S3>)); // 
expected-warning{{deprecated}}
+static_assert(!__is_trivially_relocatable(Holder<S3>)); // 
expected-warning{{deprecated}}
 static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S3>));
 static_assert(!__is_trivially_equality_comparable(Holder<S3>));
 
@@ -148,7 +148,7 @@ static_assert(!__is_trivially_assignable(S6, const S6&));
 static_assert(__is_trivially_destructible(S6));
 static_assert(!__is_trivially_copyable(S6));
 static_assert(!__is_trivially_relocatable(S6)); // 
expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(S6));
+static_assert(__builtin_is_cpp_trivially_relocatable(S6));
 static_assert(!__is_trivially_equality_comparable(S6));
 
 static_assert(__is_trivially_constructible(Holder<S6>));
@@ -157,7 +157,7 @@ static_assert(!__is_trivially_assignable(Holder<S6>, const 
Holder<S6>&));
 static_assert(__is_trivially_destructible(Holder<S6>));
 static_assert(!__is_trivially_copyable(Holder<S6>));
 static_assert(!__is_trivially_relocatable(Holder<S6>)); // 
expected-warning{{deprecated}}
-static_assert(!__builtin_is_cpp_trivially_relocatable(Holder<S6>));
+static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S6>));
 static_assert(!__is_trivially_equality_comparable(Holder<S6>));
 
 struct S7 {
diff --git a/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp 
b/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp
new file mode 100644
index 0000000000000..29722fadd4d17
--- /dev/null
+++ b/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -triple arm64 -fptrauth-calls -fptrauth-intrinsics 
-std=c++26 -verify %s
+
+// This test intentionally does not enable the global address discrimination
+// of vtable pointers. This lets us configure them with different schemas
+// and verify that we're correctly tracking the existence of address 
discrimination
+
+// expected-no-diagnostics
+
+struct NonAddressDiscPtrauth {
+  void * __ptrauth(1, 0, 1234) p;
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(NonAddressDiscPtrauth));
+
+struct AddressDiscPtrauth {
+  void * __ptrauth(1, 1, 1234) p;
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(AddressDiscPtrauth));
+
+struct MultipleBaseClasses : NonAddressDiscPtrauth, AddressDiscPtrauth {
+
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(MultipleBaseClasses));
+
+struct MultipleMembers {
+   NonAddressDiscPtrauth field0;
+   AddressDiscPtrauth field1;
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(MultipleMembers));
+
+struct UnionOfPtrauth {
+    union {
+        NonAddressDiscPtrauth field0;
+        AddressDiscPtrauth field1;
+    } u;
+};
+
+static_assert(!__builtin_is_cpp_trivially_relocatable(UnionOfPtrauth));
+
+struct 
[[clang::ptrauth_vtable_pointer(process_independent,address_discrimination,no_extra_discrimination)]]
 Polymorphic trivially_relocatable_if_eligible {
+  virtual ~Polymorphic();
+};
+
+struct Foo : Polymorphic {
+  Foo(const Foo&);
+  ~Foo();
+};
+
+
+static_assert(__builtin_is_cpp_trivially_relocatable(Polymorphic));
+
+struct 
[[clang::ptrauth_vtable_pointer(process_independent,no_address_discrimination,no_extra_discrimination)]]
 NonAddressDiscriminatedPolymorphic trivially_relocatable_if_eligible {
+  virtual ~NonAddressDiscriminatedPolymorphic();
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(NonAddressDiscriminatedPolymorphic));
+
+
+struct PolymorphicMembers {
+    Polymorphic field;
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(PolymorphicMembers));
+
+struct UnionOfPolymorphic {
+  union trivially_relocatable_if_eligible {
+    Polymorphic p;
+    int i;
+  } u;
+};
+
+static_assert(!__builtin_is_cpp_trivially_relocatable(UnionOfPolymorphic));
+
+
+struct UnionOfNonAddressDiscriminatedPolymorphic {
+  union trivially_relocatable_if_eligible {
+    NonAddressDiscriminatedPolymorphic p;
+    int i;
+  } u;
+};
+static_assert(!__builtin_is_cpp_trivially_relocatable(UnionOfNonAddressDiscriminatedPolymorphic));
+
+struct UnionOfNonAddressDiscriminatedPtrauth {
+  union {
+    NonAddressDiscPtrauth p;
+    int i;
+  } u;
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(UnionOfNonAddressDiscriminatedPtrauth));
+
+struct UnionOfAddressDisriminatedPtrauth {
+  union {
+    AddressDiscPtrauth p;
+    int i;
+  } u;
+};
+
+static_assert(!__builtin_is_cpp_trivially_relocatable(UnionOfAddressDisriminatedPtrauth));

>From 3190a524391c5f31f957ef369359b1f631c32e07 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Thu, 12 Jun 2025 17:23:41 -0700
Subject: [PATCH 2/7] Add comments and more tests

---
 clang/include/clang/AST/ASTContext.h      | 20 +++++++++++
 clang/lib/AST/ASTContext.cpp              | 14 ++++----
 clang/lib/Sema/SemaTypeTraits.cpp         | 16 +++++----
 clang/test/SemaCXX/ptrauth-triviality.cpp | 42 ++++++++++++++++++++---
 4 files changed, 76 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 826f5257b0463..68b8d67ab4828 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -628,11 +628,25 @@ class ASTContext : public RefCountedBase<ASTContext> {
   getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
   void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
                                      CXXRecordDeclRelocationInfo);
+
+  /// Examines a given type, and returns whether the T itself
+  /// is address discriminated, or any transitively embedded types
+  /// contain data that is address discriminated. This includes
+  /// implicitly authenticated values like vtable pointers, as well as
+  /// explicitly qualified fields.
   bool containsAddressDiscriminatedPointerAuth(QualType T);
 
 private:
+  // A simple helper function to short circuit pointer auth checks.
+  bool isPointerAuthenticationAvailable() const {
+    return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics ||
+           LangOpts.PointerAuthVTPtrAddressDiscrimination;
+  }
+
   llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
       RelocatableClasses;
+
+  // FIXME: store in RecordDeclBitfields in future?
   llvm::DenseMap<const RecordDecl *, bool>
       RecordContainsAddressDiscriminatedPointerAuth;
 
@@ -3671,7 +3685,13 @@ OPT_LIST(V)
   /// authentication policy for the specified record.
   const CXXRecordDecl *
   baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
+
+  /// If this class is polymorphic, returns true if any of this class's
+  /// vtable pointers have an address discriminated pointer authentication
+  /// schema.
+  /// This does not check fields of the class or base classes.
   bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
+
   bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
                                StringRef MangledName);
 
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 34b540fd36efc..6db95ac106703 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1706,7 +1706,7 @@ void ASTContext::setRelocationInfoForCXXRecord(
 }
 
 bool ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
-  if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthIntrinsics)
+  if (!isPointerAuthenticationAvailable())
     return false;
 
   T = T.getCanonicalType();
@@ -1716,13 +1716,14 @@ bool 
ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
   if (!RD)
     return false;
 
+  if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
+      Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
+    return Existing->second;
+
   auto SaveReturn = [this, RD](bool Result) {
     RecordContainsAddressDiscriminatedPointerAuth.insert({RD, Result});
     return Result;
   };
-  if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
-      Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
-    return Existing->second;
   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
     if (CXXRD->isPolymorphic() &&
         hasAddressDiscriminatedVTableAuthentication(CXXRD))
@@ -15157,10 +15158,11 @@ ASTContext::baseForVTableAuthentication(const 
CXXRecordDecl *ThisClass) {
 
 bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
     const CXXRecordDecl *Class) {
-  assert(Class->isPolymorphic());
+  if (!isPointerAuthenticationAvailable() || !Class->isPolymorphic())
+    return false;
   const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
   using AuthAttr = VTablePointerAuthenticationAttr;
-  const auto *ExplicitAuth = BaseType->getAttr<AuthAttr>();
+  const AuthAttr *ExplicitAuth = BaseType->getAttr<AuthAttr>();
   if (!ExplicitAuth)
     return LangOpts.PointerAuthVTPtrAddressDiscrimination;
   AuthAttr::AddressDiscriminationMode AddressDiscrimination =
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp 
b/clang/lib/Sema/SemaTypeTraits.cpp
index 43af236068655..a0b989fc33b2a 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -190,17 +190,19 @@ static bool IsEligibleForTrivialRelocation(Sema &SemaRef,
 
   bool IsUnion = D->isUnion();
   for (const FieldDecl *Field : D->fields()) {
-    QualType FieldType = Field->getType();
-    if (FieldType->isDependentType())
+    if (Field->getType()->isDependentType())
       continue;
-    if (FieldType->isReferenceType())
+    if (Field->getType()->isReferenceType())
       continue;
     // ... has a non-static data member of an object type that is not
     // of a trivially relocatable type
     if (!SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))
       return false;
-    if (IsUnion &&
-        SemaRef.Context.containsAddressDiscriminatedPointerAuth(FieldType))
+
+    // A union contains values with address discriminated pointer auth
+    // cannot be relocated.
+    if (IsUnion && SemaRef.Context.containsAddressDiscriminatedPointerAuth(
+                       Field->getType()))
       return false;
   }
   return !D->hasDeletedDestructor();
@@ -318,7 +320,6 @@ bool Sema::IsCXXTriviallyRelocatableType(const 
CXXRecordDecl &RD) {
 }
 
 bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
-
   QualType BaseElementType = getASTContext().getBaseElementType(Type);
 
   if (Type->isVariableArrayType())
@@ -672,6 +673,9 @@ static bool IsTriviallyRelocatableType(Sema &SemaRef, 
QualType T) {
   if (!BaseElementType->isObjectType())
     return false;
 
+  // The deprecated __builtin_is_trivially_relocatable does not have
+  // an equivalent to __builtin_trivially_relocate, so there is no
+  // safe way to use it if there are any address discriminated values.
   if (SemaRef.getASTContext().containsAddressDiscriminatedPointerAuth(T))
     return false;
 
diff --git a/clang/test/SemaCXX/ptrauth-triviality.cpp 
b/clang/test/SemaCXX/ptrauth-triviality.cpp
index 6f3650f7ac2e3..2c95e93239790 100644
--- a/clang/test/SemaCXX/ptrauth-triviality.cpp
+++ b/clang/test/SemaCXX/ptrauth-triviality.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++20 -fptrauth-calls 
-fptrauth-intrinsics -verify -fsyntax-only %s
-// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++20 -fptrauth-calls 
-fptrauth-intrinsics -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++26 -fptrauth-calls 
-fptrauth-intrinsics -verify -fsyntax-only %s
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++26 -fptrauth-calls 
-fptrauth-intrinsics -verify -fsyntax-only %s
 
 #define AQ __ptrauth(1,1,50)
 #define IQ __ptrauth(1,0,50)
@@ -99,7 +99,6 @@ static_assert(!__is_trivially_assignable(S4, const S4&));
 static_assert(__is_trivially_destructible(S4));
 static_assert(!__is_trivially_copyable(S4));
 static_assert(!__is_trivially_relocatable(S4)); // 
expected-warning{{deprecated}}
-//FIXME
 static_assert(__builtin_is_cpp_trivially_relocatable(S4));
 static_assert(!__is_trivially_equality_comparable(S4));
 
@@ -124,7 +123,6 @@ static_assert(!__is_trivially_assignable(S5, const S5&));
 static_assert(__is_trivially_destructible(S5));
 static_assert(!__is_trivially_copyable(S5));
 static_assert(!__is_trivially_relocatable(S5)); // 
expected-warning{{deprecated}}
-//FIXME
 static_assert(__builtin_is_cpp_trivially_relocatable(S5));
 static_assert(!__is_trivially_equality_comparable(S5));
 
@@ -182,3 +180,39 @@ static_assert(__is_trivially_copyable(Holder<S7>));
 static_assert(__is_trivially_relocatable(Holder<S7>)); // 
expected-warning{{deprecated}}
 static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S7>));
 static_assert(__is_trivially_equality_comparable(Holder<S7>));
+
+template <class... Bases> struct MultipleInheriter : Bases... {
+};
+
+template <class T> static const bool test_is_trivially_relocatable_v = 
__builtin_is_cpp_trivially_relocatable(T);
+template <class... Types> static const bool 
multiple_inheritance_is_relocatable = 
test_is_trivially_relocatable_v<MultipleInheriter<Types...>>;
+template <class... Types> static const bool 
inheritance_relocatability_matches_bases_v =
+  (test_is_trivially_relocatable_v<Types> && ...) == 
multiple_inheritance_is_relocatable<Types...>;
+
+static_assert(multiple_inheritance_is_relocatable<S4, S5> == 
multiple_inheritance_is_relocatable<S5, S4>);
+static_assert(inheritance_relocatability_matches_bases_v<S4, S5>);
+static_assert(inheritance_relocatability_matches_bases_v<S5, S4>);
+
+struct AA AddressDiscriminatedPolymorphicBase 
trivially_relocatable_if_eligible {
+  virtual void foo();
+};
+
+struct IA NoAddressDiscriminatedPolymorphicBase 
trivially_relocatable_if_eligible {
+  virtual void bar();
+};
+
+template <class T> struct UnionWrapper trivially_relocatable_if_eligible {
+  union U {
+    T field1;
+  } u;
+};
+
+static_assert(test_is_trivially_relocatable_v<AddressDiscriminatedPolymorphicBase>);
+static_assert(test_is_trivially_relocatable_v<NoAddressDiscriminatedPolymorphicBase>);
+static_assert(inheritance_relocatability_matches_bases_v<AddressDiscriminatedPolymorphicBase,
 NoAddressDiscriminatedPolymorphicBase>);
+static_assert(inheritance_relocatability_matches_bases_v<NoAddressDiscriminatedPolymorphicBase,
 AddressDiscriminatedPolymorphicBase>);
+
+static_assert(!test_is_trivially_relocatable_v<UnionWrapper<AddressDiscriminatedPolymorphicBase>>);
+static_assert(test_is_trivially_relocatable_v<UnionWrapper<NoAddressDiscriminatedPolymorphicBase>>);
+static_assert(!test_is_trivially_relocatable_v<UnionWrapper<MultipleInheriter<NoAddressDiscriminatedPolymorphicBase,
 AddressDiscriminatedPolymorphicBase>>>);
+static_assert(!test_is_trivially_relocatable_v<UnionWrapper<MultipleInheriter<AddressDiscriminatedPolymorphicBase,
 NoAddressDiscriminatedPolymorphicBase>>>);

>From 15b1a8136f7308c0f205a756a68f147208a36278 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Sun, 15 Jun 2025 07:20:47 +0300
Subject: [PATCH 3/7] Address corentin comments

---
 clang/include/clang/AST/ASTContext.h | 10 ++------
 clang/lib/AST/ASTContext.cpp         | 38 +++++++++++++++-------------
 2 files changed, 22 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 68b8d67ab4828..72e4d803289b4 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -635,14 +635,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
   /// implicitly authenticated values like vtable pointers, as well as
   /// explicitly qualified fields.
   bool containsAddressDiscriminatedPointerAuth(QualType T);
-
-private:
   // A simple helper function to short circuit pointer auth checks.
+
   bool isPointerAuthenticationAvailable() const {
     return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics ||
            LangOpts.PointerAuthVTPtrAddressDiscrimination;
   }
 
+private:
   llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
       RelocatableClasses;
 
@@ -3686,12 +3686,6 @@ OPT_LIST(V)
   const CXXRecordDecl *
   baseForVTableAuthentication(const CXXRecordDecl *ThisClass);
 
-  /// If this class is polymorphic, returns true if any of this class's
-  /// vtable pointers have an address discriminated pointer authentication
-  /// schema.
-  /// This does not check fields of the class or base classes.
-  bool hasAddressDiscriminatedVTableAuthentication(const CXXRecordDecl *Class);
-
   bool useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
                                StringRef MangledName);
 
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6db95ac106703..76453b20f30a4 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1704,6 +1704,22 @@ void ASTContext::setRelocationInfoForCXXRecord(
   assert(RelocatableClasses.find(D) == RelocatableClasses.end());
   RelocatableClasses.insert({D, Info});
 }
+static bool
+hasAddressDiscriminatedVTableAuthentication(ASTContext &Context,
+                                            const CXXRecordDecl *Class) {
+  if (!Context.isPointerAuthenticationAvailable() || !Class->isPolymorphic())
+    return false;
+  const CXXRecordDecl *BaseType = Context.baseForVTableAuthentication(Class);
+  using AuthAttr = VTablePointerAuthenticationAttr;
+  const AuthAttr *ExplicitAuth = BaseType->getAttr<AuthAttr>();
+  if (!ExplicitAuth)
+    return Context.getLangOpts().PointerAuthVTPtrAddressDiscrimination;
+  AuthAttr::AddressDiscriminationMode AddressDiscrimination =
+      ExplicitAuth->getAddressDiscrimination();
+  if (AddressDiscrimination == AuthAttr::DefaultAddressDiscrimination)
+    return Context.getLangOpts().PointerAuthVTPtrAddressDiscrimination;
+  return AddressDiscrimination == AuthAttr::AddressDiscrimination;
+}
 
 bool ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
   if (!isPointerAuthenticationAvailable())
@@ -1721,12 +1737,14 @@ bool 
ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
     return Existing->second;
 
   auto SaveReturn = [this, RD](bool Result) {
-    RecordContainsAddressDiscriminatedPointerAuth.insert({RD, Result});
+    auto __unused[ResultIter, DidAdd] =
+        RecordContainsAddressDiscriminatedPointerAuth.try_emplace(RD, Result);
+    assert(DidAdd);
     return Result;
   };
   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
     if (CXXRD->isPolymorphic() &&
-        hasAddressDiscriminatedVTableAuthentication(CXXRD))
+        hasAddressDiscriminatedVTableAuthentication(*this, CXXRD))
       return SaveReturn(true);
     for (auto Base : CXXRD->bases()) {
       if (containsAddressDiscriminatedPointerAuth(Base.getType()))
@@ -15156,22 +15174,6 @@ ASTContext::baseForVTableAuthentication(const 
CXXRecordDecl *ThisClass) {
   return PrimaryBase;
 }
 
-bool ASTContext::hasAddressDiscriminatedVTableAuthentication(
-    const CXXRecordDecl *Class) {
-  if (!isPointerAuthenticationAvailable() || !Class->isPolymorphic())
-    return false;
-  const CXXRecordDecl *BaseType = baseForVTableAuthentication(Class);
-  using AuthAttr = VTablePointerAuthenticationAttr;
-  const AuthAttr *ExplicitAuth = BaseType->getAttr<AuthAttr>();
-  if (!ExplicitAuth)
-    return LangOpts.PointerAuthVTPtrAddressDiscrimination;
-  AuthAttr::AddressDiscriminationMode AddressDiscrimination =
-      ExplicitAuth->getAddressDiscrimination();
-  if (AddressDiscrimination == AuthAttr::DefaultAddressDiscrimination)
-    return LangOpts.PointerAuthVTPtrAddressDiscrimination;
-  return AddressDiscrimination == AuthAttr::AddressDiscrimination;
-}
-
 bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
                                          StringRef MangledName) {
   auto *Method = cast<CXXMethodDecl>(VirtualMethodDecl.getDecl());

>From 3ba1e3911ba2b43f12255b5cd989cbf69bd55dec Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Sun, 15 Jun 2025 11:14:50 +0300
Subject: [PATCH 4/7] __unused doesn't work on the linux and windows bots

---
 clang/lib/AST/ASTContext.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 76453b20f30a4..6f40b4c2733a9 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1737,8 +1737,10 @@ bool 
ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
     return Existing->second;
 
   auto SaveReturn = [this, RD](bool Result) {
-    auto __unused[ResultIter, DidAdd] =
+    auto [ResultIter, DidAdd] =
         RecordContainsAddressDiscriminatedPointerAuth.try_emplace(RD, Result);
+    (void)ResultIter;
+    (void)DidAdd;
     assert(DidAdd);
     return Result;
   };

>From 6b5de16a8d45fc168d4f4a98907b9b5286b5aef8 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Sun, 15 Jun 2025 13:22:49 +0300
Subject: [PATCH 5/7] Address discriminated __ptrauth should not be relocatable

After consideration, while "supportable" by relocation, it
seems much more reasonable for people to understand that
explicitly qualified types can have different relocatability
semantics.

Implicitly address discriminated fields should be relocatable
as developers in general cannot control those behaviours, hence
the trivial_relocation language explicitly acknowledges that
this impacts unions.

Explicitly address discriminated fields do however drastically
change the developer aware model of a type, and the practical
requirements for efficiently handling __ptrauth qualified types
mean that you would want

   some_addr_discriminated_t[100];

to not be reported as trivially relocatable, while

   struct {
     ...
     some_addr_discriminated_t field;
     ...
   }

to be reported as such, and the actual decision would regress
to what proportion of the object being relocated is subject to
such a policy.

Having is_trivially_relocatable change behaviour according to
some hypothetical internal heuristic is clearly a terrible
idea, and so I think for now we should instead simply limit
the application of trivial relocation to address discriminated
data to those fields that outside of the control of developers.
---
 clang/include/clang/AST/ASTContext.h          | 35 ++++++++++++----
 clang/lib/AST/ASTContext.cpp                  | 40 +++++++++++--------
 clang/lib/Sema/SemaTypeTraits.cpp             |  3 ++
 clang/test/SemaCXX/ptrauth-triviality.cpp     |  8 ++--
 .../SemaCXX/trivially-relocatable-ptrauth.cpp | 15 +++++--
 5 files changed, 70 insertions(+), 31 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 72e4d803289b4..35a97c1372d1c 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -629,17 +629,26 @@ class ASTContext : public RefCountedBase<ASTContext> {
   void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
                                      CXXRecordDeclRelocationInfo);
 
-  /// Examines a given type, and returns whether the T itself
+  /// Examines a given type, and returns whether the type itself
   /// is address discriminated, or any transitively embedded types
   /// contain data that is address discriminated. This includes
   /// implicitly authenticated values like vtable pointers, as well as
   /// explicitly qualified fields.
-  bool containsAddressDiscriminatedPointerAuth(QualType T);
-  // A simple helper function to short circuit pointer auth checks.
+  bool containsAddressDiscriminatedPointerAuth(QualType T) {
+    if (!isPointerAuthenticationAvailable())
+      return false;
+    return findPointerAuthContent(T) != PointerAuthContent::None;
+  }
 
-  bool isPointerAuthenticationAvailable() const {
-    return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics ||
-           LangOpts.PointerAuthVTPtrAddressDiscrimination;
+  /// Examines a given type, and returns whether the type itself
+  /// or any data it transitively contains has a pointer authentication
+  /// schema that is not safely relocatable. e.g. any data or fields
+  /// with address discrimination other than any otherwise similar
+  /// vtable pointers.
+  bool containsNonRelocatablePointerAuth(QualType T) {
+    if (!isPointerAuthenticationAvailable())
+      return false;
+    return findPointerAuthContent(T) == 
PointerAuthContent::AddressDiscriminatedData;
   }
 
 private:
@@ -647,7 +656,19 @@ class ASTContext : public RefCountedBase<ASTContext> {
       RelocatableClasses;
 
   // FIXME: store in RecordDeclBitfields in future?
-  llvm::DenseMap<const RecordDecl *, bool>
+  enum class PointerAuthContent : uint8_t {
+    None,
+    AddressDiscriminatedVTable,
+    AddressDiscriminatedData
+  };
+
+  // A simple helper function to short circuit pointer auth checks.
+  bool isPointerAuthenticationAvailable() const {
+    return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics ||
+           LangOpts.PointerAuthVTPtrAddressDiscrimination;
+  }
+  PointerAuthContent findPointerAuthContent(QualType T);
+  llvm::DenseMap<const RecordDecl *, PointerAuthContent>
       RecordContainsAddressDiscriminatedPointerAuth;
 
   ImportDecl *FirstLocalImport = nullptr;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6f40b4c2733a9..6fee1ca10fe3e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1704,10 +1704,11 @@ void ASTContext::setRelocationInfoForCXXRecord(
   assert(RelocatableClasses.find(D) == RelocatableClasses.end());
   RelocatableClasses.insert({D, Info});
 }
+
 static bool
-hasAddressDiscriminatedVTableAuthentication(ASTContext &Context,
+primaryBaseHaseAddressDiscriminatedVTableAuthentication(ASTContext &Context,
                                             const CXXRecordDecl *Class) {
-  if (!Context.isPointerAuthenticationAvailable() || !Class->isPolymorphic())
+  if (!Class->isPolymorphic())
     return false;
   const CXXRecordDecl *BaseType = Context.baseForVTableAuthentication(Class);
   using AuthAttr = VTablePointerAuthenticationAttr;
@@ -1721,22 +1722,23 @@ hasAddressDiscriminatedVTableAuthentication(ASTContext 
&Context,
   return AddressDiscrimination == AuthAttr::AddressDiscrimination;
 }
 
-bool ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
-  if (!isPointerAuthenticationAvailable())
-    return false;
+ASTContext::PointerAuthContent ASTContext::findPointerAuthContent(QualType T) {
+  assert(isPointerAuthenticationAvailable());
 
   T = T.getCanonicalType();
   if (T.hasAddressDiscriminatedPointerAuth())
-    return true;
+    return PointerAuthContent::AddressDiscriminatedData;
   const RecordDecl *RD = T->getAsRecordDecl();
   if (!RD)
-    return false;
+    return PointerAuthContent::None;
 
   if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD);
       Existing != RecordContainsAddressDiscriminatedPointerAuth.end())
     return Existing->second;
 
-  auto SaveReturn = [this, RD](bool Result) {
+  PointerAuthContent Result = PointerAuthContent::None;
+
+  auto SaveResultAndReturn = [&]() -> PointerAuthContent {
     auto [ResultIter, DidAdd] =
         RecordContainsAddressDiscriminatedPointerAuth.try_emplace(RD, Result);
     (void)ResultIter;
@@ -1744,20 +1746,26 @@ bool 
ASTContext::containsAddressDiscriminatedPointerAuth(QualType T) {
     assert(DidAdd);
     return Result;
   };
+  auto ShouldContinueAfterUpdate = [&](PointerAuthContent NewResult) {
+    static_assert(PointerAuthContent::None < 
PointerAuthContent::AddressDiscriminatedVTable);
+    static_assert(PointerAuthContent::AddressDiscriminatedVTable < 
PointerAuthContent::AddressDiscriminatedData);
+    if (NewResult > Result)
+      Result = NewResult;
+    return Result != PointerAuthContent::AddressDiscriminatedData;
+  };
   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
-    if (CXXRD->isPolymorphic() &&
-        hasAddressDiscriminatedVTableAuthentication(*this, CXXRD))
-      return SaveReturn(true);
+    if (primaryBaseHaseAddressDiscriminatedVTableAuthentication(*this, CXXRD) 
&& !ShouldContinueAfterUpdate(PointerAuthContent::AddressDiscriminatedVTable))
+      return SaveResultAndReturn();
     for (auto Base : CXXRD->bases()) {
-      if (containsAddressDiscriminatedPointerAuth(Base.getType()))
-        return SaveReturn(true);
+      if (!ShouldContinueAfterUpdate(findPointerAuthContent(Base.getType())))
+        return SaveResultAndReturn();
     }
   }
   for (auto *FieldDecl : RD->fields()) {
-    if (containsAddressDiscriminatedPointerAuth(FieldDecl->getType()))
-      return SaveReturn(true);
+    if 
(!ShouldContinueAfterUpdate(findPointerAuthContent(FieldDecl->getType())))
+      return SaveResultAndReturn();
   }
-  return SaveReturn(false);
+  return SaveResultAndReturn();
 }
 
 void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp 
b/clang/lib/Sema/SemaTypeTraits.cpp
index a0b989fc33b2a..4dbb2450857e0 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -331,6 +331,9 @@ bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
   if (BaseElementType->isIncompleteType())
     return false;
 
+  if (Context.containsNonRelocatablePointerAuth(Type))
+    return false;
+
   if (BaseElementType->isScalarType() || BaseElementType->isVectorType())
     return true;
 
diff --git a/clang/test/SemaCXX/ptrauth-triviality.cpp 
b/clang/test/SemaCXX/ptrauth-triviality.cpp
index 2c95e93239790..ba8a8273d5c05 100644
--- a/clang/test/SemaCXX/ptrauth-triviality.cpp
+++ b/clang/test/SemaCXX/ptrauth-triviality.cpp
@@ -26,7 +26,7 @@ static_assert(!__is_trivially_assignable(S1, const S1&));
 static_assert(__is_trivially_destructible(S1));
 static_assert(!__is_trivially_copyable(S1));
 static_assert(!__is_trivially_relocatable(S1)); // 
expected-warning{{deprecated}}
-static_assert(__builtin_is_cpp_trivially_relocatable(S1));
+static_assert(!__builtin_is_cpp_trivially_relocatable(S1));
 static_assert(!__is_trivially_equality_comparable(S1));
 
 static_assert(__is_trivially_constructible(Holder<S1>));
@@ -35,7 +35,7 @@ static_assert(!__is_trivially_assignable(Holder<S1>, const 
Holder<S1>&));
 static_assert(__is_trivially_destructible(Holder<S1>));
 static_assert(!__is_trivially_copyable(Holder<S1>));
 static_assert(!__is_trivially_relocatable(Holder<S1>)); // 
expected-warning{{deprecated}}
-static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S1>));
+static_assert(!__builtin_is_cpp_trivially_relocatable(Holder<S1>));
 static_assert(!__is_trivially_equality_comparable(Holder<S1>));
 
 struct S2 {
@@ -146,7 +146,7 @@ static_assert(!__is_trivially_assignable(S6, const S6&));
 static_assert(__is_trivially_destructible(S6));
 static_assert(!__is_trivially_copyable(S6));
 static_assert(!__is_trivially_relocatable(S6)); // 
expected-warning{{deprecated}}
-static_assert(__builtin_is_cpp_trivially_relocatable(S6));
+static_assert(!__builtin_is_cpp_trivially_relocatable(S6));
 static_assert(!__is_trivially_equality_comparable(S6));
 
 static_assert(__is_trivially_constructible(Holder<S6>));
@@ -155,7 +155,7 @@ static_assert(!__is_trivially_assignable(Holder<S6>, const 
Holder<S6>&));
 static_assert(__is_trivially_destructible(Holder<S6>));
 static_assert(!__is_trivially_copyable(Holder<S6>));
 static_assert(!__is_trivially_relocatable(Holder<S6>)); // 
expected-warning{{deprecated}}
-static_assert(__builtin_is_cpp_trivially_relocatable(Holder<S6>));
+static_assert(!__builtin_is_cpp_trivially_relocatable(Holder<S6>));
 static_assert(!__is_trivially_equality_comparable(Holder<S6>));
 
 struct S7 {
diff --git a/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp 
b/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp
index 29722fadd4d17..b38499a634fcf 100644
--- a/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp
+++ b/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp
@@ -16,20 +16,27 @@ struct AddressDiscPtrauth {
   void * __ptrauth(1, 1, 1234) p;
 };
 
-static_assert(__builtin_is_cpp_trivially_relocatable(AddressDiscPtrauth));
+static_assert(!__builtin_is_cpp_trivially_relocatable(AddressDiscPtrauth));
 
 struct MultipleBaseClasses : NonAddressDiscPtrauth, AddressDiscPtrauth {
 
 };
 
-static_assert(__builtin_is_cpp_trivially_relocatable(MultipleBaseClasses));
+static_assert(!__builtin_is_cpp_trivially_relocatable(MultipleBaseClasses));
 
-struct MultipleMembers {
+struct MultipleMembers1 {
    NonAddressDiscPtrauth field0;
    AddressDiscPtrauth field1;
 };
 
-static_assert(__builtin_is_cpp_trivially_relocatable(MultipleMembers));
+static_assert(!__builtin_is_cpp_trivially_relocatable(MultipleMembers1));
+
+struct MultipleMembers2 {
+   NonAddressDiscPtrauth field0;
+   NonAddressDiscPtrauth field1;
+};
+
+static_assert(__builtin_is_cpp_trivially_relocatable(MultipleMembers2));
 
 struct UnionOfPtrauth {
     union {

>From ea3af8adf5e8b5956b575133a976f10d06548051 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Sun, 15 Jun 2025 13:39:41 +0300
Subject: [PATCH 6/7] sigh, formatting

---
 clang/include/clang/AST/ASTContext.h |  3 ++-
 clang/lib/AST/ASTContext.cpp         | 18 +++++++++++-------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 35a97c1372d1c..0efa7dbec5b0e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -648,7 +648,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   bool containsNonRelocatablePointerAuth(QualType T) {
     if (!isPointerAuthenticationAvailable())
       return false;
-    return findPointerAuthContent(T) == 
PointerAuthContent::AddressDiscriminatedData;
+    return findPointerAuthContent(T) ==
+           PointerAuthContent::AddressDiscriminatedData;
   }
 
 private:
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6fee1ca10fe3e..b2516d7f2e6fc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1705,9 +1705,8 @@ void ASTContext::setRelocationInfoForCXXRecord(
   RelocatableClasses.insert({D, Info});
 }
 
-static bool
-primaryBaseHaseAddressDiscriminatedVTableAuthentication(ASTContext &Context,
-                                            const CXXRecordDecl *Class) {
+static bool primaryBaseHaseAddressDiscriminatedVTableAuthentication(
+    ASTContext &Context, const CXXRecordDecl *Class) {
   if (!Class->isPolymorphic())
     return false;
   const CXXRecordDecl *BaseType = Context.baseForVTableAuthentication(Class);
@@ -1747,14 +1746,18 @@ ASTContext::PointerAuthContent 
ASTContext::findPointerAuthContent(QualType T) {
     return Result;
   };
   auto ShouldContinueAfterUpdate = [&](PointerAuthContent NewResult) {
-    static_assert(PointerAuthContent::None < 
PointerAuthContent::AddressDiscriminatedVTable);
-    static_assert(PointerAuthContent::AddressDiscriminatedVTable < 
PointerAuthContent::AddressDiscriminatedData);
+    static_assert(PointerAuthContent::None <
+                  PointerAuthContent::AddressDiscriminatedVTable);
+    static_assert(PointerAuthContent::AddressDiscriminatedVTable <
+                  PointerAuthContent::AddressDiscriminatedData);
     if (NewResult > Result)
       Result = NewResult;
     return Result != PointerAuthContent::AddressDiscriminatedData;
   };
   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
-    if (primaryBaseHaseAddressDiscriminatedVTableAuthentication(*this, CXXRD) 
&& !ShouldContinueAfterUpdate(PointerAuthContent::AddressDiscriminatedVTable))
+    if (primaryBaseHaseAddressDiscriminatedVTableAuthentication(*this, CXXRD) 
&&
+        !ShouldContinueAfterUpdate(
+            PointerAuthContent::AddressDiscriminatedVTable))
       return SaveResultAndReturn();
     for (auto Base : CXXRD->bases()) {
       if (!ShouldContinueAfterUpdate(findPointerAuthContent(Base.getType())))
@@ -1762,7 +1765,8 @@ ASTContext::PointerAuthContent 
ASTContext::findPointerAuthContent(QualType T) {
     }
   }
   for (auto *FieldDecl : RD->fields()) {
-    if 
(!ShouldContinueAfterUpdate(findPointerAuthContent(FieldDecl->getType())))
+    if (!ShouldContinueAfterUpdate(
+            findPointerAuthContent(FieldDecl->getType())))
       return SaveResultAndReturn();
   }
   return SaveResultAndReturn();

>From 54f93cb5427958e6f8edaae06499b260273a4646 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oli...@apple.com>
Date: Mon, 16 Jun 2025 10:56:58 +0300
Subject: [PATCH 7/7] remove extraneous check

---
 clang/include/clang/AST/ASTContext.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 0efa7dbec5b0e..95312b9168d24 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -665,8 +665,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   // A simple helper function to short circuit pointer auth checks.
   bool isPointerAuthenticationAvailable() const {
-    return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics ||
-           LangOpts.PointerAuthVTPtrAddressDiscrimination;
+    return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics;
   }
   PointerAuthContent findPointerAuthContent(QualType T);
   llvm::DenseMap<const RecordDecl *, PointerAuthContent>

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to