royjacobson created this revision. Herald added a project: All. royjacobson requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
As noticed in GH58962, we should only diagnose illegal overloads of member functions when the ref qualifiers don't match if the trailing constraints are the same. The fix is to move the existing constraints check earlier in Sema::IsOverload. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D138749 Files: clang/lib/Sema/SemaOverload.cpp clang/test/CXX/over/over.load/p2-0x.cpp
Index: clang/test/CXX/over/over.load/p2-0x.cpp =================================================================== --- clang/test/CXX/over/over.load/p2-0x.cpp +++ 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<typename T> +__add_rvalue_reference(T) declval(); + +template<unsigned R> +struct type +{ + void func() requires (R == 0); + void func() & requires (R == 1); + void func() && requires (R == 2); +}; + +template<typename T> +concept test = requires { declval<T>().func(); }; + +static_assert(test<type<0>&>); +static_assert(test<type<0>&&>); +static_assert(test<type<1>&>); +static_assert(not test<type<1>&&>); +static_assert(not test<type<2>&>); +static_assert(test<type<2>&&>); + +} +#endif Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -1316,6 +1316,24 @@ (!SameTemplateParameterList || !SameReturnType)) return true; } + + 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; + } + } + // 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 +1350,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 +1422,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; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits