On Tue, Apr 3, 2018 at 10:38 PM, Alexandre Oliva <aol...@redhat.com> wrote: > On Apr 3, 2018, Jason Merrill <ja...@redhat.com> wrote: > >> On Tue, Apr 3, 2018 at 3:54 AM, Alexandre Oliva <aol...@redhat.com> wrote: >>> On Apr 2, 2018, Jason Merrill <ja...@redhat.com> wrote: >>> >>>> On Sat, Mar 31, 2018 at 4:23 AM, Alexandre Oliva <aol...@redhat.com> wrote: >>>>> On Mar 30, 2018, Jason Merrill <ja...@redhat.com> wrote: >>>>> template <typename T> >>>>> void foo(T t) { >>>>> typename T::template C<auto> u = t; >>>>> T::template C<auto> (t); >>>>> T::template C<auto>::f (t, u); >>>>> } >>> >>>> We should be able to distinguish those cases based on tag_type. > >>> [...] >>> And then, while we're parsing "template C<auto>", we haven't yet reached >>> the '::' after the closing angle bracket that would tell us to regard >>> the id necessarily as a typename, so I don't see how we'd get a >>> scope_type in tag_type for the third case. > >> Ah, good point. Then perhaps put the new function in pt.c and also >> call it from tsubst_copy_and_build? > > I couldn't figure out how to trigger checks in tsubst_copy_and_build; > the testcases I threw at it all went through tsubst_qualified_id. I > think we can only get an identifier_p in a TEMPLATE_ID_EXPR when it's a > qualified id naming a member of another template; unqualified names that > could possibly take explicit template arguments would have to have > visible declarations, and then we'd get (an overload of) the > declarations in the TEMPLATE_ID_EXPR. I see evidence in pt.c that some > cases of Koenig lookup may involve identifier_p template substitution, > and I see evidence in the standard that the unqualified template-id > could have explicit template args, but... we won't regard <whatever> as > a template arg list if it's not preceded by an id that names a template, > be it a template-dependent qualified id preceded by the 'template' > keyword, be a template found by name lookup. If we find an unrelated > template function (as in the snippet below), we'll stick to it. So it > seems to me that the patch below is all we need. Am I missing anything? > > struct foo { template <typename T> friend void bar(T& t); }; > template <int> void bar(); > template <typename T> void f(T& x) { bar<auto> (x); } > void g(foo& x) { f (x); } > > > Regstrapping on i686- and x86_64-linux-gnu. Ok to install if it passes? > > > [PR c++/84979] reject auto in explicit tmpl args for tmpl-fn > > With concepts, we accept auto in explicit template arguments, but we > should only accept them for template classes. Passing them to > template functions or variables is not allowed. So, reject it, at > parse time if possible, at specialization time otherwise. > > > for gcc/cp/ChangeLog > > PR c++/84979 > * pt.c (check_auto_in_tmpl_args): New. > (tsubst_qualified_id): Use it to reject template args > referencing auto for non-type templates. > * parser.c (cp_parser_template_id): Likewise. > * cp-tree.h (check_auto_in_tmpl_args): Declare. > * typeck2.c (build_functional_cast): Report correct location > for invalid use of auto. > > for gcc/testsuite/ChangeLog > > PR c++/84979 > * g++.dg/concepts/pr84979.C: New. > * g++.dg/concepts/pr84979-2.C: New. > * g++.dg/concepts/pr84979-3.C: New. > --- > gcc/cp/cp-tree.h | 1 + > gcc/cp/parser.c | 10 +++++- > gcc/cp/pt.c | 52 > +++++++++++++++++++++++++++++ > gcc/cp/typeck2.c | 3 +- > gcc/testsuite/g++.dg/concepts/pr84979-2.C | 41 +++++++++++++++++++++++ > gcc/testsuite/g++.dg/concepts/pr84979-3.C | 45 +++++++++++++++++++++++++ > gcc/testsuite/g++.dg/concepts/pr84979.C | 9 +++++ > 7 files changed, 159 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979-2.C > create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979-3.C > create mode 100644 gcc/testsuite/g++.dg/concepts/pr84979.C > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index db79338035da..4777aa34cdbe 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -6496,6 +6496,7 @@ extern void maybe_show_extern_c_location (void); > > /* in pt.c */ > extern bool check_template_shadow (tree); > +extern bool check_auto_in_tmpl_args (tree, tree); > extern tree get_innermost_template_args (tree, int); > extern void maybe_begin_member_template_processing (tree); > extern void maybe_end_member_template_processing (void); > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index e946d0b72292..40a1e5549f02 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -15831,8 +15831,16 @@ cp_parser_template_id (cp_parser *parser, > location_t combined_loc > = make_location (token->location, token->location, finish_loc); > > + /* Check for concepts autos where they don't belong. We could > + identify types in some cases of idnetifier TEMPL, looking ahead > + for a CPP_SCOPE, but that would buy us nothing: we accept auto in > + types. We reject them in functions, but if what we have is an > + identifier, even with none_type we can't conclude it's NOT a > + type, we have to wait for template substitution. */ > + if (flag_concepts && check_auto_in_tmpl_args (templ, arguments)) > + template_id = error_mark_node; > /* Build a representation of the specialization. */ > - if (identifier_p (templ)) > + else if (identifier_p (templ)) > template_id = build_min_nt_loc (combined_loc, > TEMPLATE_ID_EXPR, > templ, arguments); > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index 284eaf3cab66..a5c489fc0768 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -14890,6 +14890,15 @@ tsubst_qualified_id (tree qualified_id, tree args, > complain); > else > expr = lookup_template_function (expr, template_args); > + > + /* We may be repeating a check already done during parsing, but > + if it was well-formed and passed then, it will pass again > + now, and if it didn't, we wouldn't have got here. The case > + we want to catch is when we couldn't tell then, and can now, > + namely when templ prior to substitution was an > + identifier. */ > + if (flag_concepts && check_auto_in_tmpl_args (expr, template_args)) > + return error_mark_node;
I think we want this added code to go at the beginning of the block, before we've wrapped the template in a TEMPLATE_ID_EXPR. OK with that change. Jason