Skip to content

Commit f1ac334

Browse files
MitalAshokcor3ntin
andauthored
[Clang][SemaCXX] Preserve qualifiers in derived-to-base cast in defaulted comparison operators (#102619)
Fixes #102588 Co-authored-by: cor3ntin <[email protected]>
1 parent f006246 commit f1ac334

File tree

3 files changed

+58
-4
lines changed

3 files changed

+58
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ Bug Fixes to C++ Support
355355
- Fix an issue with dependent source location expressions (#GH106428), (#GH81155), (#GH80210), (#GH85373)
356356
- Fixed a bug in the substitution of empty pack indexing types. (#GH105903)
357357
- Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048)
358+
- Fixed a bug where defaulted comparison operators would remove ``const`` from base classes. (#GH102588)
359+
358360

359361
Bug Fixes to AST Handling
360362
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8450,10 +8450,12 @@ class DefaultedComparisonSynthesizer
84508450
if (Obj.first.isInvalid() || Obj.second.isInvalid())
84518451
return {ExprError(), ExprError()};
84528452
CXXCastPath Path = {Base};
8453-
return {S.ImpCastExprToType(Obj.first.get(), Base->getType(),
8454-
CK_DerivedToBase, VK_LValue, &Path),
8455-
S.ImpCastExprToType(Obj.second.get(), Base->getType(),
8456-
CK_DerivedToBase, VK_LValue, &Path)};
8453+
const auto CastToBase = [&](Expr *E) {
8454+
QualType ToType = S.Context.getQualifiedType(
8455+
Base->getType(), E->getType().getQualifiers());
8456+
return S.ImpCastExprToType(E, ToType, CK_DerivedToBase, VK_LValue, &Path);
8457+
};
8458+
return {CastToBase(Obj.first.get()), CastToBase(Obj.second.get())};
84578459
}
84588460

84598461
ExprPair getField(FieldDecl *Field) {

clang/test/SemaCXX/cxx20-default-compare.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 %s -std=c++23 -verify -Wfloat-equal
22

3+
#include "Inputs/std-compare.h"
4+
35
struct Foo {
46
float val;
57
bool operator==(const Foo &) const;
@@ -15,3 +17,51 @@ bool operator==(const Foo &, const Foo &) = default; // expected-warning {{comp
1517

1618
// Declare the defaulted comparison function as a non-member function. Arguments are passed by value.
1719
bool operator==(Foo, Foo) = default; // expected-warning {{comparing floating point with == or != is unsafe}} expected-note {{in defaulted equality comparison operator for 'Foo' first required here}}
20+
21+
namespace GH102588 {
22+
struct A {
23+
int i = 0;
24+
constexpr operator int() const { return i; }
25+
constexpr operator int&() { return ++i; }
26+
};
27+
28+
struct B : A {
29+
bool operator==(const B &) const = default;
30+
};
31+
32+
constexpr bool f() {
33+
B x;
34+
return x == x;
35+
}
36+
37+
static_assert(f());
38+
39+
struct ConstOnly {
40+
std::strong_ordering operator<=>(const ConstOnly&) const;
41+
std::strong_ordering operator<=>(ConstOnly&) = delete;
42+
friend bool operator==(const ConstOnly&, const ConstOnly&);
43+
friend bool operator==(ConstOnly&, ConstOnly&) = delete;
44+
};
45+
46+
struct MutOnly {
47+
std::strong_ordering operator<=>(const MutOnly&) const = delete;;
48+
std::strong_ordering operator<=>(MutOnly&);
49+
friend bool operator==(const MutOnly&, const MutOnly&) = delete;;
50+
friend bool operator==(MutOnly&, MutOnly&);
51+
};
52+
53+
struct ConstCheck : ConstOnly {
54+
friend std::strong_ordering operator<=>(const ConstCheck&, const ConstCheck&) = default;
55+
std::strong_ordering operator<=>(ConstCheck const& __restrict) const __restrict = default;
56+
friend bool operator==(const ConstCheck&, const ConstCheck&) = default;
57+
bool operator==(this const ConstCheck&, const ConstCheck&) = default;
58+
};
59+
60+
// FIXME: Non-reference explicit object parameter are rejected
61+
struct MutCheck : MutOnly {
62+
friend bool operator==(MutCheck, MutCheck) = default;
63+
// std::strong_ordering operator<=>(this MutCheck, MutCheck) = default;
64+
friend std::strong_ordering operator<=>(MutCheck, MutCheck) = default;
65+
// bool operator==(this MutCheck, MutCheck) = default;
66+
};
67+
}

0 commit comments

Comments
 (0)