* 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