Author: Roy Jacobson Date: 2022-11-29T14:57:26+02:00 New Revision: 3c75feab3bbda563374f08e46a7c052c0c6f1c36
URL: https://github.com/llvm/llvm-project/commit/3c75feab3bbda563374f08e46a7c052c0c6f1c36 DIFF: https://github.com/llvm/llvm-project/commit/3c75feab3bbda563374f08e46a7c052c0c6f1c36.diff LOG: [clang] Compare constraints before diagnosing mismatched ref qualifiers (GH58962) 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. Closes https://github.com/llvm/llvm-project/issues/58962 Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D138749 Added: Modified: clang/lib/Sema/SemaOverload.cpp clang/test/CXX/over/over.load/p2-0x.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index a20d7dda79300..1eb68090a8fdb 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1316,6 +1316,17 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, (!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 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, 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 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, } } - if (ConsiderRequiresClauses) { - Expr *NewRC = New->getTrailingRequiresClause(), - *OldRC = Old->getTrailingRequiresClause(); - if ((NewRC != nullptr) != (OldRC != nullptr)) - // RC are most certainly diff erent - 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 index cf38741056aba..183f3cb322af7 100644 --- 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 @@ class Y { 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits