This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] [PR c++/84979] improve auto handling in explicit tmpl args for concepts
On Tue, Apr 3, 2018 at 10:38 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Apr 3, 2018, Jason Merrill <jason@redhat.com> wrote:
>
>> On Tue, Apr 3, 2018 at 3:54 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
>>> On Apr 2, 2018, Jason Merrill <jason@redhat.com> wrote:
>>>
>>>> On Sat, Mar 31, 2018 at 4:23 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
>>>>> On Mar 30, 2018, Jason Merrill <jason@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