https://github.com/ojhunt updated https://github.com/llvm/llvm-project/pull/164528
>From cf5921c9584278eb5fb213e33ecc38d6f2882a23 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <[email protected]> Date: Tue, 21 Oct 2025 18:10:04 -0700 Subject: [PATCH 1/2] [PAC][clang] Correct handling of ptrauth queries of incomplete types In normal circumstances we can never get to this point as earlier Sema checks will have already have prevented us from making these queries. However in some cases, for example a sufficiently large number of errors, clang can start allowing incomplete types in records. This means a number of the internal interfaces can end up perform type trait queries that require querying the pointer authentication properties of types that contain incomplete types. While the trait queries attempt to guard against incomplete types, those tests fail in this case as the incomplete types are actually nested in the seemingly complete parent type. --- clang/lib/AST/ASTContext.cpp | 25 +++++++++++- .../ptrauth-nested-incomplete-types.cpp | 39 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 32c8f6209a693..2cf2cdfc3d5e3 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1618,8 +1618,26 @@ void ASTContext::setRelocationInfoForCXXRecord( RelocatableClasses.insert({D, Info}); } +// In future we may want to distinguish the presence or absence of address +// discrimination, from the inability to determine the presence. For now we rely +// on all source facing interfaces (type trait queries, etc) diagnosing and +// reporting an error before reaching these paths. +static bool canDeterminePointerAuthContent(QualType Type) { + if (Type->isIncompleteType() || Type->isDependentType()) + return false; + const TagDecl *Decl = Type->getAsTagDecl(); + return !Decl || !Decl->getDefinition()->isInvalidDecl(); +} +static bool canDeterminePointerAuthContent(const ASTContext &Ctx, + const TagDecl *Decl) { + CanQualType DeclType = Ctx.getCanonicalTagType(Decl); + return canDeterminePointerAuthContent(DeclType); +} + static bool primaryBaseHaseAddressDiscriminatedVTableAuthentication( const ASTContext &Context, const CXXRecordDecl *Class) { + if (!canDeterminePointerAuthContent(Context, Class)) + return false; if (!Class->isPolymorphic()) return false; const CXXRecordDecl *BaseType = Context.baseForVTableAuthentication(Class); @@ -1639,7 +1657,7 @@ ASTContext::findPointerAuthContent(QualType T) const { assert(isPointerAuthenticationAvailable()); T = T.getCanonicalType(); - if (T->isDependentType()) + if (!canDeterminePointerAuthContent(T)) return PointerAuthContent::None; if (T.hasAddressDiscriminatedPointerAuth()) @@ -3230,6 +3248,7 @@ QualType ASTContext::removeAddrSpaceQualType(QualType T) const { uint16_t ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD) { + assert(canDeterminePointerAuthContent(*this, RD)); assert(RD->isPolymorphic() && "Attempted to get vtable pointer discriminator on a monomorphic type"); std::unique_ptr<MangleContext> MC(createMangleContext()); @@ -3517,7 +3536,9 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { assert(!T->isDependentType() && "cannot compute type discriminator of a dependent type"); - + assert(canDeterminePointerAuthContent(T) && + "cannot compute type discriminator of an incomplete or otherwise " + "invalid type"); SmallString<256> Str; llvm::raw_svector_ostream Out(Str); diff --git a/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp b/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp new file mode 100644 index 0000000000000..233d365288d8c --- /dev/null +++ b/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fptrauth-intrinsics -fsyntax-only -ferror-limit 1 -verify -std=c++26 %s +// RUN: %clang_cc1 -fptrauth-intrinsics -fsyntax-only -ferror-limit 1 -verify -std=c++03 %s +// RUN: %clang_cc1 -fsyntax-only -ferror-limit 1 -verify -std=c++03 %s + +/// Force two errors so we hit the error limit leading to skip of template instantiation +# "" // expected-error {{invalid preprocessing directive}} +# "" +// expected-error@* {{too many errors emitted}} + +template <typename> +struct a {}; +struct test_polymorphic { + virtual ~test_polymorphic(); + a<int> field; +}; +static_assert(__is_trivially_relocatable(test_polymorphic)); + +struct test_struct { + test_struct(int) {} + void test_instantiate() { + test_struct d(0); + } + void test_type_trait_query() { + __is_trivially_relocatable(test_struct); + } + a<int> e; +}; + +struct test_subclass : test_struct { + test_subclass() : test_struct(0) { + } + + void test_subclass_instantiation() { + test_subclass subclass{}; + } + void test_subclass_type_trait_query() { + __is_trivially_relocatable(test_subclass); + } +}; >From c2674221ac14278c2dac05c215c34583695fdf02 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <[email protected]> Date: Thu, 23 Oct 2025 01:05:16 -0700 Subject: [PATCH 2/2] Simplified the guards, and added an additional test path --- clang/lib/AST/ASTContext.cpp | 27 +++---------------- .../ptrauth-nested-incomplete-types.cpp | 7 +++++ 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2cf2cdfc3d5e3..687cd46773f43 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1618,26 +1618,8 @@ void ASTContext::setRelocationInfoForCXXRecord( RelocatableClasses.insert({D, Info}); } -// In future we may want to distinguish the presence or absence of address -// discrimination, from the inability to determine the presence. For now we rely -// on all source facing interfaces (type trait queries, etc) diagnosing and -// reporting an error before reaching these paths. -static bool canDeterminePointerAuthContent(QualType Type) { - if (Type->isIncompleteType() || Type->isDependentType()) - return false; - const TagDecl *Decl = Type->getAsTagDecl(); - return !Decl || !Decl->getDefinition()->isInvalidDecl(); -} -static bool canDeterminePointerAuthContent(const ASTContext &Ctx, - const TagDecl *Decl) { - CanQualType DeclType = Ctx.getCanonicalTagType(Decl); - return canDeterminePointerAuthContent(DeclType); -} - static bool primaryBaseHaseAddressDiscriminatedVTableAuthentication( const ASTContext &Context, const CXXRecordDecl *Class) { - if (!canDeterminePointerAuthContent(Context, Class)) - return false; if (!Class->isPolymorphic()) return false; const CXXRecordDecl *BaseType = Context.baseForVTableAuthentication(Class); @@ -1657,7 +1639,7 @@ ASTContext::findPointerAuthContent(QualType T) const { assert(isPointerAuthenticationAvailable()); T = T.getCanonicalType(); - if (!canDeterminePointerAuthContent(T)) + if (T->isDependentType()) return PointerAuthContent::None; if (T.hasAddressDiscriminatedPointerAuth()) @@ -1666,6 +1648,9 @@ ASTContext::findPointerAuthContent(QualType T) const { if (!RD) return PointerAuthContent::None; + if (RD->isInvalidDecl()) + return PointerAuthContent::None; + if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD); Existing != RecordContainsAddressDiscriminatedPointerAuth.end()) return Existing->second; @@ -3248,7 +3233,6 @@ QualType ASTContext::removeAddrSpaceQualType(QualType T) const { uint16_t ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD) { - assert(canDeterminePointerAuthContent(*this, RD)); assert(RD->isPolymorphic() && "Attempted to get vtable pointer discriminator on a monomorphic type"); std::unique_ptr<MangleContext> MC(createMangleContext()); @@ -3536,9 +3520,6 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { assert(!T->isDependentType() && "cannot compute type discriminator of a dependent type"); - assert(canDeterminePointerAuthContent(T) && - "cannot compute type discriminator of an incomplete or otherwise " - "invalid type"); SmallString<256> Str; llvm::raw_svector_ostream Out(Str); diff --git a/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp b/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp index 233d365288d8c..8fad2fb05bc6d 100644 --- a/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp +++ b/clang/test/SemaCXX/ptrauth-nested-incomplete-types.cpp @@ -26,6 +26,13 @@ struct test_struct { a<int> e; }; +struct test_struct2 { + test_struct member; + void test() { + test_struct2 t{.member = {0}}; + } +}; + struct test_subclass : test_struct { test_subclass() : test_struct(0) { } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
