https://github.com/akashagrwl updated 
https://github.com/llvm/llvm-project/pull/210254

>From c2f6ad63e6f8937494b6233891fa38996d8b5b47 Mon Sep 17 00:00:00 2001
From: Akash Agrawal <[email protected]>
Date: Thu, 16 Jul 2026 23:06:52 -0700
Subject: [PATCH 1/5] [Clang][Sema] Don't delay the access check when computing
 implicit deletion

Sema::isMemberAccessibleForDeletion treats AR_delayed as unreachable, but
CheckAccess returns AR_delayed whenever it runs inside an enclosing
delayed-diagnostics scope. That happens when deletion checking runs
synchronously while parsing a later declaration -- e.g. while explaining why a
defaulted operator<=> is deleted for an expression in that declaration's
initializer. The caller cannot consume a delayed diagnostic, so letting
CheckAccess delay always hits
llvm_unreachable("cannot delay =delete computation") and crashes.

Force an immediate answer by wrapping the CheckAccess call in
DelayedDiagnostics.pushUndelayed()/popUndelayed() via llvm::scope_exit,
mirroring the existing Sema::CheckEnableIf pattern in SemaOverload.cpp.
---
 clang/lib/Sema/SemaAccess.cpp                | 11 +++++++++++
 clang/test/SemaCXX/cxx20-default-compare.cpp | 18 ++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 17415b4185eff..f2e19488a6ee2 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -21,6 +21,7 @@
 #include "clang/Sema/DelayedDiagnostic.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
+#include "llvm/ADT/ScopeExit.h"
 
 using namespace clang;
 using namespace sema;
@@ -1612,6 +1613,16 @@ bool Sema::isMemberAccessibleForDeletion(CXXRecordDecl 
*NamingClass,
   // Suppress diagnostics.
   Entity.setDiag(Diag);
 
+  // Deletion checking can run while we are inside an enclosing
+  // delayed-diagnostics scope (e.g. when parsing a later declaration whose
+  // initializer requires explaining why a defaulted comparison operator is
+  // deleted). CheckAccess would then return AR_delayed, but the result must be
+  // known immediately here. Force an undelayed check, mirroring CheckEnableIf.
+  llvm::scope_exit UndelayDiags(
+      [&, CurrentState(DelayedDiagnostics.pushUndelayed())] {
+        DelayedDiagnostics.popUndelayed(CurrentState);
+      });
+
   switch (CheckAccess(*this, Loc, Entity)) {
   case AR_accessible: return true;
   case AR_inaccessible: return false;
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp 
b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 3e4673c31e489..cb2886608d6f6 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -65,3 +65,21 @@ struct MutCheck : MutOnly {
   // bool operator==(this MutCheck, MutCheck) = default;
 };
 }
+
+namespace delayed_deletion_check {
+// Explaining why a defaulted comparison operator is deleted can run while we
+// are parsing a later declaration, i.e. inside an enclosing 
delayed-diagnostics
+// scope. The access check for the deleted-ness computation must produce an
+// immediate answer rather than being delayed. Previously this crashed.
+struct HasPrivateSpaceship {
+private:
+  std::strong_ordering operator<=>(const HasPrivateSpaceship &) const; // 
expected-note 2 {{declared private here}}
+};
+
+struct S {
+  HasPrivateSpaceship member; // expected-note 2 {{because it would invoke a 
private 'operator<=>' member of 'delayed_deletion_check::HasPrivateSpaceship' 
to compare member 'member'}}
+  auto operator<=>(const S &) const = default; // expected-warning 
{{explicitly defaulted three-way comparison operator is implicitly deleted}} 
expected-note {{replace 'default' with 'delete'}} expected-note {{explicitly 
defaulted function was implicitly deleted here}}
+};
+
+bool b = (S{} < S{}); // expected-error {{object of type 'S' cannot be 
compared because its 'operator<=>' is implicitly deleted}}
+}

>From 62811efb260c7d6c7cd3b889f23af649b5905f57 Mon Sep 17 00:00:00 2001
From: Akash Agrawal <[email protected]>
Date: Wed, 22 Jul 2026 05:57:08 -0700
Subject: [PATCH 2/5] renaming delayed_deletion_check to
 immediate_deletion_check

---
 clang/test/SemaCXX/cxx20-default-compare.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp 
b/clang/test/SemaCXX/cxx20-default-compare.cpp
index cb2886608d6f6..04e95cede930e 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -66,7 +66,7 @@ struct MutCheck : MutOnly {
 };
 }
 
-namespace delayed_deletion_check {
+namespace immediate_deletion_check  {
 // Explaining why a defaulted comparison operator is deleted can run while we
 // are parsing a later declaration, i.e. inside an enclosing 
delayed-diagnostics
 // scope. The access check for the deleted-ness computation must produce an
@@ -77,7 +77,7 @@ struct HasPrivateSpaceship {
 };
 
 struct S {
-  HasPrivateSpaceship member; // expected-note 2 {{because it would invoke a 
private 'operator<=>' member of 'delayed_deletion_check::HasPrivateSpaceship' 
to compare member 'member'}}
+  HasPrivateSpaceship member; // expected-note 2 {{because it would invoke a 
private 'operator<=>' member of 'immediate_deletion_check 
::HasPrivateSpaceship' to compare member 'member'}}
   auto operator<=>(const S &) const = default; // expected-warning 
{{explicitly defaulted three-way comparison operator is implicitly deleted}} 
expected-note {{replace 'default' with 'delete'}} expected-note {{explicitly 
defaulted function was implicitly deleted here}}
 };
 

>From debd6d7a27705237d900725406d9c602e8496a63 Mon Sep 17 00:00:00 2001
From: Akash Agrawal <[email protected]>
Date: Wed, 22 Jul 2026 18:40:01 +0530
Subject: [PATCH 3/5] Apply suggestions from code review

Co-authored-by: Younan Zhang <[email protected]>
---
 clang/lib/Sema/SemaAccess.cpp                | 5 ++---
 clang/test/SemaCXX/cxx20-default-compare.cpp | 4 ----
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index f2e19488a6ee2..9205ab1f283b7 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1613,11 +1613,10 @@ bool Sema::isMemberAccessibleForDeletion(CXXRecordDecl 
*NamingClass,
   // Suppress diagnostics.
   Entity.setDiag(Diag);
 
-  // Deletion checking can run while we are inside an enclosing
+  // We don't want to delay access checking even we are inside an enclosing
   // delayed-diagnostics scope (e.g. when parsing a later declaration whose
   // initializer requires explaining why a defaulted comparison operator is
-  // deleted). CheckAccess would then return AR_delayed, but the result must be
-  // known immediately here. Force an undelayed check, mirroring CheckEnableIf.
+  // deleted)
   llvm::scope_exit UndelayDiags(
       [&, CurrentState(DelayedDiagnostics.pushUndelayed())] {
         DelayedDiagnostics.popUndelayed(CurrentState);
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp 
b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 04e95cede930e..87a6cfd09e186 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -67,10 +67,6 @@ struct MutCheck : MutOnly {
 }
 
 namespace immediate_deletion_check  {
-// Explaining why a defaulted comparison operator is deleted can run while we
-// are parsing a later declaration, i.e. inside an enclosing 
delayed-diagnostics
-// scope. The access check for the deleted-ness computation must produce an
-// immediate answer rather than being delayed. Previously this crashed.
 struct HasPrivateSpaceship {
 private:
   std::strong_ordering operator<=>(const HasPrivateSpaceship &) const; // 
expected-note 2 {{declared private here}}

>From ae3dac8127875e97571f6e09b13250757abd6cf3 Mon Sep 17 00:00:00 2001
From: Akash Agrawal <[email protected]>
Date: Wed, 22 Jul 2026 22:53:58 -0700
Subject: [PATCH 4/5] nit: typo fix removed extra space

---
 clang/test/SemaCXX/cxx20-default-compare.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp 
b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 87a6cfd09e186..c569e9d866970 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -66,14 +66,14 @@ struct MutCheck : MutOnly {
 };
 }
 
-namespace immediate_deletion_check  {
+namespace immediate_deletion_check {
 struct HasPrivateSpaceship {
 private:
   std::strong_ordering operator<=>(const HasPrivateSpaceship &) const; // 
expected-note 2 {{declared private here}}
 };
 
 struct S {
-  HasPrivateSpaceship member; // expected-note 2 {{because it would invoke a 
private 'operator<=>' member of 'immediate_deletion_check 
::HasPrivateSpaceship' to compare member 'member'}}
+  HasPrivateSpaceship member; // expected-note 2 {{because it would invoke a 
private 'operator<=>' member of 'immediate_deletion_check::HasPrivateSpaceship' 
to compare member 'member'}}
   auto operator<=>(const S &) const = default; // expected-warning 
{{explicitly defaulted three-way comparison operator is implicitly deleted}} 
expected-note {{replace 'default' with 'delete'}} expected-note {{explicitly 
defaulted function was implicitly deleted here}}
 };
 

>From ae697d5d63bce30f942350bd59105dabdb437c5d Mon Sep 17 00:00:00 2001
From: Akash Agrawal <[email protected]>
Date: Thu, 23 Jul 2026 07:15:11 -0700
Subject: [PATCH 5/5] adds release note

---
 clang/docs/ReleaseNotes.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 28fea9a99b609..d511bebd85a61 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -334,6 +334,10 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
   `[](Types... = args...) {}`). Clang now diagnoses the illegal default
   argument instead of asserting. (#GH210714)
 
+- Fixed a crash when computing the implicit deletion of a defaulted comparison
+  operator required an access check that ran while an enclosing declaration
+  was still being parsed. (#GH210692)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made

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

Reply via email to