diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1316,6 +1316,17 @@ (!SameTemplateParameterList || !SameReturnType)) return true; } + + if (ConsiderRequiresClauses) { + Expr *NewRC = New->getTrailingRequiresClause(), + *OldRC = Old->getTrailingRequiresClause(); + if ((NewRC != nullptr) != (OldRC != nullptr)) + return true; + + if (NewRC && !AreConstraintExpressionsEqual(Old, OldRC, New, NewRC)) + return true; + } + // If the function is a class member, its signature includes the // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. // @@ -1332,14 +1343,15 @@ if (!UseMemberUsingDeclRules && (OldMethod->getRefQualifier() == RQ_None || NewMethod->getRefQualifier() == RQ_None)) { - // C++0x [over.load]p2: - // - Member function declarations with the same name and the same - // parameter-type-list as well as member function template - // declarations with the same name, the same parameter-type-list, and - // the same template parameter lists cannot be overloaded if any of - // them, but not all, have a ref-qualifier (8.3.5). + // C++20 [over.load]p2: + // - Member function declarations with the same name, the same + // parameter-type-list, and the same trailing requires-clause (if + // any), as well as member function template declarations with the + // same name, the same parameter-type-list, the same trailing + // requires-clause (if any), and the same template-head, cannot be + // overloaded if any of them, but not all, have a ref-qualifier. Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) - << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); + << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); Diag(OldMethod->getLocation(), diag::note_previous_declaration); } return true; @@ -1403,23 +1415,6 @@ } } - if (ConsiderRequiresClauses) { - Expr *NewRC = New->getTrailingRequiresClause(), - *OldRC = Old->getTrailingRequiresClause(); - if ((NewRC != nullptr) != (OldRC != nullptr)) - // RC are most certainly different - these are overloads. - return true; - - if (NewRC) { - llvm::FoldingSetNodeID NewID, OldID; - NewRC->Profile(NewID, Context, /*Canonical=*/true); - OldRC->Profile(OldID, Context, /*Canonical=*/true); - if (NewID != OldID) - // RCs are not equivalent - these are overloads. - return true; - } - } - // The signatures match; this is not an overload. return false; } diff --git a/clang/test/CXX/over/over.load/p2-0x.cpp b/clang/test/CXX/over/over.load/p2-0x.cpp --- a/clang/test/CXX/over/over.load/p2-0x.cpp +++ b/clang/test/CXX/over/over.load/p2-0x.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s // Member function declarations with the same name and the same // parameter-type-list as well as mem- ber function template @@ -22,3 +23,31 @@ void k(); // expected-note{{previous declaration}} void k() &&; // expected-error{{cannot overload a member function with ref-qualifier '&&' with a member function without a ref-qualifier}} }; + + +#if __cplusplus >= 202002L +namespace GH58962 { + +template +__add_rvalue_reference(T) declval(); + +template +struct type +{ + void func() requires (R == 0); + void func() & requires (R == 1); + void func() && requires (R == 2); +}; + +template +concept test = requires { declval().func(); }; + +static_assert(test&>); +static_assert(test&&>); +static_assert(test&>); +static_assert(not test&&>); +static_assert(not test&>); +static_assert(test&&>); + +} +#endif