Index: clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp +++ clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp @@ -404,14 +404,17 @@ const auto *Fr = Result.Nodes.getNodeAs("Friend"); assert(F && "Matcher is expected to find only FunctionDecls"); - if (F->getLocation().isInvalid()) + // Three-way comparison operator<=> is syntactic sugar and generates implicit + // nodes for all other operators. + if (F->getLocation().isInvalid() || F->isImplicit()) return; - // Skip functions which return just 'auto'. + // Skip functions which return 'auto' and defaulted operators. const auto *AT = F->getDeclaredReturnType()->getAs(); - if (AT != nullptr && !AT->isConstrained() && - AT->getKeyword() == AutoTypeKeyword::Auto && - !hasAnyNestedLocalQualifiers(F->getDeclaredReturnType())) + if (AT != nullptr && + ((!AT->isConstrained() && AT->getKeyword() == AutoTypeKeyword::Auto && + !hasAnyNestedLocalQualifiers(F->getDeclaredReturnType())) || + F->isDefaulted())) return; // TODO: implement those Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-trailing-return-type-cxx20.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/modernize-use-trailing-return-type-cxx20.cpp +++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-trailing-return-type-cxx20.cpp @@ -52,3 +52,49 @@ T req2(T t) requires requires { t + t; }; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a trailing return type for this function [modernize-use-trailing-return-type] // CHECK-FIXES: {{^}}auto req2(T t) -> T requires requires { t + t; };{{$}} + +// +// Operator c++20 defaulted comparison operators +// +// Requires + +namespace std { +struct strong_ordering { + using value_type = signed char; + static strong_ordering const less; + static strong_ordering const equal; + static strong_ordering const equivalent; + static strong_ordering const greater; + + constexpr strong_ordering(value_type v) : val(v) {} + template + requires(T{0}) friend constexpr auto + operator==(strong_ordering v, T u) noexcept -> bool { + return v.val == u; + } + friend constexpr auto operator==(strong_ordering v, strong_ordering w) noexcept -> bool = default; + + value_type val{}; +}; +inline constexpr strong_ordering strong_ordering::less{-1}; +inline constexpr strong_ordering strong_ordering::equal{0}; +inline constexpr strong_ordering strong_ordering::equivalent{0}; +inline constexpr strong_ordering strong_ordering::greater{1}; + +} // namespace std + +struct TestDefaultOperatorA { + int a{}; + int b{}; + + friend auto operator<=>(const TestDefaultOperatorA &, const TestDefaultOperatorA &) noexcept = default; +}; + +struct TestDefaultOperatorB { + int a{}; + int b{}; + friend auto operator==(const TestDefaultOperatorB &, const TestDefaultOperatorB &) noexcept -> bool = default; + friend bool operator<(const TestDefaultOperatorB &, const TestDefaultOperatorB &) noexcept = default; + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use a trailing return type for this function [modernize-use-trailing-return-type] + // CHECK-FIXES: {{^}} friend auto operator<(const TestDefaultOperatorB &, const TestDefaultOperatorB &) noexcept -> bool = default;{{$}} +};