Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -7755,6 +7755,10 @@ // followed by the non-static data members of C for (FieldDecl *Field : Record->fields()) { + // C++23 [class.bit]p2: + // Unnamed bit-fields are not members ... + if (Field->isUnnamedBitfield()) + continue; // Recursively expand anonymous structs. if (Field->isAnonymousStructOrUnion()) { if (visitSubobjects(Results, Field->getType()->getAsCXXRecordDecl(), Index: clang/test/CXX/class/class.compare/class.compare.default/p1.cpp =================================================================== --- clang/test/CXX/class/class.compare/class.compare.default/p1.cpp +++ clang/test/CXX/class/class.compare/class.compare.default/p1.cpp @@ -226,3 +226,26 @@ (void)(b == 0); } } // namespace p2085_2 + +namespace GH61417 { +struct A { + unsigned x : 1; + unsigned : 0; + unsigned y : 1; + + constexpr A() : x(0), y(0) {} + bool operator==(const A& rhs) const noexcept = default; +}; + +void f1() { + constexpr A a, b; + constexpr bool c = (a == b); // no diagnostic, we should not be comparing the + // unnamed bit-field which is indeterminate +} + +void f2() { + A a, b; + bool c = (a == b); // no diagnostic nor crash during codegen attempting to + // access info for unnamed bit-field +} +} Index: clang/test/CodeGenCXX/defaulted_equality_ignore_unnamed_bitfields.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/defaulted_equality_ignore_unnamed_bitfields.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - | FileCheck %s + +// Check that we don't attempt to compare the unnamed bitfields +struct A { + unsigned x : 1; + unsigned : 1; + + friend bool operator==(A, A); +}; + + +struct B { + unsigned x : 1; + unsigned : 31; + + friend bool operator==(B, B); +}; + +bool operator==(A, A) = default; +bool operator==(B, B) = default; + + +// If it compares the unnamed bitfields it will first compare the named bit-field +// and then branch based on the result of that comparison. +// We also won't see a lshr in order to clear the named bitfield. +// CHECK-NOT: br +// CHECK-NOT: lshr