Author: Akash Agrawal Date: 2026-07-23T15:06:49Z New Revision: 97a5889383220967c7ed4eb8d23470d875f8cbcc
URL: https://github.com/llvm/llvm-project/commit/97a5889383220967c7ed4eb8d23470d875f8cbcc DIFF: https://github.com/llvm/llvm-project/commit/97a5889383220967c7ed4eb8d23470d875f8cbcc.diff LOG: [Clang][Sema] Don't delay the access check when computing implicit deletion (#210254) 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. Fixes https://github.com/llvm/llvm-project/issues/210692 Co-authored-by: Claude-Sonnet Added: Modified: clang/docs/ReleaseNotes.md clang/lib/Sema/SemaAccess.cpp clang/test/SemaCXX/cxx20-default-compare.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 08397eae28557..639f7b09ae002 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -364,6 +364,10 @@ features cannot lower the translation-unit ABI level; `[](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 diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 17415b4185eff..9205ab1f283b7 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,15 @@ bool Sema::isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, // Suppress diagnostics. Entity.setDiag(Diag); + // 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) + 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..c569e9d866970 100644 --- a/clang/test/SemaCXX/cxx20-default-compare.cpp +++ b/clang/test/SemaCXX/cxx20-default-compare.cpp @@ -65,3 +65,17 @@ struct MutCheck : MutOnly { // bool operator==(this MutCheck, MutCheck) = default; }; } + +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'}} + 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}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
