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