* 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