Ping. On Thu, Sep 10, 2020 at 06:15:24PM -0400, Marek Polacek via Gcc-patches wrote: > To quickly recap, P0846 says that a name is also considered to refer to > a template if it is an unqualified-id followed by a < and name lookup > finds either one or more functions or finds nothing. > > In a template, when parsing a function call that has type-dependent > arguments, we can't perform ADL right away so we set KOENIG_LOOKUP_P in > the call to remember to do it when instantiating the call > (tsubst_copy_and_build/CALL_EXPR). When the called function is a > function template, we represent the call with a TEMPLATE_ID_EXPR; > usually the operand is an OVERLOAD. > > In the P0846 case though, the operand can be an IDENTIFIER_NODE, when > name lookup found nothing when parsing the template name. But we > weren't handling this correctly in tsubst_copy_and_build. First > we need to pass the FUNCTION_P argument from <case TEMPLATE_ID_EXPR> to > <case IDENTIFIER_NODE>, otherwise we give a bogus error. And then in > <case CALL_EXPR> we need to perform ADL. The rest of the changes is to > give better errors when ADL didn't find anything. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > I think I'd like to backport to 10 too. > > gcc/cp/ChangeLog: > > PR c++/97010 > * pt.c (tsubst_copy_and_build) <case TEMPLATE_ID_EXPR>: Call > tsubst_copy_and_build explicitly instead of using the RECUR macro. > Handle a TEMPLATE_ID_EXPR with an IDENTIFIER_NODE as its operand. > <case CALL_EXPR>: Perform ADL for a TEMPLATE_ID_EXPR with an > IDENTIFIER_NODE as its operand. > > gcc/testsuite/ChangeLog: > > PR c++/97010 > * g++.dg/cpp2a/fn-template21.C: New test. > * g++.dg/cpp2a/fn-template22.C: New test. > --- > gcc/cp/pt.c | 37 ++++++++++++++++------ > gcc/testsuite/g++.dg/cpp2a/fn-template21.C | 24 ++++++++++++++ > gcc/testsuite/g++.dg/cpp2a/fn-template22.C | 25 +++++++++++++++ > 3 files changed, 77 insertions(+), 9 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/fn-template21.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/fn-template22.C > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index 30c6735dede..566e24f9bf3 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -19241,7 +19241,8 @@ out: > } > > /* Like tsubst but deals with expressions and performs semantic > - analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)". */ > + analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)" or > + "F<TARGS> (ARGS)". */ > > tree > tsubst_copy_and_build (tree t, > @@ -19323,7 +19324,10 @@ tsubst_copy_and_build (tree t, > case TEMPLATE_ID_EXPR: > { > tree object; > - tree templ = RECUR (TREE_OPERAND (t, 0)); > + tree templ = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, > + complain, in_decl, > + function_p, > + integral_constant_expression_p); > tree targs = TREE_OPERAND (t, 1); > > if (targs) > @@ -19370,13 +19374,21 @@ tsubst_copy_and_build (tree t, > } > else > object = NULL_TREE; > - templ = lookup_template_function (templ, targs); > + > + tree tid = lookup_template_function (templ, targs); > > if (object) > - RETURN (build3 (COMPONENT_REF, TREE_TYPE (templ), > - object, templ, NULL_TREE)); > + RETURN (build3 (COMPONENT_REF, TREE_TYPE (tid), > + object, tid, NULL_TREE)); > + else if (identifier_p (templ)) > + { > + /* C++20 P0846: we can encounter an IDENTIFIER_NODE here when > + name lookup found nothing when parsing the template name. */ > + gcc_assert (cxx_dialect >= cxx20 || seen_error ()); > + RETURN (tid); > + } > else > - RETURN (baselink_for_fns (templ)); > + RETURN (baselink_for_fns (tid)); > } > > case INDIRECT_REF: > @@ -19967,14 +19979,17 @@ tsubst_copy_and_build (tree t, > > /* We do not perform argument-dependent lookup if normal > lookup finds a non-function, in accordance with the > - expected resolution of DR 218. */ > + resolution of DR 218. */ > if (koenig_p > && ((is_overloaded_fn (function) > /* If lookup found a member function, the Koenig lookup is > not appropriate, even if an unqualified-name was used > to denote the function. */ > && !DECL_FUNCTION_MEMBER_P (get_first_fn (function))) > - || identifier_p (function)) > + || identifier_p (function) > + /* C++20 P0846: Lookup found nothing. */ > + || (TREE_CODE (function) == TEMPLATE_ID_EXPR > + && identifier_p (TREE_OPERAND (function, 0)))) > /* Only do this when substitution turns a dependent call > into a non-dependent call. */ > && type_dependent_expression_p_push (t) > @@ -19982,9 +19997,13 @@ tsubst_copy_and_build (tree t, > function = perform_koenig_lookup (function, call_args, tf_none); > > if (function != NULL_TREE > - && identifier_p (function) > + && (identifier_p (function) > + || (TREE_CODE (function) == TEMPLATE_ID_EXPR > + && identifier_p (TREE_OPERAND (function, 0)))) > && !any_type_dependent_arguments_p (call_args)) > { > + if (TREE_CODE (function) == TEMPLATE_ID_EXPR) > + function = TREE_OPERAND (function, 0); > if (koenig_p && (complain & tf_warning_or_error)) > { > /* For backwards compatibility and good diagnostics, try > diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template21.C > b/gcc/testsuite/g++.dg/cpp2a/fn-template21.C > new file mode 100644 > index 00000000000..7b3f26bbfa0 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/fn-template21.C > @@ -0,0 +1,24 @@ > +// PR c++/97010 > +// { dg-do compile { target c++20 } } > + > +namespace M { > + struct S { int x; }; > + S foo (); > + > + template<typename> > + void get (S); > +} > + > +template<typename T> > +void bar (const T& t) > +{ > + get<int>(t); > +} > + > +int > +main () > +{ > + auto a = M::foo (); > + get<int>(a); > + bar (a); > +} > diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template22.C > b/gcc/testsuite/g++.dg/cpp2a/fn-template22.C > new file mode 100644 > index 00000000000..62cc81db0c7 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/fn-template22.C > @@ -0,0 +1,25 @@ > +// PR c++/97010 > +// { dg-do compile { target c++20 } } > + > +namespace M { > + struct S { int x; }; > + S foo (); > + > +// Test not-found-by-ADL scenario. > +// template<typename> > +// void get (S); > +} > + > +template<typename T> > +void bar (const T& t) > +{ > + get<int>(t); // { dg-error ".get. was not declared in this scope" } > +} > + > +int > +main () > +{ > + auto a = M::foo (); > + get<int>(a); // { dg-error ".get. was not declared in this scope" } > + bar (a); > +} > > base-commit: af47a2035a4882e6d4506e3d00b5a42414e3ee2b > -- > 2.26.2 >
Re: [PATCH] c++: Fix P0846 (ADL and function templates) in template [PR97010]
Marek Polacek via Gcc-patches Fri, 18 Sep 2020 13:05:58 -0700
- [PATCH] c++: Fix P0846 (ADL and function tem... Marek Polacek via Gcc-patches
- Re: [PATCH] c++: Fix P0846 (ADL and fun... Marek Polacek via Gcc-patches
- Re: [PATCH] c++: Fix P0846 (ADL and... Marek Polacek via Gcc-patches
- Re: [PATCH] c++: Fix P0846 (ADL and fun... Jason Merrill via Gcc-patches