usaxena95 updated this revision to Diff 470174. usaxena95 marked 2 inline comments as done. usaxena95 added a comment.
Addressed comments. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D136440/new/ https://reviews.llvm.org/D136440 Files: clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaOverload.cpp clang/test/SemaTemplate/concepts-using-decl.cpp
Index: clang/test/SemaTemplate/concepts-using-decl.cpp =================================================================== --- /dev/null +++ clang/test/SemaTemplate/concepts-using-decl.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s + +namespace heads_without_concepts { +struct base { + template <int N, int M> + int foo() { return 1; }; +}; + +struct bar : public base { + using base::foo; + template <int N> + int foo() { return 2; }; // expected-note {{candidate template ignored: substitution failure: too many template arguments for function template 'foo'}} +}; + +void func() { + bar f; + f.foo<10>(); + // FIXME(GH58571): bar::foo should not hide base::foo. + f.foo<10, 10>(); // expected-error {{no matching member function for call to 'foo'}} +} +} + +namespace static_methods { +template<class> concept False = false; + +struct Base { + static void foo(auto); +}; +struct Derived : public Base { + using Base::foo; + static void foo(False auto); +}; +void func() { + Derived::foo(42); +} +} + +namespace constrained_members { +template <unsigned n> struct Opaque {}; +template <unsigned n> void expect(Opaque<n> _) {} + +struct Empty{}; +constexpr int EmptySize = sizeof(Empty); + +template<typename T> concept IsEmpty = sizeof(T) == EmptySize; + +namespace base_members_not_hidden { +struct base { + template <typename T> + Opaque<0> foo() { return Opaque<0>(); }; +}; + +struct bar1 : public base { + using base::foo; + template <typename T> requires IsEmpty<T> + Opaque<1> foo() { return Opaque<1>(); }; +}; + +struct bar2 : public base { + using base::foo; + template <IsEmpty T> + Opaque<1> foo() { return Opaque<1>(); }; +}; + +struct bar3 : public base { + using base::foo; + template <typename T> + Opaque<1> foo() requires IsEmpty<T> { return Opaque<1>(); }; +}; + +void func() { + expect<0>(base{}.foo<Empty>()); + expect<0>(base{}.foo<int>()); + expect<1>(bar1{}.foo<Empty>()); + expect<0>(bar1{}.foo<int>()); + expect<1>(bar2{}.foo<Empty>()); + expect<0>(bar2{}.foo<int>()); + expect<1>(bar3{}.foo<Empty>()); + expect<0>(bar3{}.foo<int>()); +} +} +namespace base_members_hidden { +struct base1 { + template <typename T> requires IsEmpty<T> + Opaque<0> foo() { return Opaque<0>(); }; // expected-note {{candidate function [with T = constrained_members::Empty]}} +}; +struct bar1 : public base1 { + using base1::foo; + template <typename T> requires IsEmpty<T> + Opaque<1> foo() { return Opaque<1>(); }; +}; +struct base2 { + template <IsEmpty T> + Opaque<0> foo() { return Opaque<0>(); }; +}; +struct bar2 : public base2 { + using base2::foo; + template <IsEmpty T> + Opaque<1> foo() { return Opaque<1>(); }; +}; +struct baz : public base1 { + using base1::foo; + template <typename T> requires IsEmpty<T> && IsEmpty<T> + Opaque<1> foo() { return Opaque<1>(); }; // expected-note {{candidate function [with T = constrained_members::Empty]}} +}; +void func() { + expect<0>(base1{}.foo<Empty>()); + expect<1>(bar1{}.foo<Empty>()); + expect<0>(base2{}.foo<Empty>()); + expect<1>(bar2{}.foo<Empty>()); + expect<1>(baz{}.foo<Empty>()); // expected-error {{call to member function 'foo' is ambiguous}} +} +} +} Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -1280,26 +1280,42 @@ !FunctionParamTypesAreEqual(OldType, NewType))) return true; - // C++ [temp.over.link]p4: - // The signature of a function template consists of its function - // signature, its return type and its template parameter list. The names - // of the template parameters are significant only for establishing the - // relationship between the template parameters and the rest of the - // signature. - // - // We check the return type and template parameter lists for function - // templates first; the remaining checks follow. - // - // However, we don't consider either of these when deciding whether - // a member introduced by a shadow declaration is hidden. - if (!UseMemberUsingDeclRules && NewTemplate && - (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), - OldTemplate->getTemplateParameters(), - false, TPL_TemplateMatch) || - !Context.hasSameType(Old->getDeclaredReturnType(), - New->getDeclaredReturnType()))) - return true; - + if (NewTemplate) { + // C++ [temp.over.link]p4: + // The signature of a function template consists of its function + // signature, its return type and its template parameter list. The names + // of the template parameters are significant only for establishing the + // relationship between the template parameters and the rest of the + // signature. + // + // We check the return type and template parameter lists for function + // templates first; the remaining checks follow. + bool SameTemplateParameterList = TemplateParameterListsAreEqual( + NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch); + bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(), + New->getDeclaredReturnType()); + // FIXME(GH58571): Match template parameter list even for non contrained + // template heads. This currently ensures that the code prior to C++20 is + // not newly broken. + bool ContraintsInTemplateHead = + NewTemplate->getTemplateParameters()->hasAssociatedConstraints() || + OldTemplate->getTemplateParameters()->hasAssociatedConstraints(); + // C++ [namespace.udecl]p11: + // The set of declarations named by a using-declarator that inhabits a + // class C does not include member functions and member function + // templates of a base class that "correspond" to (and thus would + // conflict with) a declaration of a function or function template in + // C. + // Comparing return types is not required for the "correspond" check to + // decide whether a member introduced by a shadow declaration is hidden. + if (UseMemberUsingDeclRules && ContraintsInTemplateHead && + !SameTemplateParameterList) + return true; + if (!UseMemberUsingDeclRules && + (!SameTemplateParameterList || !SameReturnType)) + 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. // Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -3675,8 +3675,8 @@ const LookupResult &OldDecls, NamedDecl *&OldDecl, bool IsForUsingDecl); - bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl, - bool ConsiderCudaAttrs = true, + bool IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true, bool ConsiderRequiresClauses = true); // Calculates whether the expression Constraint depends on an enclosing
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits