Ping. On Fri, Sep 18, 2020 at 04:05:16PM -0400, Marek Polacek via Gcc-patches wrote: > 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 > > >
Marek