Author: Mital Ashok Date: 2024-09-05T09:41:39+02:00 New Revision: f1ac334b13c22222ed5c71bad04ed8345b2be135
URL: https://github.com/llvm/llvm-project/commit/f1ac334b13c22222ed5c71bad04ed8345b2be135 DIFF: https://github.com/llvm/llvm-project/commit/f1ac334b13c22222ed5c71bad04ed8345b2be135.diff LOG: [Clang][SemaCXX] Preserve qualifiers in derived-to-base cast in defaulted comparison operators (#102619) Fixes #102588 Co-authored-by: cor3ntin <corentinja...@gmail.com> Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/cxx20-default-compare.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1520f7a2916aae..44ffad94ef41fc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -355,6 +355,8 @@ Bug Fixes to C++ Support - Fix an issue with dependent source location expressions (#GH106428), (#GH81155), (#GH80210), (#GH85373) - Fixed a bug in the substitution of empty pack indexing types. (#GH105903) - Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048) +- Fixed a bug where defaulted comparison operators would remove ``const`` from base classes. (#GH102588) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3044f1218f5b23..f90f16c2923d03 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8450,10 +8450,12 @@ class DefaultedComparisonSynthesizer if (Obj.first.isInvalid() || Obj.second.isInvalid()) return {ExprError(), ExprError()}; CXXCastPath Path = {Base}; - return {S.ImpCastExprToType(Obj.first.get(), Base->getType(), - CK_DerivedToBase, VK_LValue, &Path), - S.ImpCastExprToType(Obj.second.get(), Base->getType(), - CK_DerivedToBase, VK_LValue, &Path)}; + const auto CastToBase = [&](Expr *E) { + QualType ToType = S.Context.getQualifiedType( + Base->getType(), E->getType().getQualifiers()); + return S.ImpCastExprToType(E, ToType, CK_DerivedToBase, VK_LValue, &Path); + }; + return {CastToBase(Obj.first.get()), CastToBase(Obj.second.get())}; } ExprPair getField(FieldDecl *Field) { diff --git a/clang/test/SemaCXX/cxx20-default-compare.cpp b/clang/test/SemaCXX/cxx20-default-compare.cpp index 7074ee885ac4a2..3e4673c31e4890 100644 --- a/clang/test/SemaCXX/cxx20-default-compare.cpp +++ b/clang/test/SemaCXX/cxx20-default-compare.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -std=c++23 -verify -Wfloat-equal +#include "Inputs/std-compare.h" + struct Foo { float val; bool operator==(const Foo &) const; @@ -15,3 +17,51 @@ bool operator==(const Foo &, const Foo &) = default; // expected-warning {{comp // Declare the defaulted comparison function as a non-member function. Arguments are passed by value. 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}} + +namespace GH102588 { +struct A { + int i = 0; + constexpr operator int() const { return i; } + constexpr operator int&() { return ++i; } +}; + +struct B : A { + bool operator==(const B &) const = default; +}; + +constexpr bool f() { + B x; + return x == x; +} + +static_assert(f()); + +struct ConstOnly { + std::strong_ordering operator<=>(const ConstOnly&) const; + std::strong_ordering operator<=>(ConstOnly&) = delete; + friend bool operator==(const ConstOnly&, const ConstOnly&); + friend bool operator==(ConstOnly&, ConstOnly&) = delete; +}; + +struct MutOnly { + std::strong_ordering operator<=>(const MutOnly&) const = delete;; + std::strong_ordering operator<=>(MutOnly&); + friend bool operator==(const MutOnly&, const MutOnly&) = delete;; + friend bool operator==(MutOnly&, MutOnly&); +}; + +struct ConstCheck : ConstOnly { + friend std::strong_ordering operator<=>(const ConstCheck&, const ConstCheck&) = default; + std::strong_ordering operator<=>(ConstCheck const& __restrict) const __restrict = default; + friend bool operator==(const ConstCheck&, const ConstCheck&) = default; + bool operator==(this const ConstCheck&, const ConstCheck&) = default; +}; + +// FIXME: Non-reference explicit object parameter are rejected +struct MutCheck : MutOnly { + friend bool operator==(MutCheck, MutCheck) = default; + // std::strong_ordering operator<=>(this MutCheck, MutCheck) = default; + friend std::strong_ordering operator<=>(MutCheck, MutCheck) = default; + // bool operator==(this MutCheck, MutCheck) = default; +}; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits