* 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

Reply via email to