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

Reply via email to