This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] [C++ RFC] Support named type capture for generic lambdas and generic functions as proposed by N3878
- From: Andrew Sutton <andrew dot n dot sutton at gmail dot com>
- To: Adam Butcher <adam at jessamine dot co dot uk>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>, Botond Ballo <botond dot ballo at utoronto dot ca>, Andrew Sutton <asutton at cs dot tamu dot edu>, Volker Reichelt <reichelt at gcc dot gnu dot org>
- Date: Tue, 25 Mar 2014 08:49:40 -0400
- Subject: Re: [PATCH] [C++ RFC] Support named type capture for generic lambdas and generic functions as proposed by N3878
- Authentication-results: sourceware.org; auth=none
- References: <1395731034-14803-1-git-send-email-adam at jessamine dot co dot uk>
It's not clear that this feature will be part of concepts. It will not
be included in the initial working paper, so the proposal will need to
be re-evaluated.
Andrew
On Tue, Mar 25, 2014 at 3:03 AM, Adam Butcher <adam@jessamine.co.uk> wrote:
> * parser.c (cp_parser_simple_type_specifier): Lookahead for a braced
> identifier after a generic type ('auto') parameter and, if present, use
> that as the type identifier name. Otherwise generate one with
> make_generic_type_name. Pass the resulting identifier as the new second
> parameter ...
> (synthesize_implicit_template_parm): ... here. Synthesize the template
> type parm with the provided name rather than generating one.
>
> * g++.dg/cpp1y/generic-fn-typeid.C: New testcase.
> ---
> gcc/cp/parser.c | 55 +++++++++++++++++++++-----
> gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C | 42 ++++++++++++++++++++
> 2 files changed, 88 insertions(+), 9 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C
>
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index 49fb731..4d6f8fe 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -2128,8 +2128,10 @@ static tree cp_parser_late_parsing_omp_declare_simd
> static tree cp_parser_late_parsing_cilk_simd_fn_info
> (cp_parser *, tree);
>
> +static tree make_generic_type_name
> + ();
> static tree synthesize_implicit_template_parm
> - (cp_parser *);
> + (cp_parser *, tree);
> static tree finish_fully_implicit_template
> (cp_parser *, tree);
>
> @@ -14530,23 +14532,58 @@ cp_parser_simple_type_specifier (cp_parser* parser,
> maybe_warn_cpp0x (CPP0X_AUTO);
> if (parser->auto_is_implicit_function_template_parm_p)
> {
> - type = synthesize_implicit_template_parm (parser);
> + /* Synthesize an implicit template parameter named as specified by
> + the IDENTIFIER_NODE of a braced identifier (as proposed by section
> + 2.2 of N3878). If no braced identifier is present then a name is
> + generated a via make_generic_type_name. */
> +
> + if (cp_lexer_peek_nth_token
> + (parser->lexer, 2)->type == CPP_OPEN_BRACE)
> + {
> + /* The 'auto' has only been peeked and is expected to be consumed
> + later; parse the braced identifier leaving the closing brace as
> + the next token. */
> +
> + cp_lexer_consume_token (parser->lexer); /* RID_AUTO */
> + cp_lexer_consume_token (parser->lexer); /* CPP_OPEN_BRACE */
> +
> + tree synth_id = cp_parser_identifier (parser);
> + if (synth_id != error_mark_node)
> + type = synthesize_implicit_template_parm (parser, synth_id);
> +
> + if (cp_parser_require
> + (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE) == 0
> + || synth_id == error_mark_node)
> + {
> + error_at (input_location,
> + "expected braced identifier for generic type capture");
> + return error_mark_node;
> + }
> +
> + /* Roll-back one token to allow for consume below. */
> + cp_lexer_set_token_position (parser->lexer,
> + cp_lexer_previous_token_position
> + (parser->lexer));
> + }
> + else
> + type = synthesize_implicit_template_parm
> + (parser, make_generic_type_name ());
>
> if (current_class_type && LAMBDA_TYPE_P (current_class_type))
> {
> if (cxx_dialect < cxx1y)
> - pedwarn (location_of (type), 0,
> + pedwarn (token->location, 0,
> "use of %<auto%> in lambda parameter declaration "
> "only available with "
> "-std=c++1y or -std=gnu++1y");
> }
> else if (cxx_dialect < cxx1y)
> - pedwarn (location_of (type), 0,
> + pedwarn (token->location, 0,
> "use of %<auto%> in parameter declaration "
> "only available with "
> "-std=c++1y or -std=gnu++1y");
> else
> - pedwarn (location_of (type), OPT_Wpedantic,
> + pedwarn (token->location, OPT_Wpedantic,
> "ISO C++ forbids use of %<auto%> in parameter "
> "declaration");
> }
> @@ -31957,11 +31994,12 @@ tree_type_is_auto_or_concept (const_tree t)
> }
>
> /* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
> - (creating a new template parameter list if necessary). Returns the newly
> - created template type parm. */
> + (creating a new template parameter list if necessary). The template type
> + parameter is given the id SYNTH_ID. Returns the newly created template type
> + parm. */
>
> tree
> -synthesize_implicit_template_parm (cp_parser *parser)
> +synthesize_implicit_template_parm (cp_parser *parser, tree synth_id)
> {
> gcc_assert (current_binding_level->kind == sk_function_parms);
>
> @@ -32073,7 +32111,6 @@ synthesize_implicit_template_parm (cp_parser *parser)
> /* Synthesize a new template parameter and track the current template
> parameter chain with implicit_template_parms. */
>
> - tree synth_id = make_generic_type_name ();
> tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
> synth_id);
> tree new_parm
> diff --git a/gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C b/gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C
> new file mode 100644
> index 0000000..ab208a4
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C
> @@ -0,0 +1,42 @@
> +// Check braced type capture for generic parameter types (from N3878)
> +// { dg-do compile { target c++1y } }
> +// { dg-options "" }
> +
> +auto f(auto {MyType} a, MyType b)
> +{
> +}
> +auto f2(auto {A} a, auto {B} b)
> +{
> +}
> +auto g(auto {g} x) // { dg-error "declaration|shadows" }
> +{
> +}
> +auto h(auto {x} x) // { dg-error "declaration|shadows" }
> +{
> +}
> +auto i(auto {}) // { dg-error "braced identifier|auto" }
> +{ // { dg-error "expected" }
> +}
> +auto j(auto {int}) // { dg-error "braced identifier|auto" }
> +{ // { dg-error "expected" }
> +}
> +auto k(auto {;}) // { dg-error "braced identifier|auto" }
> +{ // { dg-error "expected" }
> +}
> +
> +int main()
> +{
> + auto l = [] (auto {X} x1, X x2) {};
> +
> + l("a", "b");
> + f("a", "b");
> + f2("a", "b");
> +
> + l(1, 2);
> + f(1, 2);
> + f2(1, 2);
> +
> + l(1, 2.d); // { dg-error "no match" }
> + f(1, 2.d); // { dg-error "no match" }
> + f2(1, 2.d);
> +}
> --
> 1.9.0
>