[clang] [Clang] Skip invalid fields when synthesizing defaulted comparisons (PR #221570)

Akash Manna via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 8 22:59:34 PDT 2026


https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/221570

>From 398a9aa7028c97e39e6317b0866052c39d1f2234 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Sun, 6 Sep 2026 18:58:51 +0530
Subject: [PATCH 1/4] [Clang] Skip invalid fields when synthesizing defaulted
 comparisons

A field whose type carries an address space is already rejected by
CheckFieldDecl and marked invalid, but DefaultedComparisonVisitor
still visited it when building a defaulted operator== or operator<=>.
BuildFieldReferenceExpr then asserted because a member type is never
supposed to carry an address space qualifier.

Skip invalid fields in visitSubobjects, matching what the other
defaulted-member visitors already do.

Fixes #194605
---
 clang/docs/ReleaseNotes.md                   |  4 ++++
 clang/lib/Sema/SemaDeclCXX.cpp               |  3 +++
 clang/test/SemaCXX/cxx20-default-compare.cpp | 11 +++++++++++
 3 files changed, 18 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 0fb6dcf59d4c9..59b5c14c59242 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -652,6 +652,10 @@ features cannot lower the translation-unit ABI level;
 - Fixed a crash when a coroutine keyword appeared inside a mem-initializer on a
   function that is not a constructor. (#GH194298)
 
+- Fixed an assertion when a defaulted comparison operator was synthesized for a
+  class with an invalid non-static data member, such as one qualified with an
+  address space. (#GH194605)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4457ec58902d0..28beb44af987b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8203,6 +8203,9 @@ class DefaultedComparisonVisitor {
       //   Unnamed bit-fields are not members ...
       if (Field->isUnnamedBitField())
         continue;
+      // Skip invalid fields; they have already been diagnosed.
+      if (Field->isInvalidDecl())
+        continue;
       // Recursively expand anonymous structs.
       if (Field->isAnonymousStructOrUnion()) {
         if (visitSubobjects(Results, Field->getType()->getAsCXXRecordDecl(),
diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 4e93298bd17a9..a8ddb3d36fa58 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -88,3 +88,14 @@ union A {
 A a;
 bool b = a == a;
 }
+
+namespace GH194605 {
+struct S {
+  int [[clang::address_space(1)]] i; // expected-error {{field may not be qualified with an address space}}
+  bool operator==(const S &) const = default;
+};
+
+static_assert(!__is_trivially_equality_comparable(S));
+
+bool f(const S &a, const S &b) { return a == b; }
+}

>From 828e118dfd0e80b51721c14c33b12d036950900d Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Mon, 7 Sep 2026 19:03:06 +0530
Subject: [PATCH 2/4] drop redundant comment

---
 clang/lib/Sema/SemaDeclCXX.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 28beb44af987b..ac98bdaf22f0c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -8203,7 +8203,6 @@ class DefaultedComparisonVisitor {
       //   Unnamed bit-fields are not members ...
       if (Field->isUnnamedBitField())
         continue;
-      // Skip invalid fields; they have already been diagnosed.
       if (Field->isInvalidDecl())
         continue;
       // Recursively expand anonymous structs.

>From 4d0624cc929f0765e2d4cfa9b87e3c7badb26115 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Mon, 7 Sep 2026 20:09:27 +0530
Subject: [PATCH 3/4] Drop the type trait from the test

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

diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp b/clang/test/SemaCXX/cxx20-default-compare.cpp
index a8ddb3d36fa58..71bef0eb8de6f 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -95,7 +95,5 @@ struct S {
   bool operator==(const S &) const = default;
 };
 
-static_assert(!__is_trivially_equality_comparable(S));
-
 bool f(const S &a, const S &b) { return a == b; }
 }

>From 5003516498cc65bb37e6800ae63502bbfd89202f Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Mon, 7 Sep 2026 20:53:33 +0530
Subject: [PATCH 4/4] Simplify the test.

---
 clang/test/SemaCXX/cxx20-default-compare.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp b/clang/test/SemaCXX/cxx20-default-compare.cpp
index 71bef0eb8de6f..b812aba747ac9 100644
--- a/clang/test/SemaCXX/cxx20-default-compare.cpp
+++ b/clang/test/SemaCXX/cxx20-default-compare.cpp
@@ -95,5 +95,5 @@ struct S {
   bool operator==(const S &) const = default;
 };
 
-bool f(const S &a, const S &b) { return a == b; }
+static_assert(S{} == S{});
 }



More information about the cfe-commits mailing list