From b88eb855b53184161ad1ea0eea1962100941cf0b Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Sun, 6 Jun 2021 03:20:25 +0200 Subject: [PATCH] [clang] use correct builtin type for defaulted comparison analyzer Fixes PR50591. When analyzing classes with members which have user-defined conversion operators to builtin types, the defaulted comparison analyzer was picking the member type instead of the type for the builtin operator which was selected as the best match. This could either result in wrong comparison category being selected, or a crash when runtime checks are enabled. Signed-off-by: Matheus Izvekov Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D103760 --- clang/lib/Sema/SemaDeclCXX.cpp | 7 ++++++- .../CXX/class/class.compare/class.spaceship/p2.cpp | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index fd2d93e..d39837d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7863,8 +7863,13 @@ private: return Result::deleted(); } } else { + QualType T = Best->BuiltinParamTypes[0]; + assert(T == Best->BuiltinParamTypes[1] && + "builtin comparison for different types?"); + assert(Best->BuiltinParamTypes[2].isNull() && + "invalid builtin comparison"); Optional Cat = - getComparisonCategoryForBuiltinCmp(Args[0]->getType()); + getComparisonCategoryForBuiltinCmp(T); assert(Cat && "no category for builtin comparison?"); R.Category = *Cat; } diff --git a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp index 06126a4..47b14cb 100644 --- a/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp +++ b/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp @@ -172,3 +172,23 @@ namespace PR48856 { int C::*x; // expected-note {{because there is no viable three-way comparison function for member 'x'}} }; } + +namespace PR50591 { + struct a1 { + operator int() const; + }; + struct b1 { + auto operator<=>(b1 const &) const = default; + a1 f; + }; + std::strong_ordering cmp_b1 = b1() <=> b1(); + + struct a2 { + operator float() const; + }; + struct b2 { + auto operator<=>(b2 const &) const = default; + a2 f; + }; + std::partial_ordering cmp_b2 = b2() <=> b2(); +} -- 2.7.4