From: Adam Butcher
Date: Tue, 4 Aug 2009 00:23:35 +0100
Subject: [PATCH] First pass polymorphic lambda support.  This version adds an optional template paramter list in angle-brackes after the lambda-introducer.

---
 gcc/cp/decl.c      |    8 ++++++++
 gcc/cp/parser.c    |   46 +++++++++++++++++++++++++++++++++++++++++++++-
 gcc/cp/semantics.c |    3 +++
 3 files changed, 56 insertions(+), 1 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 488a2d5..0d4155b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8151,6 +8151,14 @@ grokdeclarator (const cp_declarator *declarator,
 	{
 	  error ("parameter declared %<auto%>");
 	  type = error_mark_node;
+          /**
+           * If decl context is function definition or function
+           * template definition then synthesize a new typename
+           * parameter and replace 'auto' with that type.  
+           * This is for simplifying the syntax of polymorphic lambdas
+           * but could be applied generically I guess.(?)
+           * TODO: everything...
+           */
 	}
     }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cc7c5f0..3c76b10 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7183,6 +7183,7 @@ cp_parser_lambda_introducer (cp_parser* parser,
 /* Parse the (optional) middle of a lambda expression.
 
    lambda-parameter-declaration:
+       lambda-typename-spec [opt]
      ( lambda-parameter-declaration-list [opt] ) exception-specification [opt]
        lambda-return-type-clause [opt]
 
@@ -7194,8 +7195,33 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
 {
   tree param_list = NULL_TREE;
   tree exception_spec = NULL_TREE;
+  tree template_param_list = NULL_TREE;
 
-  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+  if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+  {
+    VEC (deferred_access_check,gc) *checks;
+  
+    cp_parser_require (parser, CPP_LESS, "%<<%>");
+
+    push_deferring_access_checks (dk_deferred);
+
+    /* TODO: allow for this to be omitted and implicit with function parameter
+     * TODO: list identifiers without decl-spec.
+     * TODO: */
+    template_param_list = cp_parser_template_parameter_list (parser);
+    
+    /* TODO: actually use this at the pop site */
+    checks = get_deferred_access_checks ();
+
+    cp_parser_skip_to_end_of_template_parameter_list (parser);
+
+    /* We just processed one more parameter list.  */
+    ++parser->num_template_parameter_lists;
+
+    push_deferring_access_checks (dk_no_check);
+  }
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) || template_param_list != NULL_TREE)
   {
     cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
@@ -7305,6 +7331,21 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
     DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
     finish_method (fco);
 
+    if (template_param_list != NULL_TREE)
+    {
+      tree saved_current_function_decl = current_function_decl;
+      pop_deferring_access_checks ();
+      /* Clear current function decl to allow check_member_template
+       * to pass -- currently it rejects templates inside functions.
+       * -- Couldn't figure out a way to test for lambda inside
+       * check_member_template.  */
+      current_function_decl = NULL_TREE;
+      fco = finish_member_template_decl (fco);
+      current_function_decl = saved_current_function_decl;
+      --parser->num_template_parameter_lists;
+      pop_deferring_access_checks ();
+      finish_template_decl (template_param_list);
+    }
     finish_member_declaration (fco);
 
     LAMBDA_EXPR_FUNCTION (lambda_expr) = fco;
@@ -7344,6 +7385,9 @@ cp_parser_lambda_body (cp_parser* parser,
     tree fco = LAMBDA_EXPR_FUNCTION (lambda_expr);
     tree body;
 
+    if (DECL_FUNCTION_TEMPLATE_P (fco))
+      fco = DECL_TEMPLATE_RESULT (fco);
+
     /* Let the front end know that we are going to be defining this
        function. */
     start_preparsed_function (
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 48ad19c..50ac5e8 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5262,6 +5262,9 @@ deduce_lambda_return_type (tree lambda, tree expr)
   tree return_type;
   tree result;
 
+  if( TREE_CODE (fco) == TEMPLATE_DECL )
+    fco = DECL_TEMPLATE_RESULT (fco);
+
   return_type = finish_decltype_type (
       expr,
       /*id_expression_or_member_access_p=*/false);
-- 
1.5.6.GIT

