public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [lambda] Segmentation fault in simple lambda program
@ 2009-08-06 13:52 John Freeman
  0 siblings, 0 replies; 24+ messages in thread
From: John Freeman @ 2009-08-06 13:52 UTC (permalink / raw)
  To: gcc

On Thu, Aug 6, 2009 at 6:27 AM, Adam Butcher <adam@jessamine.co.uk 
<mailto:adam@jessamine.co.uk>> wrote:

    I take you're point on [finish_struct_1] potentially being overkill
    but at least it means that user programs
    that copy can work.


Right.  I only added that comment so that other developers who come 
along and want to optimize it won't fall into the same trap I did.
 

    I've attached my two diffs made against the latest lambda head.
     First is explicit polymorphic lambda support via the
    additional template parameter syntax, second is the very hacky
    'for-discovery-purposes-only' prototype for typename
    inference.


I was hesitant to add the first patch alone, but now that you've got the 
second, I'm eager to take another look. 
 

    Currently for auto typename inference, cv-qualifiers (and other bits
    like attributes) are lost

    One thing I'm worried about is that I'm using make_tree_vec() with a
    length one greater than that of the previous
    vector in order to grow the template parameter list whilst parsing
    function arguments.


I'll be sure to look at these issues.
 

    There's a number of things I'm not sure about regarding location of
    the implementation (parser.c, semantics.c, decl.c
    etc).


The general guideline I followed was to put as much non-parsing logic 
into semantics.c as possible, and call into it from parser.c when 
needed.  I'm not sure what needs to go into decl.c either.


I will try to take this opportunity of renewed interest in the lambdas 
branch to look at dependent type support and name mangling.  When I say 
dependent type support, I mean using lambdas that capture or declare 
variables of dependent type from a surrounding template context.  Many 
people won't be able to effectively use lambdas until these features are 
added.

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04 22:45           ` John Freeman
@ 2009-08-06 12:40             ` Adam Butcher
  0 siblings, 0 replies; 24+ messages in thread
From: Adam Butcher @ 2009-08-06 12:40 UTC (permalink / raw)
  To: John Freeman
  Cc: Jason Merrill, Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

[-- Attachment #1: Type: text/plain, Size: 5632 bytes --]

Adam Butcher wrote:
>John Freeman wrote:
>>
>> I just inspected my code again.  The call to layout_class_type at the
>> beginning of finish_lambda_function_body at semantics.c:5241 was
>> intended to recalculate offsets to members in the case of default captures.
>>
>> Here is the complete order of the pertinent function calls (file
>> location has nothing to do with call order; I supply them to help the
>> reader to follow):
>>
>> finish_struct @ parser.c:6985
>>
>> cp_parser_lambda_body @ parser.c:6992
>> --> finish_lambda_function_body @ parser.c:7380
>> ----> layout_class_type @ semantics.c:5241
>>
>> finish_struct_1 @ ???? I don't see this added yet.  I've checked out
>> revision 150396.
>>
>I think Jason's waiting for the formality of copyright assignment to be finalized.   I attached my patches against the
>latest lambda branch head in the following mail if you want to try them out:
>  http://gcc.gnu.org/ml/gcc/2009-08/msg00058.html
>
I see you've committed the fix.  Great.  Much better to do the relayout in semantics.c where the previous layout stuff
was than in the parser.  I take you're point on it potentially being overkill but at least it means that user programs
that copy can work.

I guess this thread is done with now that the fix has been committed.  I should start another to discuss polymorphic
lambda experimentation and implicit template parameters.  BTW I have got the latter working now -- to a certain (read
limited and buggy) extent.

The 'implicit template parameter via auto' addition is literally a quick hack for me to investigate what functionally
needs to occur to achieve it -- the implementation is not pleasant by any means as yet.

I've attached my two diffs made against the latest lambda head.  First is explicit polymorphic lambda support via the
additional template parameter syntax, second is the very hacky 'for-discovery-purposes-only' prototype for typename
inference.  The examples below demonstrate the supported syntaxes.

  1.  [] <typename T, typename U> (T const& t, U u) { return t + u; }
  2.  [] (auto const& t, auto u) { return t + u; }
  3.  [] <typename T> (T const& t, auto u) { return t + u; }

Currently for auto typename inference, cv-qualifiers (and other bits like attributes) are lost but I'll come to that
when I rewrite it all in light of what I have found out.  Just thought I'd share this functional-approximation to a
solution.  As a result of the aforementioned bug, although 1. and 3. produce effectively the same code, 2. ends up
being equivalent to:

      [] <typename __AutoT1, typename __AutoT2> (__AutoT1& t, __AutoT2 u) { return t + u; }

rather than the expected:

      [] <typename __AutoT1, typename __AutoT2> (__AutoT1 const& t, __AutoT2 u) { return t + u; }

There's a number of things I'm not sure about regarding location of the implementation (parser.c, semantics.c, decl.c
etc).

One thing I'm worried about is that I'm using make_tree_vec() with a length one greater than that of the previous
vector in order to grow the template parameter list whilst parsing function arguments.  This seems inefficient and
ugly.  Not least as there seems to be no way to ditch the old tree-vec.  I can ggc_free it but that won't do any
housekeeping of the tree counts and sizes.  It looks like tree-vecs are only supposed to be alloc'd into the pool
(zone?) and never removed.  In this case, incrementally adding additional parameters, you get allocs like:

  [--tree-vec-1--]
  [--tree-vec-1--] [-+-tree-vec-2-+-]
  [--tree-vec-1--] [-+-tree-vec-2-+-] [-++-tree-vec-3-++-]

And all you want is the last one.  I appreciate that its probably done this way to avoiding full fragmentation
management but I'd expect this sort of thing may happen often (or maybe it shouldn't!).  Off the top of my head, one
solution would be to add tree_vec_resize() which would realloc the memory and update the counts/sizes iff the tree-vec
were the last in the list.  The fallback behaviour if it weren't the last would be to do the previous manual
make_tree_vec() behaviour.  Something like:

   [--tv1--]

tv1 = tree_vec_resize (tv1, TREE_VEC_LENGTH (tv1) + 1);

   [-+-tv1-+-]

tv1 = tree_vec_resize (tv1, TREE_VEC_LENGTH (tv1) + 1);

   [-++-tv1-++-]

tv2 = make_tree_vec (n)

   [-++-tv1-++-] [--tv2--]

tv1 = tree_vec_resize (tv1, TREE_VEC_LENGTH (tv1) + 1);

   [-++-tv1-++-] [--tv2--] [-+++-tv1-+++-]
   ^           ^
   | no longer |
   | referenced|

This seems to work optimally in the case of incremental addition to the last tree-vec -- you are left with the minimum
tree-vecs necessary to avoid full fragmentation handling, and it degrades to supports the effect of the manual method
of calling make_tree_vec (old_size + n).

Maybe a doubling size on realloc and starting at, say, 4 elements could make realloc'ing more efficient -- but it
would require different 'end' and length handling for tree-vec which may pervade the code-base (though the macro
front-ends may be able to hide this).

Maybe I've misunderstood tree-vecs and the garbage collection mechanics completely and its simply not an issue.  Or it
shouldn't be an issue because they shouldn't be used in that way.

The other option would be to keep hold of the original tree-list (which can be trivially chained) and only build the
tree-vec after parsing the function parameter decl (rather than build it after each parameter).  This may complicate
scoping/lookup of the template arguments though as current_template_parameters value is a currently a tree-vec.

In all there's a lot I'm not sure of!  Its all just experimentation!

Any feedback is always appreciated.

Regards,
Adam

[-- Attachment #2: 0001-First-pass-polymorphic-lambda-support.patch --]
[-- Type: application/octet-stream, Size: 3964 bytes --]

From 02488ab530d65d039672a5bc3cd42391b05f5ba0 Mon Sep 17 00:00:00 2001
From: Adam Butcher <ajb@ccrvm001a.(none)>
Date: Tue, 4 Aug 2009 13:42:25 +0100
Subject: [PATCH 1/2] First pass polymorphic lambda support.

This commit adds experimental support for an optional template-parameter-list in angle-brackets at the start of a lambda-parameter-declaration.
---
 gcc/cp/parser.c    |   48 +++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/cp/semantics.c |    3 +++
 2 files changed, 50 insertions(+), 1 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index af8fe01..b56ee7c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7163,9 +7163,13 @@ cp_parser_lambda_introducer (cp_parser* parser,
 /* Parse the (optional) middle of a lambda expression.
 
    lambda-parameter-declaration:
+       lambda-template-param-decl [opt]
      ( lambda-parameter-declaration-list [opt] ) exception-specification [opt]
        lambda-return-type-clause [opt]
 
+   lambda-template-param-decl:
+     < template-parameter-list >
+
    LAMBDA_EXPR is the current representation of the lambda expression.  */
 
 static void
@@ -7174,8 +7178,30 @@ 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);
+
+      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, "%<(%>");
 
@@ -7280,6 +7306,23 @@ 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 clean 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;
@@ -7318,6 +7361,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 (fco,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index ed9ec25..e088690 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5272,6 +5272,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.6.2.5


[-- Attachment #3: 0002-Very-hacky-implementation-of-template-typename-infer.patch --]
[-- Type: application/octet-stream, Size: 12527 bytes --]

From cc937d2ea8a6b2705f582b9bddd0f93eec9914ca Mon Sep 17 00:00:00 2001
From: Adam Butcher <ajb@ccrvm001a.(none)>
Date: Thu, 6 Aug 2009 10:40:13 +0100
Subject: [PATCH 2/2] Very hacky implementation of template typename inference from auto parameters in lambda call operator.

 * This is just a behavioural proof to find out how things work.
 * Need to figure out appropriate places for things.
 * Currently loses cv qualifiers so auto const& becomes __AutoTn& which is no good!
 * The code is supremely ugly and hacky - but it does work (ish).
 * Not sure how to free tree_vec's and tidy up the counts and sizes (looks like they're only intended to grow)
---
 gcc/cp/decl.c   |   69 +++++++++++++++++++-
 gcc/cp/parser.c |  187 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/cp/pt.c     |    8 +++
 3 files changed, 256 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 488a2d5..cf2b3af 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7531,6 +7531,54 @@ check_var_type (tree identifier, tree type)
   return type;
 }
 
+/* FIXME: either replace with something better or failing that at least put this interface in a header */
+struct auto_type_param_handler_t
+{
+   tree (*hook) (struct auto_type_param_handler_t* handler);
+};
+
+/* Substitute DEDUCED for 'auto' where it occurs within TYPE.  */
+
+tree subst_auto
+  (tree type, tree deduced);
+
+tree
+subst_auto (tree type, tree deduced)
+{
+  /* XXX: Maybe to loop rather than recurse here? */
+  enum tree_code code;
+  tree* last;
+
+  /* Cannot chain substitution if only auto was given */
+  gcc_assert (!is_auto (type));
+
+  last = &type;
+
+  while (last && !is_auto (*last))
+    {
+      code = TREE_CODE (*last);
+      if (code == POINTER_TYPE || code == REFERENCE_TYPE
+          || code == OFFSET_TYPE || code == FUNCTION_TYPE
+          || code == METHOD_TYPE || code == ARRAY_TYPE)
+        {
+          last = &TREE_TYPE (*last);
+	}
+      else if (TYPE_PTRMEMFUNC_P (type))
+        {
+          last = &TREE_TYPE (TREE_TYPE
+			(TYPE_PTRMEMFUNC_FN_TYPE (*last)));
+	}
+      else last = 0;
+    }
+
+  if (last)
+    {
+      *last = deduced;
+      return deduced;
+    }
+  return NULL_TREE;
+}
+
 /* Given declspecs and a declarator (abstract or otherwise), determine
    the name and type of the object declared and construct a DECL node
    for it.
@@ -8137,6 +8185,7 @@ grokdeclarator (const cp_declarator *declarator,
   /* Issue errors about use of storage classes for parameters.  */
   if (decl_context == PARM)
     {
+      tree auto_type;
       if (declspecs->specs[(int)ds_typedef])
 	{
 	  error ("typedef declaration invalid in parameter declaration");
@@ -8147,10 +8196,24 @@ grokdeclarator (const cp_declarator *declarator,
 	       || thread_p)
 	error ("storage class specifiers invalid in parameter declarations");
 
-      if (type_uses_auto (type))
+      auto_type = type_uses_auto (type);
+      if (auto_type)
 	{
-	  error ("parameter declared %<auto%>");
-	  type = error_mark_node;
+	  /* FIXME: something nicer than this global! */
+	  extern struct auto_type_param_handler_t* auto_type_param_handler;
+
+	  if (auto_type_param_handler == 0)
+	    {
+	      error ("parameter declared %<auto%>");
+	      type = error_mark_node;
+	    }
+	  else
+	    {
+	      /* Invoke custom handler */
+	      type = auto_type_param_handler->hook (auto_type_param_handler);
+	      /* FIXME: re-apply qualifiers to type if non-null,
+	         ideally just subst the auto with the returned type. */
+	    }
 	}
     }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b56ee7c..17b7ff6 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7160,6 +7160,172 @@ cp_parser_lambda_introducer (cp_parser* parser,
 
 }
 
+
+struct auto_type_param_handler_t;
+
+typedef tree (*auto_param_hook_t) (struct auto_type_param_handler_t*);
+
+/* FIXME: either replace with something better or failing that at least put this interface in a header */
+struct auto_type_param_handler_t
+{
+   auto_param_hook_t hook;
+};
+
+/* FIXME: something nicer than this global! */
+struct auto_type_param_handler_t* auto_type_param_handler = 0;
+
+
+struct lambda_parameter_auto_handler_t
+{
+   auto_param_hook_t hook;
+   tree* template_param_list;
+   VEC (deferred_access_check,gc)* checks;
+   cp_parser* parser;
+   int i;
+};
+
+tree lambda_parameter_make_auto_type_name
+  (struct lambda_parameter_auto_handler_t*);
+tree lambda_parameter_auto_handler
+  (struct lambda_parameter_auto_handler_t*);
+
+tree
+lambda_parameter_make_auto_type_name (struct lambda_parameter_auto_handler_t* handler)
+{
+  char buf[32];
+  sprintf (buf, "__AutoT%d", ++handler->i);
+  return get_identifier (buf);
+}
+
+/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
+   ORIG_LEVEL, DECL, and TYPE.  */
+
+static tree
+build_template_parm_index (int index,
+			   int level,
+			   int orig_level,
+			   tree decl,
+			   tree type)
+{
+  tree t = make_node (TEMPLATE_PARM_INDEX);
+  TEMPLATE_PARM_IDX (t) = index;
+  TEMPLATE_PARM_LEVEL (t) = level;
+  TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
+  TEMPLATE_PARM_DECL (t) = decl;
+  TREE_TYPE (t) = type;
+  TREE_CONSTANT (t) = TREE_CONSTANT (decl);
+  TREE_READONLY (t) = TREE_READONLY (decl);
+
+  return t;
+}
+
+tree
+lambda_parameter_auto_handler (struct lambda_parameter_auto_handler_t* handler)
+{
+  struct cp_binding_level* scope = current_binding_level;
+  location_t param_loc = cp_lexer_peek_token (handler->parser->lexer)->location; /* XXX: Any way to get current location? */
+
+  /* First auto parameter may need to start a template parameter list.  */
+  bool become_template = *handler->template_param_list == NULL_TREE;
+
+  tree synth_id = lambda_parameter_make_auto_type_name (handler);
+  tree synth_param = finish_template_type_parm (class_type_node, synth_id);
+  synth_param = build_tree_list (NULL_TREE, synth_param);
+
+  if (become_template)
+    {
+      /* do something rude and pretend that the template parameter
+	 scope surrounds the function definition.  XXX: can we
+	 guarantee that the immediate-outer scope /is/ the fco? */
+      current_binding_level = current_binding_level->level_chain;
+
+      /*if (ENABLE_SCOPE_CHECKING)
+	--binding_depth;*/
+
+      push_deferring_access_checks (dk_deferred);
+      begin_template_parm_list ();
+    }
+
+  synth_param = process_template_parm (0,
+				       param_loc,
+				       synth_param,
+				       /*non_type=*/false,
+				       /*param_pack=*/false);
+
+  /* re-index */
+  if (!become_template)
+    {
+      tree old = *handler->template_param_list;
+      size_t len = TREE_VEC_LENGTH (old);
+      size_t idx;
+      extern tree x_canonical_type_parameter (tree);
+
+      tree p = TREE_VALUE (TREE_VEC_ELT (old, --len));
+      if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
+	idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
+      else
+	idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
+
+      ++idx;
+
+      TEMPLATE_TYPE_PARM_INDEX (TREE_TYPE (synth_id))
+	= build_template_parm_index (idx, processing_template_decl,
+				     processing_template_decl,
+				     TYPE_NAME (TREE_TYPE (synth_id)),
+				     TREE_TYPE (synth_id));
+      TYPE_CANONICAL (TREE_TYPE (synth_id)) = x_canonical_type_parameter (TREE_TYPE (synth_id));
+    }
+
+  if (become_template)
+    {
+      *handler->template_param_list = end_template_parm_list (synth_param);
+      ++handler->parser->num_template_parameter_lists;
+      push_deferring_access_checks (dk_no_check);
+      push_binding_level (scope);
+    }
+  else /* add to existing template parameter list */
+    {
+      tree old = *handler->template_param_list;
+      tree new_vec;
+      size_t len;
+
+      gcc_assert (TREE_CODE (old) == TREE_VEC);
+
+      len = TREE_VEC_LENGTH (old);
+
+      /* XXX: Maybe do doubling and store real length in handler
+	 state, there doesn't seem to be any way to free these; or
+	 rather no way to free them that tidies up the
+	 tree_node_counts and sizes.  Ideally just want a
+	 realloc_tree_vec or some such thing that would do realloc and
+	 housekeeping.  Maybe there's some reason why this
+         would be a bad thing. (?)  In fact it would be better
+         to keep building a tree list and only flatten into
+         a vector after parsing the parameter list. */
+      new_vec = make_tree_vec (len+1);
+      {
+	size_t n;
+	for (n = 0; n != len; ++n)
+	  TREE_VEC_ELT (new_vec, n) = TREE_VEC_ELT (old, n);
+      }
+      TREE_VEC_ELT (new_vec, len) = synth_param;
+     /* memcpy (new_vec, old, sizeof (struct tree_vec) + sizeof (tree) * (len-1));
+      TREE_VEC_LENGTH (new_vec) = ++len;
+      */
+
+      /* XXX: free old one - how?  maybe ggc_free? but how to tidy up
+      ggc_free (old);
+       * the node counts and sizes? */
+
+      *handler->template_param_list = new_vec;
+
+      TREE_VALUE (current_template_parms) = new_vec;
+    }
+
+  /* replace auto with the synthesized template typename type */
+  return TREE_TYPE (synth_id);
+}
+
 /* Parse the (optional) middle of a lambda expression.
 
    lambda-parameter-declaration:
@@ -7179,11 +7345,11 @@ 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;
+  VEC (deferred_access_check,gc) *checks = 0;
+  struct lambda_parameter_auto_handler_t auto_handler;
 
   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);
@@ -7201,6 +7367,14 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
       push_deferring_access_checks (dk_no_check);
     }
 
+  /* Set up handler for auto being used in function parameter list.  */
+  auto_handler.hook = (auto_param_hook_t) lambda_parameter_auto_handler;
+  auto_handler.template_param_list = &template_param_list;
+  auto_handler.checks = 0;
+  auto_handler.parser = parser;
+  auto_handler.i = 0;
+  auto_type_param_handler = (struct auto_type_param_handler_t*) &auto_handler;
+
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) || template_param_list != NULL_TREE)
     {
       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
@@ -7213,10 +7387,13 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
           begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
 
           param_list = cp_parser_parameter_declaration_list (parser, &is_error);
+
           /* TODO: better way to handle this error?  */
           if (is_error)
             param_list = NULL_TREE;
 
+      auto_type_param_handler = 0;
+
           /* Remove the function parms from scope.  */
           {
             tree t;
@@ -7310,6 +7487,7 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
       {
         tree saved_current_function_decl = current_function_decl;
         pop_deferring_access_checks ();
+	/* TODO: do checks */
 
         /* Clear current function decl to allow check_member_template
            to pass.  Currently it rejects templates inside functions.
@@ -7319,16 +7497,15 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
         fco = finish_member_template_decl (fco);
         current_function_decl = saved_current_function_decl;
 
-        --parser->num_template_parameter_lists;
+	--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;
-
   }
-
 }
 
 /* Parse the body of a lambda expression, which is simply
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ed45324..2d8380c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3150,6 +3150,13 @@ canonical_type_parameter (tree type)
     }
 }
 
+/* FIXME: Cleanup this mess */
+tree x_canonical_type_parameter (tree type);
+tree x_canonical_type_parameter (tree type)
+{
+  return canonical_type_parameter (type);
+}
+
 /* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
    TEMPLATE_PARM_LEVEL has been decreased by LEVELS.  If such a
    TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a
@@ -17480,6 +17487,7 @@ is_auto (const_tree type)
 tree
 type_uses_auto (tree type)
 {
+  /* XXX: Maybe to loop rather than recurse here? */
   enum tree_code code;
   if (is_auto (type))
     return type;
-- 
1.6.2.5


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  5:39         ` John Freeman
  2009-08-04 15:33           ` Richard Henderson
@ 2009-08-04 22:45           ` John Freeman
  2009-08-06 12:40             ` Adam Butcher
  1 sibling, 1 reply; 24+ messages in thread
From: John Freeman @ 2009-08-04 22:45 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

John Freeman wrote:
>
>> +    /* relayout again -- to allow for implicit
>> +     * parameters to have been added to the capture if it was a
>> +     * 'default capture' -- note that this would not be necessary if
>> +     * the stack-pointer variant was implemented -- since the layout
>> +     * would be known.
>> +     * Relayingout here might have nasty effect if one were to query
>> +     * sizeof *this from within the body -- would that even be
>> +     * possible -- *this would refer to the lambda or the enclosing
>> +     * class instance -- if there was one.???
>> +     *
>> +     * NOTE: I think this is a redefinition error; I'm just faking that
>> +     * it isn't by clearing the size node... need to use stack pointer
>> +     * method.  But that will likely bring its own issues -- not with
>> +     * class layout though.
>> +     */
>> +    TYPE_SIZE (type) = NULL_TREE;
>> +    finish_struct_1 (type);
>
> Relaying out the class after the lambda body was parsed is something I 
> had attempted to do, but possibly failed at.  It will absolutely need 
> to be done.

I just inspected my code again.  The call to layout_class_type at the 
beginning of finish_lambda_function_body at semantics.c:5241 was 
intended to recalculate offsets to members in the case of default captures.

Here is the complete order of the pertinent function calls (file 
location has nothing to do with call order; I supply them to help the 
reader to follow):

finish_struct @ parser.c:6985

cp_parser_lambda_body @ parser.c:6992
--> finish_lambda_function_body @ parser.c:7380
----> layout_class_type @ semantics.c:5241

finish_struct_1 @ ???? I don't see this added yet.  I've checked out 
revision 150396.


- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04 14:49           ` Jason Merrill
@ 2009-08-04 16:17             ` John Freeman
  0 siblings, 0 replies; 24+ messages in thread
From: John Freeman @ 2009-08-04 16:17 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

Jason Merrill wrote:
> Incidentally, how does it work to just move the existing call of 
> finish_struct to after we parse the body?  I don't see why we need it 
> to be complete while we're in the body.

When I was working on it, there were some checks to make sure the class 
was complete.  I can't recall exactly where or why, but it was what led 
to me have two calls to finish_struct.

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04 14:57                 ` Jason Merrill
@ 2009-08-04 16:14                   ` John Freeman
  0 siblings, 0 replies; 24+ messages in thread
From: John Freeman @ 2009-08-04 16:14 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

Jason Merrill wrote:
> On 08/04/2009 10:17 AM, John Freeman wrote:
>> Reiterating, to allow more freedom in implementation, we can just say it
>> "behaves as" a template, rather than "is" a template.
>
> I don't see the difference.  As long as they work the same, the 
> compiler is free to do whatever it wants internally.

Ok, sounds great then.  Like I said, I wasn't sure if that allowance was 
implicit in the wording.

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  5:39         ` John Freeman
@ 2009-08-04 15:33           ` Richard Henderson
  2009-08-04 22:45           ` John Freeman
  1 sibling, 0 replies; 24+ messages in thread
From: Richard Henderson @ 2009-08-04 15:33 UTC (permalink / raw)
  To: John Freeman
  Cc: Jason Merrill, Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

On 08/03/2009 09:39 PM, John Freeman wrote:
>> * Instead of transforming:
>> *
>> * [&] { i = 1; j = 2; k = 3; };
>> *
>> * into
>> *
>> * [&i,&j,&k] { i = 1; j = 2; k = 3; };
>> *
>> * and thus storing three pointers to int, transform it into:
>> *
>> * [sp=enclosing-stack-pointer] { var-from-stack(i,sp) = 1;
>> * var-from-stack(j,sp) = 2;
>> * var-from-stack(k,sp) = 3; };
>> *
>> * and only store one pointer.
>
> This is preferred for reference default captures, but I was not familiar
> with stack pointer mechanics in GCC. I just wanted to get something
> working first that could be improved later.

Have a look at the documentation at the beginning of tree-nested.c.
Having something so magic as an "enclosing stack pointer" got us into
a lot of trouble in the past.  It's much better to be explicit about
things and create a struct to pop onto the stack of the caller.

Lets say you have

   int i, j, k, l;
   ...
   [&] { return i + j + k; }
   ...
   [&] { return j + k + l; }

you'd create a

   struct frame
   {
     int i,j,k,l;
   };

   frame f;
   [&f] { return f.i + f.j + f.k; }
   [&f] { return f.j + f.k + f.l; }

which is effectively what tree-nested.c does.


r~

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04 14:46               ` John Freeman
@ 2009-08-04 14:57                 ` Jason Merrill
  2009-08-04 16:14                   ` John Freeman
  0 siblings, 1 reply; 24+ messages in thread
From: Jason Merrill @ 2009-08-04 14:57 UTC (permalink / raw)
  To: John Freeman; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

On 08/04/2009 10:17 AM, John Freeman wrote:
> Reiterating, to allow more freedom in implementation, we can just say it
> "behaves as" a template, rather than "is" a template.

I don't see the difference.  As long as they work the same, the compiler 
is free to do whatever it wants internally.

Jason

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  9:07         ` Adam Butcher
  2009-08-04 13:35           ` Adam Butcher
  2009-08-04 13:44           ` John Freeman
@ 2009-08-04 14:49           ` Jason Merrill
  2009-08-04 16:17             ` John Freeman
  2 siblings, 1 reply; 24+ messages in thread
From: Jason Merrill @ 2009-08-04 14:49 UTC (permalink / raw)
  To: Adam Butcher; +Cc: jfreeman08, adam.butcher, Esben Mose Hansen, gcc

On 08/04/2009 04:52 AM, Adam Butcher wrote:
> Yes sorry about that.  I appreciate the issue.  I had taken a branch of trunk and applied the lambda changes to it to
> keep only lambda changes on my working branch (allowing simpler future rebaseing).  There were a number of things I
> had to change to to get the lambda changes a) building and b) working with test programs.  Unfortunately I did all
> this in one commit.  Not very helpful.  I will mail you my 'fixes' diff against the latest lambda branch head
> independent of the rebase noise if you want.

No need, it was easy enough to just apply it on another branch and 
compare against my branch.  Git makes so many things easier...

> Hopefully.  From my point of view the class generated by a lambda expression should be equivalent to something you
> could write yourself -- aside from the single stack-pointer reference optimization which only a compiler could achieve
> -- the class has a name, albeit invisible to the user (except in errors/warnings), and instances of should be useable
> just as if there were user-defined functors.  I'm sure there are things I've overlooked but hopefully this
> proof-of-concept will help to allay people's fears.

I agree.

Incidentally, how does it work to just move the existing call of 
finish_struct to after we parse the body?  I don't see why we need it to 
be complete while we're in the body.

I suppose I'll go ahead and review the current code; I haven't really 
looked at it closely yet.

Jason

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04 14:18             ` Jason Merrill
@ 2009-08-04 14:46               ` John Freeman
  2009-08-04 14:57                 ` Jason Merrill
  0 siblings, 1 reply; 24+ messages in thread
From: John Freeman @ 2009-08-04 14:46 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

Jason Merrill wrote:
> On 08/04/2009 09:35 AM, John Freeman wrote:
>
>> In my opinion, lambdas are not intended as just a shortcut to writing a
>> function object class. This is why our proposal did not require that
>> lambdas be implemented as classes; it is simply one implementation.
>> (Awaiting word to see if this is still the case in the working draft of
>> the standard; it may not be, but that doesn't change my opinion :)
>
> From N2859: "The type of the lambda-expression (which is also the type 
> of the closure object) is a unique, unnamed non-union class 
> type—called the closure type...."

Yes, this is the wording I'm worried about (it changed in N2914, but is 
similar).  I don't think it was in our original proposal.  I'm awaiting 
a response from Daveed Vandevoorde to see if it prescribes an 
implementation.

>
> IMO, it's better to define new functionality in terms of already 
> familiar features rather than have to specify everything about how a 
> new feature interacts with the rest of the language.

Right.  We defined the new functionality in terms of existing 
functionality for just this reason, but we did not prescribe an 
implementation (similar to other features in the standard).  Granted, a 
class is the obvious and intended implementation, but we don't want to 
prevent optimizations where possible, as long as they preserve 
behavior.  I'm not sure if this allowance is implicit in the wording; 
I'm not a standardese expert.  Hopefully, this answers the below as well.

>>
>> In response to Jason's concern here, a template implementation is not
>> required, just convenient. Hopefully you won't think of it as "templates
>> without template syntax", but "deduction using the existing template
>> mechanism".
>
> As above, suggesting that it doesn't have to be a template suggests 
> that there's a lot more specification left to do, such as how do you 
> deal with expressions whose type you don't know yet?  If you allow 
> non-lambda uses, how do they fit into overload resolution?  If you 
> just say it's a template, we already know how they work.

Reiterating, to allow more freedom in implementation, we can just say it 
"behaves as" a template, rather than "is" a template.

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04 13:44           ` John Freeman
@ 2009-08-04 14:18             ` Jason Merrill
  2009-08-04 14:46               ` John Freeman
  0 siblings, 1 reply; 24+ messages in thread
From: Jason Merrill @ 2009-08-04 14:18 UTC (permalink / raw)
  To: John Freeman; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

On 08/04/2009 09:35 AM, John Freeman wrote:

> In my opinion, lambdas are not intended as just a shortcut to writing a
> function object class. This is why our proposal did not require that
> lambdas be implemented as classes; it is simply one implementation.
> (Awaiting word to see if this is still the case in the working draft of
> the standard; it may not be, but that doesn't change my opinion :)

 From N2859: "The type of the lambda-expression (which is also the type 
of the closure object) is a unique, unnamed non-union class type—called 
the closure type...."

IMO, it's better to define new functionality in terms of already 
familiar features rather than have to specify everything about how a new 
feature interacts with the rest of the language.

> Thus,
> users should never see the class name. In warnings and errors, a lambda
> should be treated like an anonymous class, swapping its
> compiler-generated name with a placeholder like <lambda function>
> (similar to <anonymous class>).

Yep.

>>> Since templates work so differently from normal functions, I'm a little
>>> uncomfortable with the idea of templates that don't involve any template
>>> syntax, just the use of auto in the parameter list. But I'm open to
>>> giving it a try, at least in the lambda context. Maybe outside of
>>> lambda it could be used with a small template introducer...
>
> In response to Jason's concern here, a template implementation is not
> required, just convenient. Hopefully you won't think of it as "templates
> without template syntax", but "deduction using the existing template
> mechanism".

As above, suggesting that it doesn't have to be a template suggests that 
there's a lot more specification left to do, such as how do you deal 
with expressions whose type you don't know yet?  If you allow non-lambda 
uses, how do they fit into overload resolution?  If you just say it's a 
template, we already know how they work.

Jason

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  9:07         ` Adam Butcher
  2009-08-04 13:35           ` Adam Butcher
@ 2009-08-04 13:44           ` John Freeman
  2009-08-04 14:18             ` Jason Merrill
  2009-08-04 14:49           ` Jason Merrill
  2 siblings, 1 reply; 24+ messages in thread
From: John Freeman @ 2009-08-04 13:44 UTC (permalink / raw)
  To: Adam Butcher; +Cc: Jason Merrill, adam.butcher, Esben Mose Hansen, gcc

Adam Butcher wrote:
>
> Hopefully.  From my point of view the class generated by a lambda expression should be equivalent to something you
> could write yourself -- aside from the single stack-pointer reference optimization which only a compiler could achieve
> -- the class has a name, albeit invisible to the user (except in errors/warnings), and instances of should be useable
> just as if there were user-defined functors.  I'm sure there are things I've overlooked but hopefully this
> proof-of-concept will help to allay people's fears.
>   

In my opinion, lambdas are not intended as just a shortcut to writing a 
function object class.  This is why our proposal did not require that 
lambdas be implemented as classes; it is simply one implementation.  
(Awaiting word to see if this is still the case in the working draft of 
the standard; it may not be, but that doesn't change my opinion :)  
Thus, users should never see the class name.  In warnings and errors, a 
lambda should be treated like an anonymous class, swapping its 
compiler-generated name with a placeholder like <lambda function> 
(similar to <anonymous class>).  Additionally, users should never be 
able to instantiate a function call operator member, as below:

>> Makes sense.  I suppose to specify explicit template arguments users
>> would have to write
>>
>> lambdaob.operator()<template-arg>(fn-arg)
>
>   
> That would be the case for explicit instantiation yes.  With my implementation you could only get such as nullary
> function template if you explicitly specified the template parameters and explicitly specified an empty call argument
> list.  I've made the template parameter list optional within the already optional lambda-parameter-declaration.  If
> present, it has to be followed by a function parameter list.  The intent of course is that any template parameters
> will be referenced in the function parameter list.  Though it does not prevent having unreferenced template parameters
> that would need to be explicitly bound.

If a higher-order function were to accept a "function-like object" and 
instantiate its function call operator member, then it is using it as a 
class, and should not pretend to accept function pointers or lambdas.  
The argument types of a lambda function can be deduced from the context 
of the lambda expression, meaning a template constant lambda function 
should never be necessary.

>   
>> Since templates work so differently from normal functions, I'm a little
>> uncomfortable with the idea of templates that don't involve any template
>> syntax, just the use of auto in the parameter list.  But I'm open to
>> giving it a try, at least in the lambda context.  Maybe outside of
>> lambda it could be used with a small template introducer...
>>     

In response to Jason's concern here, a template implementation is not 
required, just convenient.  Hopefully you won't think of it as 
"templates without template syntax", but "deduction using the existing 
template mechanism".

> [snip]  The benefit
> of using it in lambdas is that the call operator is never 'seen', so whether its a template or not shouldn't affect
> the caller providing the input arguments are compatible.
>   

Exactly.

>> so we'd really expect them to be only deduced.
>>     
> Yes.
>   

Exactly.

>> When I last left the discussion, the biggest
>> issue in my opinion was concept map dropping.  The workaround made the
>> deduction algorithm intimidatingly complex.
>>
>>     
> I am not up to speed with the issues but they obviously exist.  One thing I don't understand, and perhaps you could
> help, is that whatever issues polymorphic lambdas have -- surely manually written function objects with template call
> operators have the same issues.  Is this true?  

We did not want (and I doubt a concept proposal would approve) 
polymorphic lambdas to interrupt the modular type checking of 
constrained templates, i.e. templates using concepts, so the constraints 
would have to be deduced and added to the function call operator (in a 
class implementation for lambdas).  Hand-written function object classes 
bypass this issue by not allowing the deduction of constraints - they 
must be hand-written if the function object class is to be used in a 
constrained context.

> And if so does it mean that future standard library algorithms will be
> more constraining than exisiting ones -- or am I barking up the wrong tree?
>   

When concepts come, standard library algorithms /will/ be constrained, 
but not to disallow any correct uses.  The constraints /will/ expose 
improper uses of the standard library.

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  9:07         ` Adam Butcher
@ 2009-08-04 13:35           ` Adam Butcher
  2009-08-04 13:44           ` John Freeman
  2009-08-04 14:49           ` Jason Merrill
  2 siblings, 0 replies; 24+ messages in thread
From: Adam Butcher @ 2009-08-04 13:35 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc, jfreeman08, Esben Mose Hansen

[-- Attachment #1: Type: text/plain, Size: 280 bytes --]

Hi Jason,

Pending response from assign at gnu dot org, I've attached diffs made against your latest lambda head.  They are
cleaned up a little to from the previous diffs against trunk.  First is the re-layout fix, second is experimental
polymorphic lambda support.

Cheers,
Adam

[-- Attachment #2: 0001-Re-laid-out-lambda-class-after-parsing-body.patch --]
[-- Type: application/octet-stream, Size: 3201 bytes --]

From b175823b2e7b95580cac53fda17408cc04d6fc0c Mon Sep 17 00:00:00 2001
From: Adam Butcher <adam@jessamine.co.uk>
Date: Mon, 3 Aug 2009 18:44:32 +0100
Subject: [PATCH 1/2] Re-laid-out lambda class after parsing body.

* Lambda class is re-laid-out after parsing body to allow for any implicit captures to be correctly copied.  This also fixes the issue with -fno-elide-constructors.
 * Added comment about handling lambda no linkage check properly in  cp/tree.c (I assume that commenting out the drop-through handling will break something somewhere?).
---
 gcc/cp/cp-tree.h |    2 +-
 gcc/cp/parser.c  |   11 ++++++++++-
 gcc/cp/tree.c    |    2 ++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 038aeee..bebd3ff 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4445,7 +4445,7 @@ enum cp_tree_node_structure_enum cp_tree_node_structure
 extern void finish_scope			(void);
 extern void push_switch				(tree);
 extern void pop_switch				(void);
-extern tree make_lambda_name	(void);
+extern tree make_lambda_name			(void);
 extern int decls_match				(tree, tree);
 extern tree duplicate_decls			(tree, tree, bool);
 extern tree declare_local_label			(tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f69e197..c1cc640 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6991,6 +6991,15 @@ cp_parser_lambda_expression (cp_parser* parser)
 
     cp_parser_lambda_body (parser, lambda_expr);
 
+    /* Layout again to allow for members to have been added to the
+       capture if it was an implicit capture.  Note that this would
+       not be necessary for 'complete reference capture' ([&]) if the
+       stack-pointer variant was implemented, since the layout would
+       be fixed.  It is still required in the general case to handle
+       'implicit value capture' ([=]) and mixed cases.  */
+    TYPE_SIZE (type) = NULL_TREE;
+    finish_struct_1 (type);
+
     parser->in_function_body = saved_in_function_body;
     parser->num_template_parameter_lists = saved_num_template_parameter_lists;
     --parser->num_classes_being_defined;
@@ -7039,7 +7048,7 @@ cp_parser_lambda_introducer (cp_parser* parser,
   /* Eat the leading `['. */
   cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
 
-  /* Record default capture mode. */
+  /* Record default capture mode. "[&" "[=" "[&," "[=," */
   if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
       && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_NAME)
     LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7bed343..94a2f16 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1523,6 +1523,7 @@ no_linkage_check (tree t, bool relaxed_p)
   switch (TREE_CODE (t))
     {
       /*
+      TODO: fix no linkage check on lambda functions properly
       tree fn;
       */
 
@@ -1538,6 +1539,7 @@ no_linkage_check (tree t, bool relaxed_p)
       if (TYPE_ANONYMOUS_P (t))
 	return t;
       /*
+      TODO: fix no linkage check on lambda functions properly
       fn = decl_function_context (TYPE_MAIN_DECL (t));
       if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
 	return t;
-- 
1.6.2.5


[-- Attachment #3: 0002-First-pass-polymorphic-lambda-support.patch --]
[-- Type: application/octet-stream, Size: 3950 bytes --]

From 14f7ab315aa2cafb5c96c55c4f2182c0bb265163 Mon Sep 17 00:00:00 2001
From: Adam Butcher <ajb@ccrvm001a.(none)>
Date: Tue, 4 Aug 2009 13:42:25 +0100
Subject: [PATCH 2/2] First pass polymorphic lambda support.

This commit adds experimental support for an optional template-parameter-list in angle-brackets at the start of a lambda-parameter-declaration.
---
 gcc/cp/parser.c    |   48 +++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/cp/semantics.c |    3 +++
 2 files changed, 50 insertions(+), 1 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c1cc640..2965161 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7176,9 +7176,13 @@ cp_parser_lambda_introducer (cp_parser* parser,
 /* Parse the (optional) middle of a lambda expression.
 
    lambda-parameter-declaration:
+       lambda-template-param-decl [opt]
      ( lambda-parameter-declaration-list [opt] ) exception-specification [opt]
        lambda-return-type-clause [opt]
 
+   lambda-template-param-decl:
+     < template-parameter-list >
+
    LAMBDA_EXPR is the current representation of the lambda expression.  */
 
 static void
@@ -7187,8 +7191,30 @@ 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);
+
+      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, "%<(%>");
 
@@ -7298,6 +7324,23 @@ 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 clean 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;
@@ -7337,6 +7380,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 1742598..aebad1d 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.6.2.5


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  4:11       ` Jason Merrill
  2009-08-04  4:39         ` John Freeman
  2009-08-04  5:39         ` John Freeman
@ 2009-08-04  9:07         ` Adam Butcher
  2009-08-04 13:35           ` Adam Butcher
                             ` (2 more replies)
  2 siblings, 3 replies; 24+ messages in thread
From: Adam Butcher @ 2009-08-04  9:07 UTC (permalink / raw)
  To: Jason Merrill, jfreeman08
  Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

Jason Merrill wrote:
> On 08/03/2009 09:36 PM, Adam Butcher wrote:
>> Thanks.  I haven't any copyright assignments on file -- this is my first dabbling with gcc and I've been doing it
>> mostly to experiment with C++ lambda support and non-standard extensions such as polymorphic lambda support.
>
> OK.  We'll need an assignment in order to incorporate your changes into
> GCC.  If you want to assign all present and future changes to the
> compiler, you could use the form
>
OK I've kicked that off.

>> I've been working in my own repository which I rebased earlier today from trunk (r150148).  I've attached the
>> rebase including the fix for generating correct copying of lambda classes (re-laying out after parsing body).

> Hmm, having the new changes folded into the old changes is kind of
> inconvenient, but I suppose I can deal.  It's moot anyway until your
> assignment is on file.
>
Yes sorry about that.  I appreciate the issue.  I had taken a branch of trunk and applied the lambda changes to it to
keep only lambda changes on my working branch (allowing simpler future rebaseing).  There were a number of things I
had to change to to get the lambda changes a) building and b) working with test programs.  Unfortunately I did all
this in one commit.  Not very helpful.  I will mail you my 'fixes' diff against the latest lambda branch head
independent of the rebase noise if you want.

> Incidentally, comments like
>
> /*
>   *
>   *
>   */
>
> aren't customary in GCC sources; that's just something John did that
> we'll need to clean up before the code goes into the trunk.  There are
> other formatting irregularities, some of which I've corrected.
>
Ah I see.  I was following the principle of following the nearest style!  I have reworked my changes in this style.

>> Experimenting with a working version and seeing it's issues will be useful to me.  To others to maybe.  With
>> concepts
>> gone from C++0x and being reworked for C++15(?) maybe support for polymorphic lambdas could be reintroduced? --
>> though
>> I'm sure its much too late for that and that its likely been around the buoy many times.  From what I have read I
>> got
>> the idea that the Callable concept was the primary reason for polymorphic lambdas not being accepted.
>
> I don't know what the reasoning was there, but people have been somewhat
> conservative about what usages of lambdas are allowed for fear of
> unforseen implementation issues.  Certainly having a working
> implementation would go a lot toward convincing people to allow it, even
> if it doesn't make it into C++0x.
>
Hopefully.  From my point of view the class generated by a lambda expression should be equivalent to something you
could write yourself -- aside from the single stack-pointer reference optimization which only a compiler could achieve
-- the class has a name, albeit invisible to the user (except in errors/warnings), and instances of should be useable
just as if there were user-defined functors.  I'm sure there are things I've overlooked but hopefully this
proof-of-concept will help to allay people's fears.

>> Implied template typename arguments via auto are not currently supported.  The syntax parses but I haven't yet
>> synthesized the template arguments and therefore not replaced the auto's with them so it doesn't compile.
>
> Since templates work so differently from normal functions, I'm a little
> uncomfortable with the idea of templates that don't involve any template
> syntax, just the use of auto in the parameter list.  But I'm open to
> giving it a try, at least in the lambda context.  Maybe outside of
> lambda it could be used with a small template introducer...
>
I did think about auto as a shortcut for template typename outside of lambdas but I figured that was pushing it a bit
too far.  It wouldn't be obvious that a function declared in that way was actually a function template.  The benefit
of using it in lambdas is that the call operator is never 'seen', so whether its a template or not shouldn't affect
the caller providing the input arguments are compatible.

>> I'd welcome feedback on the syntax and semantics and of course any fundamental things I've missed by coming up with
>> such a syntax!
>>
>>  From a grammar point of view I've just expanded lambda-parameter-declaration to start with:
>>    lambda-template-param-decl [opt]
>> where lambda-template-param-decl is:
>>    <  template-parameter-list>
>
> Makes sense.  I suppose to specify explicit template arguments users
> would have to write
>
> lambdaob.operator()<template-arg>(fn-arg)
>
That would be the case for explicit instantiation yes.  With my implementation you could only get such as nullary
function template if you explicitly specified the template parameters and explicitly specified an empty call argument
list.  I've made the template parameter list optional within the already optional lambda-parameter-declaration.  If
present, it has to be followed by a function parameter list.  The intent of course is that any template parameters
will be referenced in the function parameter list.  Though it does not prevent having unreferenced template parameters
that would need to be explicitly bound.

> so we'd really expect them to be only deduced.
Yes.

>> # unspecified typename inferred by use of auto in function parameter list
>>        [=]<typename YY>  (auto* x, YY y) { return x->Func( y, a, b ); };
>> # is translated into
>>        [=]<typename YY, typename X>  (X* x, YY y) { return x->Func( y, a, b ); };
>
> A mixed declaration like that seems rather ugly to me; I'd hope that
> people would use either explicit template args or auto in a particular
> lambda, not both.  But I suppose that's not reason enough to forbid it.
>
Yes.  I was just considering the general case.  Note that auto only infers 'typename' template parameters.  If you
wanted more complex parameters you would need to specify them in the template parameter list -- but you may still want
to use auto as well.  I suspect this case would be handled better elsewhere though.  It is an edge usage that I
wouldn't expect to see.  Maybe to constrain some input -- for instance

   [=] <template <int> class T> (auto* x, T<4> const& t) { ...

would force that the second argument was a template parameterized on int 4 (for whatever obscure reason) whilst still
adding an implicit typename parameter for use in the type of 'x'.

As you say, I don't really see any reason to forbid it.  Someone may find a unique and useful use for it at some point!

John Freeman wrote:
> Jason Merrill wrote:
>>> Experimenting with a working version and seeing it's issues will be
>>> useful to me.  To others to maybe.  With concepts
>>> gone from C++0x and being reworked for C++15(?) maybe support for
>>> polymorphic lambdas could be reintroduced? -- though
>>> I'm sure its much too late for that and that its likely been around
>>> the buoy many times.  From what I have read I got
>>> the idea that the Callable concept was the primary reason for
>>> polymorphic lambdas not being accepted.
>>
>> I don't know what the reasoning was there, but people have been
>> somewhat conservative about what usages of lambdas are allowed for
>> fear of unforseen implementation issues.  Certainly having a working
>> implementation would go a lot toward convincing people to allow it,
>> even if it doesn't make it into C++0x.
>
> There were several issues with polymorphic lambdas in the presence of
> concepts that concerned many on the committee.  I've come to accept that
> it's too late to re-introduce polymorphic lambdas into C++0x (now
> C++1x), but there's no stopping GCC from implementing it as an extension.
>
I feared that would be the case.  If its accepted by the C++ community as a useful thing in GCC then maybe it could
become a defacto standard -- if we could just get comeau, digital-mars, borland, and microsoft to buy into it ;).  But
I'm getting _way_ ahead of myself! -- we don't even know if people want it yet -- or whether there are any nasties
that crop up during experiments.

> Just my opinion, but I don't think there should be any special template
> syntax [for auto to be used to infer template typename parameters in
> polymorphic lambdas].  The whole point of argument deduction was
> terseness.  It doesn't have to be implemented using templates, so I
> don't equate it with templates.
>
That's a good point.  Hopefully others will share that view -- the syntax certainly seems intuitive to me as a user.


John Freeman wrote:
> Relaying out the class after the lambda body was parsed is something I
> had attempted to do, but possibly failed at.  It will absolutely need to
> be done.
>
>> The way 'default reference capture' is implemented on the lambda branch
>> seems to be kind of reactive.  I would expect that inheriting the
>> stack somehow (maybe using just a stack pointer) would be better
>> but without more investigation I don't know if that is possible or
>> how one would go about doing it.
>
> This won't be suitable in the general case, because of the copy default
> capture [=].  Implicit captures will have to be reactive.
>
Yes I realized this when I was re-basing my changes.  I've altered my stack-pointer comment to refer to only implicit
reference capture in my latest patch.

> This is preferred for reference default captures, but I was not familiar
> with stack pointer mechanics in GCC.  I just wanted to get something
> working first that could be improved later.
>
Completely agree.  And you've done a great job.  Also handling the more general and useful case is clearly a winning
strategy.  Clients would not be affected by an optimization later -- just that their reference lambdas would drop in
size.

> When I last left the discussion, the biggest
> issue in my opinion was concept map dropping.  The workaround made the
> deduction algorithm intimidatingly complex.
>
I am not up to speed with the issues but they obviously exist.  One thing I don't understand, and perhaps you could
help, is that whatever issues polymorphic lambdas have -- surely manually written function objects with template call
operators have the same issues.  Is this true?  And if so does it mean that future standard library algorithms will be
more constraining than exisiting ones -- or am I barking up the wrong tree?

Regards,
Adam


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  4:11       ` Jason Merrill
  2009-08-04  4:39         ` John Freeman
@ 2009-08-04  5:39         ` John Freeman
  2009-08-04 15:33           ` Richard Henderson
  2009-08-04 22:45           ` John Freeman
  2009-08-04  9:07         ` Adam Butcher
  2 siblings, 2 replies; 24+ messages in thread
From: John Freeman @ 2009-08-04  5:39 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

I haven't been following GCC, so I need to thank Jason for forwarding 
this issue to me.

I just read through the messages on the list, and had some more comments:

> +    /* relayout again -- to allow for implicit
> +     * parameters to have been added to the capture if it was a
> +     * 'default capture' -- note that this would not be necessary if
> +     * the stack-pointer variant was implemented -- since the layout
> +     * would be known.
> +     * Relayingout here might have nasty effect if one were to query
> +     * sizeof *this from within the body -- would that even be
> +     * possible -- *this would refer to the lambda or the enclosing
> +     * class instance -- if there was one.???
> +     *
> +     * NOTE: I think this is a redefinition error; I'm just faking that
> +     * it isn't by clearing the size node... need to use stack pointer
> +     * method.  But that will likely bring its own issues -- not with
> +     * class layout though.
> +     */
> +    TYPE_SIZE (type) = NULL_TREE;
> +    finish_struct_1 (type);

Relaying out the class after the lambda body was parsed is something I 
had attempted to do, but possibly failed at.  It will absolutely need to 
be done.

> The way 'default reference capture' is implemented on the lambda branch seems to be kind of reactive.  I would expect
> that inheriting the stack somehow (maybe using just a stack pointer) would be better but without more investigation I
> don't know if that is possible or how one would go about doing it. 

This won't be suitable in the general case, because of the copy default 
capture [=].  Implicit captures will have to be reactive.

> /*
>  * Rather than looping through the identifiers used in the scope of
>  * the lambda and synthesizing individual captures of them, it would
>  * be better to ref the stack frame as transparently as possible...
>  * e.g. given just three ints i, j and k in scope:
>  * Instead of transforming:
>  *
>  *    [&] { i = 1; j = 2; k = 3; };
>  *
>  * into
>  *
>  *    [&i,&j,&k] { i = 1; j = 2; k = 3; };
>  *
>  * and thus storing three pointers to int, transform it into:
>  *
>  *    [sp=enclosing-stack-pointer] { var-from-stack(i,sp) = 1;
>  *                                   var-from-stack(j,sp) = 2;
>  *                                   var-from-stack(k,sp) = 3; };
>  *
>  * and only store one pointer.

This is preferred for reference default captures, but I was not familiar 
with stack pointer mechanics in GCC.  I just wanted to get something 
working first that could be improved later.

>  * I don't know if its possible but it may be possible to 'append'
>  * the lambda's stack to the existing scope rather than creating a
>  * new constrained scope -- from a logical point of view.

Again, this is not suitable to the general case because a lambda can 
outlast its enclosing scope.

> My motivation for investigating is that I consider constraining lambdas to be monomorphic significantly reduces their
> usefulness.   I'm sure there are many good reasons why the committee decided that it was the way to go.

I don't think it handicaps lambdas as much as some may believe, but 
still wanted polymorphic lambdas as well. There were just too many 
issues with deduction.  When I last left the discussion, the biggest 
issue in my opinion was concept map dropping.  The workaround made the 
deduction algorithm intimidatingly complex.

> The following program generates the expected code and runs correctly.
>  auto f = [&] <typename T, typename U> (T n, T const& m, U u) { i = ++n; j = u(++n); k = ++n; };
>   

This is exciting.  The main thing I failed to add was dependent type 
support, so I want to check this out.  (I need to register a new ssh key)

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  4:11       ` Jason Merrill
@ 2009-08-04  4:39         ` John Freeman
  2009-08-04  5:39         ` John Freeman
  2009-08-04  9:07         ` Adam Butcher
  2 siblings, 0 replies; 24+ messages in thread
From: John Freeman @ 2009-08-04  4:39 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Adam Butcher, adam.butcher, Esben Mose Hansen, gcc

Jason Merrill wrote:
>> Experimenting with a working version and seeing it's issues will be 
>> useful to me.  To others to maybe.  With concepts
>> gone from C++0x and being reworked for C++15(?) maybe support for 
>> polymorphic lambdas could be reintroduced? -- though
>> I'm sure its much too late for that and that its likely been around 
>> the buoy many times.  From what I have read I got
>> the idea that the Callable concept was the primary reason for 
>> polymorphic lambdas not being accepted.
>
> I don't know what the reasoning was there, but people have been 
> somewhat conservative about what usages of lambdas are allowed for 
> fear of unforseen implementation issues.  Certainly having a working 
> implementation would go a lot toward convincing people to allow it, 
> even if it doesn't make it into C++0x.

There were several issues with polymorphic lambdas in the presence of 
concepts that concerned many on the committee.  I've come to accept that 
it's too late to re-introduce polymorphic lambdas into C++0x (now 
C++1x), but there's no stopping GCC from implementing it as an extension.

>
>
>> Implied template typename arguments via auto are not currently 
>> supported.  The syntax parses but I haven't yet
>> synthesized the template arguments and therefore not replaced the 
>> auto's with them so it doesn't compile.
>
> Since templates work so differently from normal functions, I'm a 
> little uncomfortable with the idea of templates that don't involve any 
> template syntax, just the use of auto in the parameter list.  But I'm 
> open to giving it a try, at least in the lambda context.  Maybe 
> outside of lambda it could be used with a small template introducer...

Just my opinion, but I don't think there should be any special template 
syntax.  The whole point of argument deduction was terseness.  It 
doesn't have to be implemented using templates, so I don't equate it 
with templates.

- John

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-04  2:25     ` Adam Butcher
@ 2009-08-04  4:11       ` Jason Merrill
  2009-08-04  4:39         ` John Freeman
                           ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Jason Merrill @ 2009-08-04  4:11 UTC (permalink / raw)
  To: Adam Butcher; +Cc: adam.butcher, Esben Mose Hansen, gcc, jfreeman08

On 08/03/2009 09:36 PM, Adam Butcher wrote:
> Thanks.  I haven't any copyright assignments on file -- this is my first dabbling with gcc and I've been doing it
> mostly to experiment with C++ lambda support and non-standard extensions such as polymorphic lambda support.

OK.  We'll need an assignment in order to incorporate your changes into 
GCC.  If you want to assign all present and future changes to the 
compiler, you could use the form

http://git.savannah.gnu.org/cgit/gnulib.git/tree/doc/Copyright/request-assign.future

> Cool.  I've been working in my own repository which I rebased earlier today from trunk (r150148).  I've attached the
> rebase including the fix for generating correct copying of lambda classes (re-laying out after parsing body).

Hmm, having the new changes folded into the old changes is kind of 
inconvenient, but I suppose I can deal.  It's moot anyway until your 
assignment is on file.

Incidentally, comments like

/*
  *
  *
  */

aren't customary in GCC sources; that's just something John did that 
we'll need to clean up before the code goes into the trunk.  There are 
other formatting irregularities, some of which I've corrected.

> It also
> fixes return type deduction which didn't work after updating to 4.5 as build_lang_decl no longer accepts DECL_RESULT
> (I replaced it with build_decl directly which seemed to work fine).  There were a few other things like placement of
> GTY (()) and replacing preservation of skip_evaluation with preservation of cp_unevaluated_operand and
> c_inhibit_evaluation_warnings (which seems to have been what's occurred in other places).

Oops, and I checked in my merge without even testing that it would 
build...guess I'd better fix it.

> Experimenting with a working version and seeing it's issues will be useful to me.  To others to maybe.  With concepts
> gone from C++0x and being reworked for C++15(?) maybe support for polymorphic lambdas could be reintroduced? -- though
> I'm sure its much too late for that and that its likely been around the buoy many times.  From what I have read I got
> the idea that the Callable concept was the primary reason for polymorphic lambdas not being accepted.

I don't know what the reasoning was there, but people have been somewhat 
conservative about what usages of lambdas are allowed for fear of 
unforseen implementation issues.  Certainly having a working 
implementation would go a lot toward convincing people to allow it, even 
if it doesn't make it into C++0x.

> Implied template typename arguments via auto are not currently supported.  The syntax parses but I haven't yet
> synthesized the template arguments and therefore not replaced the auto's with them so it doesn't compile.

Since templates work so differently from normal functions, I'm a little 
uncomfortable with the idea of templates that don't involve any template 
syntax, just the use of auto in the parameter list.  But I'm open to 
giving it a try, at least in the lambda context.  Maybe outside of 
lambda it could be used with a small template introducer...

> I'd welcome feedback on the syntax and semantics and of course any fundamental things I've missed by coming up with
> such a syntax!
>
>  From a grammar point of view I've just expanded lambda-parameter-declaration to start with:
>    lambda-template-param-decl [opt]
> where lambda-template-param-decl is:
>    <  template-parameter-list>

Makes sense.  I suppose to specify explicit template arguments users 
would have to write

lambdaob.operator()<template-arg>(fn-arg)

so we'd really expect them to be only deduced.

> # unspecified typename inferred by use of auto in function parameter list
>        [=]<typename YY>  (auto* x, YY y) { return x->Func( y, a, b ); };
> # is translated into
>        [=]<typename YY, typename X>  (X* x, YY y) { return x->Func( y, a, b ); };

A mixed declaration like that seems rather ugly to me; I'd hope that 
people would use either explicit template args or auto in a particular 
lambda, not both.  But I suppose that's not reason enough to forbid it.

Jason

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-08-03 18:31   ` Jason Merrill
@ 2009-08-04  2:25     ` Adam Butcher
  2009-08-04  4:11       ` Jason Merrill
  0 siblings, 1 reply; 24+ messages in thread
From: Adam Butcher @ 2009-08-04  2:25 UTC (permalink / raw)
  To: Jason Merrill; +Cc: adam.butcher, Esben Mose Hansen, gcc, jfreeman08

[-- Attachment #1: Type: text/plain, Size: 7007 bytes --]

Jason Merrill wrote:
> Great!  Please feel free to ask me any questions you have directly.  Do
> you have copyright assignments on file yet?
>
Thanks.  I haven't any copyright assignments on file -- this is my first dabbling with gcc and I've been doing it
mostly to experiment with C++ lambda support and non-standard extensions such as polymorphic lambda support.

> I'll go ahead and merge the current trunk into the branch.
>
Cool.  I've been working in my own repository which I rebased earlier today from trunk (r150148).  I've attached the
rebase including the fix for generating correct copying of lambda classes (re-laying out after parsing body).  It also
fixes return type deduction which didn't work after updating to 4.5 as build_lang_decl no longer accepts DECL_RESULT
(I replaced it with build_decl directly which seemed to work fine).  There were a few other things like placement of
GTY (()) and replacing preservation of skip_evaluation with preservation of cp_unevaluated_operand and
c_inhibit_evaluation_warnings (which seems to have been what's occurred in other places).

> parsing the lambda body doesn't depend on the current
> contents of the class: we parse the body, noting things that we need to
> capture, then later rewrite the body to access captured variables
> through the class.
>
Great.  So re-laying out the class after parsing the body is a reasonable thing to do.

> in the X example we don't parse the body of init_i until
> after the closing brace of X.
>
I understand.  Thanks for pointing that out.

I've provided the two changesets as separate diffs in case they are of any use to anyone.

Currently I have 4.5.x with working lambdas branch and with my (non-standard) experimental support for polymorphic
lambdas.

My motivation for investigating is that I consider constraining lambdas to be monomorphic significantly reduces their
usefulness.  I'm sure there are many good reasons why the committee decided that it was the way to go.  For many
use-cases in my work though, a language feature that could replace boost.bind and boost.lambda would be most useful. 
Currently monomorphic lambdas get close but don't allow for a key benefit -- omitting type information from their
definition.  Manually written helpers work best but must generally be defined far from the use-site.

Experimenting with a working version and seeing it's issues will be useful to me.  To others to maybe.  With concepts
gone from C++0x and being reworked for C++15(?) maybe support for polymorphic lambdas could be reintroduced? -- though
I'm sure its much too late for that and that its likely been around the buoy many times.  From what I have read I got
the idea that the Callable concept was the primary reason for polymorphic lambdas not being accepted.  Maybe the
Callable concept in concepts-15 could be made to work with any function object -- including polymorphic lambdas ;). 
All a polymorphic lambda is, at least as far as I can see, is a class with a template call operator -- surely functors
of this nature must be acceptable to meet the Callable for given arguments -- so why not polymorphic lambda?  I'm sure
I must of got the wrong end of the stick somewhere.


The following program generates the expected code and runs correctly.  Please note that these are just scribblings at
the moment -- I don't expect them to necessarily go anywhere.


// Z and Y are just to make sure return type deduction works with polymorphic lambdas
struct Z
{
};

struct Y
{
   Z operator+ (int)
   {
      return Z();
   }
};

int main()
{
   char i,j,k;

   // prove Y and Z relation
   Y y;
   Z z = y + 1;

   auto add_one_i = [] (int x) { return x + 1; };
   auto add_one = [] <typename X> (X x) { return x + 1; };
   //auto add_one_auto = [] (auto const& x) { return x + 1; };

   Z z2 = add_one(y);

   auto f = [&] <typename T, typename U> (T n, T const& m, U u) { i = ++n; j = u(++n); k = ++n; };

   auto g = f;

   g(64,1,add_one);

   return i;
}


Implied template typename arguments via auto are not currently supported.  The syntax parses but I haven't yet
synthesized the template arguments and therefore not replaced the auto's with them so it doesn't compile.

I'd welcome feedback on the syntax and semantics and of course any fundamental things I've missed by coming up with
such a syntax!

From a grammar point of view I've just expanded lambda-parameter-declaration to start with:
  lambda-template-param-decl [opt]
where lambda-template-param-decl is:
  < template-parameter-list >

Regarding the simplified definition of polymorphic lambdas, I'm expecting that the use of auto to retroactively infer
template typename parameters will be controversial -- but I do think the syntax from the user's perspective is
intuitive:

# currently
      std::bind( &SomeLongTemplate<Class1,Class2>::Func, _1, _2, a, b );

# monomorphic lambda (more type than actual expression)
      [=] (SomeLongTemplate<Class1,Class2>* x, SomeBoringType y) { return x->Func( y, a, b ); };

# explicit polymorphic lambda (better but verbose)
      [=] <typename X, typename Y> (X* x, Y y) { return x->Func( y, a, b ); };

# equivalent to the above, typenames inferred by use of auto in function parameter list
      [=] (auto* x, auto y) { return x->Func( y, a, b ); };

The use of auto in the call operator's function parameter list will add a synthesized template-parameter to, and
create if necessary, a template parameter list for the call operator where the added parameter will be substituted
in-place-of auto.

# unspecified typename inferred by use of auto in function parameter list
      [=] <typename YY> (auto* x, YY y) { return x->Func( y, a, b ); };
# is translated into
      [=] <typename YY, typename X> (X* x, YY y) { return x->Func( y, a, b ); };


Again I must apologize for yet another brain-dump.  I am keen to get feedback -- even if it is to say "don't bother --
it will never work!"

Cheers
Adam



commit 2afabf298e07acd94a1aca674c0f8158f823c6e7

    Re-based C++ lambda branch as of 150148 onto trunk.

    Additional changes to make work with GCC 4.5:
     * Moved GTY (()) to before declared names.
     * skip_evaluation preservation removed; cp_unevaluated_operand and
       c_inhibit_evaluation_warnings are preserved instead.
     * DECL_RESULT node creation done directly with build_decl;
       build_lang_decl no longer accepts DECL_RESULT.

    Additional fixes:
     * Lambda class is re-laid-out after parsing body to allow for any
       implicit captures to be correctly copied.  This also fixes the
       known -fno-elide-constructors issue.

    Additional changes:
     * Added comment about handling lambda no linkage check properly
       in cp/tree.c (I assume that commenting out the drop-through
       handling will break something somewhere?).


commit cc20413435ff614b13f0d19935f818c09e165768

    First pass polymorphic lambda support.  This version adds an optional template paramter list in angle-brackes
after the lambda-introducer.


[-- Attachment #2: 0001-Re-based-C-lambda-branch-as-of-150148-onto-trunk.patch --]
[-- Type: application/octet-stream, Size: 58281 bytes --]

From: Adam Butcher
Date: Mon, 3 Aug 2009 18:44:32 +0100
Subject: [PATCH] Re-based C++ lambda branch as of 150148 onto trunk.

Additional changes to make work with GCC 4.5:
 * Moved GTY (()) to before declared names.
 * skip_evaluation preservation removed; cp_unevaluated_operand and c_inhibit_evaluation_warnings are preserved instead.
 * DECL_RESULT node creation done directly with build_decl; build_lang_decl no longer accepts DECL_RESULT.

Additional fixes:
 * Lambda class is re-laid-out after parsing body to allow for any implicit captures to be correctly copied.  This also fixes the known -fno-elide-constructors issue.

Additional changes:
 * Added comment about handling lambda no linkage check properly in  cp/tree.c (I assume that commenting out the drop-through handling will break something somewhere?).
---
 gcc/cp/class.c                                     |    3 +-
 gcc/cp/cp-objcp-common.c                           |    4 +-
 gcc/cp/cp-tree.def                                 |   10 +
 gcc/cp/cp-tree.h                                   |   84 ++++
 gcc/cp/decl.c                                      |    1 +
 gcc/cp/name-lookup.c                               |   16 +
 gcc/cp/parser.c                                    |  497 +++++++++++++++++++-
 gcc/cp/semantics.c                                 |  372 +++++++++++++++-
 gcc/cp/tree.c                                      |    6 +
 .../cpp0x/lambda/lambda-capture-const-ref-neg.C    |   14 +
 .../g++.dg/cpp0x/lambda/lambda-capture-const-ref.C |   15 +
 .../g++.dg/cpp0x/lambda/lambda-const-neg.C         |   19 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const.C   |   20 +
 .../g++.dg/cpp0x/lambda/lambda-copy-default-neg.C  |   13 +
 .../g++.dg/cpp0x/lambda/lambda-copy-default.C      |   14 +
 .../g++.dg/cpp0x/lambda/lambda-copy-neg.C          |   13 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy.C    |   14 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce.C  |   24 +
 .../g++.dg/cpp0x/lambda/lambda-in-class-neg.C      |   35 ++
 .../g++.dg/cpp0x/lambda/lambda-in-class.C          |   36 ++
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mixed.C   |   13 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable.C |   16 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C  |   52 ++
 .../g++.dg/cpp0x/lambda/lambda-non-const.C         |   19 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nop.C     |   19 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-pass.C    |   27 +
 .../g++.dg/cpp0x/lambda/lambda-recursive.C         |   21 +
 .../g++.dg/cpp0x/lambda/lambda-ref-default.C       |   15 +
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref.C     |   15 +
 29 files changed, 1390 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref-neg.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-neg.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default-neg.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-neg.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mixed.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-const.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nop.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-pass.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-recursive.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref-default.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref.C

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9a76883..a510bc6 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -150,7 +150,6 @@ static void check_bases (tree, int *, int *);
 static void check_bases_and_members (tree);
 static tree create_vtable_ptr (tree, tree *);
 static void include_empty_classes (record_layout_info);
-static void layout_class_type (tree, tree *);
 static void propagate_binfo_offsets (tree, tree);
 static void layout_virtual_bases (record_layout_info, splay_tree);
 static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *);
@@ -4824,7 +4823,7 @@ include_empty_classes (record_layout_info rli)
    BINFO_OFFSETs for all of the base-classes.  Position the vtable
    pointer.  Accumulate declared virtual functions on VIRTUALS_P.  */
 
-static void
+void
 layout_class_type (tree t, tree *virtuals_p)
 {
   tree non_static_data_members;
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 2363cd7..efe6c84 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -135,8 +135,8 @@ cp_tree_size (enum tree_code code)
     case ARGUMENT_PACK_SELECT:
       return sizeof (struct tree_argument_pack_select);
 
-    case TRAIT_EXPR:
-      return sizeof (struct tree_trait_expr);
+    case TRAIT_EXPR:            return sizeof (struct tree_trait_expr);
+    case LAMBDA_EXPR:           return sizeof (struct tree_lambda_expr);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index a43fa82..c69522f 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -416,6 +416,16 @@ DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0)
 /* Represents a trait expression during template expansion.  */
 DEFTREECODE (TRAIT_EXPR, "trait_expr", tcc_exceptional, 0)
 
+/* A lambda expression.  This is a C++0x extension.
+   LAMBDA_EXPR_DEFAULT_CAPTURE_MODE is an enum for the default, which may be
+   none.
+   LAMBDA_EXPR_CAPTURE_LIST holds the capture-list, including `this'.
+   LAMBDA_EXPR_THIS_CAPTURE goes straight to the capture of `this', if it exists.
+   LAMBDA_EXPR_MUTABLE_P signals whether this lambda was declared mutable.
+   LAMBDA_EXPR_RETURN_TYPE holds the return type, if it was specified.
+   LAMBDA_EXPR_FUNCTION is the FUNCTION_DECL generated by this expression.  */
+DEFTREECODE (LAMBDA_EXPR, "lambda_expr", tcc_exceptional, 0)
+
 /* The declared type of an expression.  This is a C++0x extension.
    DECLTYPE_TYPE_EXPR is the expression whose type we are computing.
    DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P states whether the
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c507ac8..3264d06 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -77,6 +77,7 @@ framework extensions, you must include this file before toplev.h, not after.
       TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
       ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
       CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
+      LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -87,6 +88,7 @@ framework extensions, you must include this file before toplev.h, not after.
       TYPENAME_IS_CLASS_P (in TYPENAME_TYPE)
       STMT_IS_FULL_EXPR_P (in _STMT)
       TARGET_EXPR_LIST_INIT_P (in TARGET_EXPR)
+      LAMBDA_EXPR_MUTABLE_P (in LAMBDA_EXPR)
    2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
       ICS_THIS_FLAG (in _CONV)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@@ -517,6 +519,64 @@ struct GTY (()) tree_trait_expr {
   enum cp_trait_kind kind;
 };
 
+/* Based off of ANON_AGGR_TYPE_P.  */
+#define LAMBDA_TYPE_P(NODE) \
+  (CLASS_TYPE_P (NODE) && LAMBDANAME_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
+
+/* Test if FUNCTION_DECL is a lambda function.  */
+#define LAMBDA_FUNCTION_P(FNDECL) \
+  (DECL_CONTEXT (FNDECL) && LAMBDA_TYPE_P (DECL_CONTEXT (FNDECL)))
+
+enum cp_lambda_default_capture_mode_type {
+  CPLD_NONE,
+  CPLD_COPY,
+  CPLD_REFERENCE
+};
+
+/* The method of default capture, if any.  */
+#define LAMBDA_EXPR_DEFAULT_CAPTURE_MODE(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->default_capture_mode)
+
+/* The capture-list, including `this'.  Each capture is stored as a FIELD_DECL
+ * so that the name, type, and field are all together, whether or not it has
+ * been added to the lambda's class type.
+   TREE_LIST:
+     TREE_PURPOSE: The FIELD_DECL for this capture.
+     TREE_VALUE: The initializer. This is part of a GNU extension.  */
+#define LAMBDA_EXPR_CAPTURE_LIST(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->capture_list)
+
+/* The node in the capture-list that holds the 'this' capture.  */
+#define LAMBDA_EXPR_THIS_CAPTURE(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->this_capture)
+
+/* Predicate tracking whether `this' is in the effective capture set.  */
+#define LAMBDA_EXPR_CAPTURES_THIS_P(NODE) \
+  LAMBDA_EXPR_THIS_CAPTURE(NODE)
+
+/* Predicate tracking whether the lambda was declared 'mutable'.  */
+#define LAMBDA_EXPR_MUTABLE_P(NODE) \
+  TREE_LANG_FLAG_1 (LAMBDA_EXPR_CHECK (NODE))
+
+/* The return type in the expression.
+ * NULL_TREE indicates that none was specified.  */
+#define LAMBDA_EXPR_RETURN_TYPE(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->return_type)
+
+/* The FUNCTION_DECL generated by the expression.  */
+#define LAMBDA_EXPR_FUNCTION(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->function)
+
+struct GTY (()) tree_lambda_expr
+{
+  struct tree_common common;
+  enum cp_lambda_default_capture_mode_type default_capture_mode;
+  tree capture_list;
+  tree this_capture;
+  tree return_type;
+  tree function;
+};
+
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
   TS_CP_IDENTIFIER,
@@ -530,6 +590,7 @@ enum cp_tree_node_structure_enum {
   TS_CP_STATIC_ASSERT,
   TS_CP_ARGUMENT_PACK_SELECT,
   TS_CP_TRAIT_EXPR,
+  TS_CP_LAMBDA_EXPR,
   LAST_TS_CP_ENUM
 };
 
@@ -550,6 +611,8 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
     argument_pack_select;
   struct tree_trait_expr GTY ((tag ("TS_CP_TRAIT_EXPR")))
     trait_expression;
+  struct tree_lambda_expr GTY ((tag ("TS_CP_LAMBDA_EXPR")))
+    lambda_expression;
 };
 
 \f
@@ -1155,6 +1218,7 @@ struct GTY(()) lang_type_class {
      as a list of adopted protocols or a pointer to a corresponding
      @interface.  See objc/objc-act.h for details.  */
   tree objc_info;
+  tree lambda_expr;
   /* sorted_fields is sorted based on a pointer, so we need to be able
      to resort it if pointers get rearranged.  */
   struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields")))
@@ -1426,6 +1490,10 @@ struct GTY(()) lang_type {
 #define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->befriending_classes)
 
+/* The associated LAMBDA_EXPR that made this class.  */
+#define CLASSTYPE_LAMBDA_EXPR(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->lambda_expr)
+
 /* Say whether this node was declared as a "class" or a "struct".  */
 #define CLASSTYPE_DECLARED_CLASS(NODE) \
   (LANG_TYPE_CLASS_CHECK (NODE)->declared_class)
@@ -3773,6 +3841,13 @@ extern GTY(()) VEC(tree,gc) *local_classes;
 #define VTABLE_DELTA_NAME	"__delta"
 #define VTABLE_PFN_NAME		"__pfn"
 
+#define LAMBDANAME_PREFIX "__lambda"
+#define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d"
+#define LAMBDANAME_P(ID_NODE) \
+  (!strncmp (IDENTIFIER_POINTER (ID_NODE), \
+             LAMBDANAME_PREFIX, \
+	     sizeof (LAMBDANAME_PREFIX) - 1))
+
 #if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL)
 
 #define VTABLE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \
@@ -4295,6 +4370,7 @@ extern bool currently_open_class		(tree);
 extern tree currently_open_derived_class	(tree);
 extern tree finish_struct			(tree, tree);
 extern void finish_struct_1			(tree);
+extern void layout_class_type                   (tree, tree *);
 extern int resolves_to_fixed_type_p		(tree, int *);
 extern void init_class_processing		(void);
 extern int is_empty_class			(tree);
@@ -4355,6 +4431,7 @@ extern tree pushdecl_maybe_friend		(tree, bool);
 extern void maybe_push_cleanup_level		(tree);
 extern tree pushtag				(tree, tree, tag_scope);
 extern tree make_anon_name			(void);
+extern tree make_lambda_name                    (void);
 extern tree pushdecl_top_level_maybe_friend	(tree, bool);
 extern tree pushdecl_top_level_and_finish	(tree, tree);
 extern tree check_for_out_of_scope_variable	(tree);
@@ -4879,6 +4956,13 @@ extern void finish_static_assert                (tree, tree, location_t,
 extern tree describable_type			(tree);
 extern tree finish_decltype_type                (tree, bool);
 extern tree finish_trait_expr			(enum cp_trait_kind, tree, tree);
+extern tree build_lambda_expr                   (void);
+extern tree begin_lambda_type                   (tree);
+extern void finish_lambda_function_body         (tree, tree);
+extern void deduce_lambda_return_type           (tree, tree);
+extern tree add_capture                         (tree, tree, tree, bool);
+extern tree add_default_capture                 (tree, tree, tree);
+extern tree lambda_expr_this_capture            (tree);
 
 /* in tree.c */
 extern tree force_target_expr			(tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index be1b5b7..488a2d5 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12784,6 +12784,7 @@ cp_tree_node_structure (union lang_tree_node * t)
     case STATIC_ASSERT:		return TS_CP_STATIC_ASSERT;
     case ARGUMENT_PACK_SELECT:  return TS_CP_ARGUMENT_PACK_SELECT;
     case TRAIT_EXPR:		return TS_CP_TRAIT_EXPR;
+    case LAMBDA_EXPR:		return TS_CP_LAMBDA_EXPR;
     default:			return TS_CP_GENERIC;
     }
 }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index c2d8779..858d2a0 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1843,6 +1843,22 @@ make_anon_name (void)
   return get_identifier (buf);
 }
 
+/* This code is practically identical to that for creating
+   anonymous names, but is just used for lambdas instead.  This is necessary
+   because anonymous names are recognized and cannot be passed to template
+   functions.  */
+
+static GTY(()) int lambda_cnt = 0;
+
+tree
+make_lambda_name (void)
+{
+  char buf[32];
+
+  sprintf (buf, LAMBDANAME_FORMAT, lambda_cnt++);
+  return get_identifier (buf);
+}
+
 /* Return (from the stack of) the BINDING, if any, established at SCOPE.  */
 
 static inline cxx_binding *
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e64d0bf..cc7c5f0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1626,6 +1626,14 @@ static tree cp_parser_constant_expression
   (cp_parser *, bool, bool *);
 static tree cp_parser_builtin_offsetof
   (cp_parser *);
+static tree cp_parser_lambda_expression
+  (cp_parser *);
+static void cp_parser_lambda_introducer
+  (cp_parser *, tree);
+static void cp_parser_lambda_parameter_declaration_opt
+  (cp_parser *, tree);
+static void cp_parser_lambda_body
+  (cp_parser *, tree);
 
 /* Statements [gram.stmt.stmt]  */
 
@@ -2450,6 +2458,7 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 {
   unsigned paren_depth = 0;
   unsigned brace_depth = 0;
+  unsigned square_depth = 0;
 
   if (recovering && !or_comma
       && cp_parser_uncommitted_to_tentative_parse_p (parser))
@@ -2466,6 +2475,15 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 	  /* If we've run out of tokens, then there is no closing `)'.  */
 	  return 0;
 
+        /* This is good for lambda expression capture-lists.  */
+        case CPP_OPEN_SQUARE:
+          ++square_depth;
+          break;
+        case CPP_CLOSE_SQUARE:
+          if (!square_depth--)
+            return 0;
+          break;
+
 	case CPP_SEMICOLON:
 	  /* This matches the processing in skip_to_end_of_statement.  */
 	  if (!brace_depth)
@@ -2481,7 +2499,7 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 	  break;
 
 	case CPP_COMMA:
-	  if (recovering && or_comma && !brace_depth && !paren_depth)
+	  if (recovering && or_comma && !brace_depth && !paren_depth && !square_depth)
 	    return -1;
 	  break;
 
@@ -3281,6 +3299,22 @@ cp_parser_primary_expression (cp_parser *parser,
 	return expr;
       }
 
+    case CPP_OPEN_SQUARE:
+      if (cxx_dialect == cxx0x)
+        return cp_parser_lambda_expression (parser);
+      else if (c_dialect_objc ())
+        /* We have an Objective-C++ message. */
+        return cp_parser_objc_expression (parser);
+      cp_parser_error (parser, "expected primary-expression");
+      return error_mark_node;
+
+    case CPP_OBJC_STRING:
+      if (c_dialect_objc ())
+      /* We have an Objective-C++ string literal. */
+        return cp_parser_objc_expression (parser);
+      cp_parser_error (parser, "expected primary-expression");
+      return error_mark_node;
+  
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
@@ -3538,13 +3572,6 @@ cp_parser_primary_expression (cp_parser *parser,
 
       /* Anything else is an error.  */
     default:
-      /* ...unless we have an Objective-C++ message or string literal,
-         that is.  */
-      if (c_dialect_objc ()
-	  && (token->type == CPP_OPEN_SQUARE
-              || token->type == CPP_OBJC_STRING))
-	return cp_parser_objc_expression (parser);
-
       cp_parser_error (parser, "expected primary-expression");
       return error_mark_node;
     }
@@ -6923,6 +6950,460 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
   return finish_trait_expr (kind, type1, type2);
 }
 
+/* Parse a lambda expression.
+
+   lambda-expression:
+     lambda-introducer lambda-parameter-declaration [opt] compound-statement
+
+   Returns a representation of the expression.  */
+
+static tree
+cp_parser_lambda_expression (cp_parser* parser)
+{
+  tree lambda_expr = build_lambda_expr ();
+  tree type;
+  tree expr;
+
+  cp_parser_lambda_introducer (parser, lambda_expr);
+
+  {
+    /* Inside the class, surrounding template-parameter-lists do not apply.  */
+    unsigned int saved_num_template_parameter_lists
+        = parser->num_template_parameter_lists;
+    /* We are not in a function body.  */
+    bool saved_in_function_body = parser->in_function_body;
+
+    parser->num_template_parameter_lists = 0;
+    parser->in_function_body = false;
+    /* Remember that we are defining one more class.  */
+    ++parser->num_classes_being_defined;
+
+    type = begin_lambda_type (lambda_expr);
+
+    cp_parser_lambda_parameter_declaration_opt (parser, lambda_expr);
+
+    type = finish_struct (type, /*attributes=*/NULL_TREE);
+
+    /* We want access to private members from anywhere within a member function,
+     * even in lambda expressions.  */
+    if (current_class_type)
+      make_friend_class (current_class_type, type, /*complain=*/false);
+
+    cp_parser_lambda_body (parser, lambda_expr);
+
+    /* Layout again to allow for members to have been added to the
+     * capture if it was a 'implicit capture' -- note that this would
+     * not be necessary for 'implicit reference capture' ([&]) if the
+     * stack-pointer variant was implemented, since the layout would
+     * be known.  I think it would still be required for 'implicit
+     * value capture' ([=]) though, since copies of the referenced
+     * identifiers are required.
+     *
+     * Is this doing something rude?  Without clearing the size node,
+     * a redefinition error occurs.  Maybe this is the accepted way of
+     * re-laying-out a type, but it is equally likely to be a
+     * gcc travesty.  */
+    TYPE_SIZE (type) = NULL_TREE;
+    finish_struct_1 (type);
+
+    parser->in_function_body = saved_in_function_body;
+    parser->num_template_parameter_lists = saved_num_template_parameter_lists;
+    --parser->num_classes_being_defined;
+  }
+
+  type = TREE_CHAIN (type);
+
+  {
+    /* Build aggregate constructor.
+     * - cp_parser_braced_list
+     * - cp_parser_functional_cast  */
+    VEC(constructor_elt,gc) *elts = NULL;
+    tree node;
+    for (node = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr);
+         node;
+         node = TREE_CHAIN (node))
+    {
+      CONSTRUCTOR_APPEND_ELT (
+          elts,
+          /*identifier=*/NULL_TREE,
+          TREE_VALUE (node));
+    }
+
+    expr = build_constructor (init_list_type_node, elts);
+    CONSTRUCTOR_IS_DIRECT_INIT (expr) = 1;
+  }
+
+  /* TREE_TYPE to remove TYPE_DECL wrapping  */
+  return finish_compound_literal (TREE_TYPE (type), expr);
+}
+
+/* Parse the beginning of a lambda expression.
+
+   lambda-introducer:
+     [ lambda-capture [opt] ]
+
+   LAMBDA_EXPR is the current representation of the lambda expression.  */
+
+static void
+cp_parser_lambda_introducer (cp_parser* parser,
+    tree lambda_expr)
+{
+  /* Need commas after the first capture.  */
+  bool first = true;
+
+  /* Eat the leading `['. */
+  cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
+
+  /* Record default capture mode. "[&" "[=" "[&," "[=," */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
+      && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_NAME)
+    LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE;
+  else if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+    LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY;
+
+  if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE)
+  {
+    cp_lexer_consume_token (parser->lexer);
+    if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+      cp_lexer_consume_token (parser->lexer);
+  }
+
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
+  {
+
+    cp_token* capture_token;
+    tree capture_id;
+    tree capture_init_expr;
+    cp_id_kind idk = CP_ID_KIND_NONE;
+
+    enum capture_kind_type {
+      BY_COPY,
+      BY_REFERENCE,
+      BY_RVALUE_REFERENCE
+    };
+    enum capture_kind_type capture_kind = BY_COPY;
+
+    if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+    {
+      error ("expected end of capture-list");
+      return;
+    }
+
+    if (first)
+      first = false;
+    else
+      cp_parser_require (parser, CPP_COMMA, "%<,%>");
+
+    /* Possibly capture `this'. */
+    if (cp_lexer_next_token_is_keyword (parser->lexer, RID_THIS))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      add_capture (
+          lambda_expr,
+          /*id=*/get_identifier ("__this"),
+          /*initializer=*/finish_this_expr(),
+          /*by_reference_p=*/false);
+      continue;
+    }
+
+    /* Remember whether we want to capture as a reference or not. */
+    if (cp_lexer_next_token_is (parser->lexer, CPP_AND))
+      capture_kind = BY_REFERENCE;
+    else if (cp_lexer_next_token_is (parser->lexer, CPP_AND_AND))
+      capture_kind = BY_RVALUE_REFERENCE;
+
+    if (capture_kind != BY_COPY)
+      cp_lexer_consume_token (parser->lexer);
+
+    /* Get the identifier. */
+    capture_token = cp_lexer_peek_token (parser->lexer);
+    capture_id = cp_parser_identifier (parser);
+
+    if (capture_id == error_mark_node)
+      /* Would be nice to have a cp_parser_skip_to_closing_x for general
+       * delimiters, but I modified this to stop on unnested ']' as well. It was
+       * already changed to stop on unnested '}', so the "closing_parenthesis"
+       * name is no more misleading with my change.  */
+      cp_parser_skip_to_closing_parenthesis (parser,
+          /*recovering=*/true,
+          /*or_comma=*/true,
+          /*consume_paren=*/true);
+
+    /* Find the initializer for this capture.  */
+    if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+    {
+      /* An explicit expression exists. */
+      cp_lexer_consume_token (parser->lexer);
+      capture_init_expr = cp_parser_assignment_expression (parser,
+							   /*cast_p=*/true,
+							   &idk);
+    }
+    else
+    {
+      const char* error_msg;
+
+      /* Turn the identifier into an id-expression. */
+      capture_init_expr = cp_parser_lookup_name (parser,
+          capture_id,
+          none_type,
+          /*is_template=*/false,
+          /*is_namespace=*/false,
+          /*check_dependency=*/true,
+          /*ambiguous_decls=*/NULL,
+          capture_token->location);
+
+      capture_init_expr = finish_id_expression (
+          capture_id,
+          capture_init_expr,
+          parser->scope,
+          &idk,
+          /*integral_constant_expression_p=*/false,
+          /*allow_non_integral_constant_expression_p=*/false,
+          /*non_integral_constant_expression_p=*/NULL,
+          /*template_p=*/false,
+          /*done=*/true,
+          /*address_p=*/false,
+          /*template_arg_p=*/false,
+          &error_msg,
+          capture_token->location);
+    }
+
+    add_capture (
+        lambda_expr,
+        capture_id,
+        capture_init_expr,
+        /*by_reference_p=*/capture_kind == BY_REFERENCE);
+
+  }
+
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+
+}
+
+/* Parse the (optional) middle of a lambda expression.
+
+   lambda-parameter-declaration:
+     ( lambda-parameter-declaration-list [opt] ) exception-specification [opt]
+       lambda-return-type-clause [opt]
+
+   LAMBDA_EXPR is the current representation of the lambda expression.  */
+
+static void
+cp_parser_lambda_parameter_declaration_opt (cp_parser* parser,
+    tree lambda_expr)
+{
+  tree param_list = NULL_TREE;
+  tree exception_spec = NULL_TREE;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+  {
+    cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+
+    /* Parse optional parameters.  */
+    if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+    {
+      bool is_error = false;
+
+      begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
+
+      param_list = cp_parser_parameter_declaration_list (parser, &is_error);
+      /* TODO: better way to handle this error?  */
+      if (is_error)
+        param_list = NULL_TREE;
+
+      /* Remove the function parms from scope.  */
+      {
+        tree t;
+        for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+          pop_binding (DECL_NAME (t), t);
+        leave_scope();
+      }
+
+    }
+
+    cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+
+    /* Parse optional mutable specification.  */
+    if (cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
+    }
+
+    /* Parse optional exception specification.  */
+    exception_spec = cp_parser_exception_specification_opt (parser);
+
+    /* Parse optional return type clause.  */
+    if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      LAMBDA_EXPR_RETURN_TYPE (lambda_expr) = cp_parser_type_id (parser);
+    }
+  }
+
+  /********************************************
+   * Start the function call operator
+   * - member_specification_opt
+   * + member_declaration
+   ********************************************/
+  {
+    bool saved_in_declarator_p = parser->in_declarator_p;
+    bool saved_default_arg_ok_p = parser->default_arg_ok_p;
+
+    cp_decl_specifier_seq return_type_specs;
+    cp_declarator* declarator;
+    tree fco;
+
+    parser->in_declarator_p = true;
+    parser->default_arg_ok_p = true;
+
+    clear_decl_specs (&return_type_specs);
+    if (LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
+    {
+      return_type_specs.type = LAMBDA_EXPR_RETURN_TYPE (lambda_expr);
+      /* TODO: is this necessary?  */
+      return_type_specs.any_specifiers_p = true;
+      /* TODO: do we need cp_parser_set_decl_spec_type()?  */
+    }
+    else
+    {
+      /* 5.1.1.9.2 of the standard says:
+       *   for a lambda expression that does not contain a
+       *   lambda-return-type-clause, the return type is void, unless the
+       *   compound-statement is of the form { return expression ; }  */
+      /* Will find out later what the form is, but can use void as a placeholder
+       * return type anyways.  */
+      return_type_specs.type = void_type_node;
+    }
+
+    declarator = make_id_declarator (
+        parser->scope,
+        ansi_opname (CALL_EXPR),
+        sfk_none);
+
+    declarator = make_call_declarator (
+        declarator,
+        param_list,
+        /*cv_qualifiers=*/(LAMBDA_EXPR_MUTABLE_P (lambda_expr) ?
+           (TYPE_UNQUALIFIED) :
+           (TYPE_QUAL_CONST)),
+        exception_spec,
+        /*late_return_type=*/NULL_TREE);
+
+    parser->in_declarator_p = saved_in_declarator_p;
+    parser->default_arg_ok_p = saved_default_arg_ok_p;
+
+    /* operator() is public */
+    current_access_specifier = access_public_node;
+
+    /* fco = function call operator */
+    /* TODO: look into start_function  */
+    fco = start_method (
+        &return_type_specs,
+        declarator,
+        /*attributes=*/NULL_TREE);
+    DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
+    finish_method (fco);
+
+    finish_member_declaration (fco);
+
+    LAMBDA_EXPR_FUNCTION (lambda_expr) = fco;
+
+  }
+
+}
+
+/* Parse the body of a lambda expression, which is simply
+
+   compound-statement
+
+   but which requires special handling.
+   LAMBDA_EXPR is the current representation of the lambda expression.  */
+
+static void
+cp_parser_lambda_body (cp_parser* parser,
+    tree lambda_expr)
+{
+  /* start_* / finish_* functions don't do any state preservation
+   * (finish_function sets current_function_decl to NULL), so we have to.  */
+  /*struct function* saved_cfun = cfun;*/
+  /* TODO: do we need these? from function.h */
+  tree saved_function_decl = current_function_decl;
+  int saved_unevaluated_operand = cp_unevaluated_operand;
+  int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+  push_function_context();
+
+  /********************************************
+   * Finish the function call operator
+   * - class_specifier
+   * + late_parsing_for_member
+   * + function_definition_after_declarator
+   * + ctor_initializer_opt_and_function_body
+   ********************************************/
+  {
+    tree fco = LAMBDA_EXPR_FUNCTION (lambda_expr);
+    tree body;
+
+    /* Let the front end know that we are going to be defining this
+       function. */
+    start_preparsed_function (
+        fco,
+        NULL_TREE,
+        SF_PRE_PARSED | SF_INCLASS_INLINE);
+
+    body = begin_function_body ();
+
+    /* 5.1.1.9.2 of the standard says:
+     *   for a lambda expression that does not contain a
+     *   lambda-return-type-clause, the return type is void, unless the
+     *   compound-statement is of the form { return expression ; }  */
+    /* In a lambda that has neither a lambda-return-type-clause
+     * nor a deducible form, errors should be reported for return statements
+     * in the body.  Since we used void as the placeholder return type, parsing
+     * the body as usual will give such desired behavior.  */
+    if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr)
+        && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)
+        && cp_lexer_peek_nth_token (parser->lexer, 2)->keyword == RID_RETURN
+        && cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_SEMICOLON)
+    {
+      tree compound_stmt;
+      tree expr = NULL_TREE;
+      cp_id_kind idk = CP_ID_KIND_NONE;
+     
+      cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+      compound_stmt = begin_compound_stmt (0);
+
+      cp_parser_require_keyword (parser, RID_RETURN, "%<return%>");
+
+      expr = cp_parser_expression (parser, /*cast_p=*/false, &idk);
+      deduce_lambda_return_type (lambda_expr, expr);
+      /* Will get error here if type not deduced yet.  */
+      finish_return_stmt (expr);
+
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+      finish_compound_stmt (compound_stmt);
+
+    } else {
+      /* TODO: does begin_compound_stmt want BCS_FN_BODY?
+       * cp_parser_compound_stmt does not pass it. */
+      cp_parser_function_body (parser);
+    }
+
+    finish_lambda_function_body (lambda_expr, body);
+
+  }
+
+  /*set_cfun (saved_cfun);*/
+  pop_function_context();
+  current_function_decl = saved_function_decl;
+  cp_unevaluated_operand = saved_unevaluated_operand;
+  c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
+
+}
+
+
 /* Statements [gram.stmt.stmt]  */
 
 /* Parse a statement.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 23db832..48ad19c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1444,6 +1444,20 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
       return error_mark_node;
     }
+
+  /* If decl is a field, object has a lambda type, and decl is not a member of
+   * that type, then we must get to decl through the 'this' capture of the
+   * object.  If decl is not a member of that object, either, then its access
+   * will still fail later.  */
+  if (LAMBDA_TYPE_P (TREE_TYPE (object))
+      && !same_type_ignoring_top_level_qualifiers_p(DECL_CONTEXT (decl), TREE_TYPE (object)))
+    /* TODO: if the lambda does not capture 'this', but has default capture,
+     * then we need to add it late.  */
+    object = cp_build_indirect_ref (
+        lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (object))),
+        /*errorstring=*/"",
+        /*complain=*/tf_warning_or_error);
+
   if (current_class_ptr)
     TREE_USED (current_class_ptr) = 1;
   if (processing_template_decl && !qualifying_scope)
@@ -2048,7 +2062,13 @@ finish_this_expr (void)
 
   if (current_class_ptr)
     {
+      tree type = TREE_TYPE (current_class_ref);
+
       result = current_class_ptr;
+      /* In a lambda expression, 'this' refers to the captured 'this'.  */
+      if (LAMBDA_TYPE_P (type))
+        result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type));
+
     }
   else if (current_function_decl
 	   && DECL_STATIC_FUNCTION_P (current_function_decl))
@@ -2720,11 +2740,45 @@ finish_id_expression (tree id_expression,
 	  if (context != NULL_TREE && context != current_function_decl
 	      && ! TREE_STATIC (decl))
 	    {
-	      error (TREE_CODE (decl) == VAR_DECL
-		     ? "use of %<auto%> variable from containing function"
-		     : "use of parameter from containing function");
-	      error ("  %q+#D declared here", decl);
-	      return error_mark_node;
+              tree containing_function = current_function_decl;
+              tree lambda_stack = NULL_TREE;
+
+              /* If we are in a lambda function, we can move out until we hit:
+               *   1. the context
+               *   2. a non-lambda function
+               *   3. a non-default capturing lambda function  */
+              while (context != containing_function
+                     && LAMBDA_FUNCTION_P (containing_function))
+              {
+                tree lambda_expr =
+                  CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function));
+
+                if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE)
+                  break;
+
+                lambda_stack = tree_cons (
+                    NULL_TREE,
+                    lambda_expr,
+                    lambda_stack);
+
+                containing_function = decl_function_context (containing_function);
+              }
+
+              if (context == containing_function)
+              {
+                decl = add_default_capture (
+                    lambda_stack,
+                    /*id=*/DECL_NAME (decl),
+                    /*initializer=*/decl);
+              }
+              else
+              {
+                error (TREE_CODE (decl) == VAR_DECL
+                       ? "use of %<auto%> variable from containing function"
+                       : "use of parameter from containing function");
+                error ("  %q+#D declared here", decl);
+                return error_mark_node;
+              }
 	    }
 	}
     }
@@ -5105,4 +5159,312 @@ float_const_decimal64_p (void)
   return 0;
 }
 
+/* Constructor for a lambda expression.  */
+
+tree
+build_lambda_expr (void)
+{
+  tree lambda = make_node (LAMBDA_EXPR);
+  LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) = CPLD_NONE;
+  LAMBDA_EXPR_CAPTURE_LIST         (lambda) = NULL_TREE;
+  LAMBDA_EXPR_THIS_CAPTURE         (lambda) = NULL_TREE;
+  LAMBDA_EXPR_RETURN_TYPE          (lambda) = NULL_TREE;
+  LAMBDA_EXPR_MUTABLE_P            (lambda) = false;
+  LAMBDA_EXPR_FUNCTION             (lambda) = NULL_TREE;
+  return lambda;
+}
+
+/* Return an initialized RECORD_TYPE for LAMBDA.
+ * LAMBDA must have its explicit captures already.  */
+
+tree
+begin_lambda_type (tree lambda)
+{
+  tree name;
+  tree type;
+  tree node;
+
+  /* TODO: necessary?  */
+  push_deferring_access_checks (dk_no_deferred);
+
+  /* Unique name. This is just like an unnamed class, but we cannot use
+   * make_anon_name because of certain checks against TYPE_ANONYMOUS_P.  */
+  name = make_lambda_name ();
+
+  /* Create the new RECORD_TYPE for this lambda.  */
+  type = xref_tag (
+      /*tag_code=*/record_type,
+      /*name=*/name,
+      /*scope=*/ts_current,
+      /*template_header_p=*/false);
+
+  /* Designate it as a struct so that we can use aggregate initialization.  */
+  CLASSTYPE_DECLARED_CLASS (type) = false;
+
+  /* Clear base types.  */
+  xref_basetypes (type, /*bases=*/NULL_TREE);
+
+  /* Start the class.  */
+  type = begin_class_definition (type, /*attributes=*/NULL_TREE);
+
+  /* Cross-reference the expression and the type.  */
+  TREE_TYPE (lambda) = type;
+  CLASSTYPE_LAMBDA_EXPR (type) = lambda;
+
+  /* Members are public (for finish_member_declaration) so that we can use
+   * aggregate initialization.  */
+  current_access_specifier = access_public_node;
+
+  /* For each capture, we need to add the member to the class.  */
+  for (node = LAMBDA_EXPR_CAPTURE_LIST (lambda);
+       node;
+       node = TREE_CHAIN (node))
+  {
+    tree member = TREE_PURPOSE (node);
+
+    /* Add to class.  */
+    finish_member_declaration (member);
+  }
+
+  return type;
+}
+
+/* Take a BODY generated by begin_function_body, and add the finishing
+ * touches. This is mainly a wrapper around finish_function_body and code
+ * generation, with lambda-specific extras like return type deduction.  */
+
+void
+finish_lambda_function_body (tree lambda, tree body)
+{
+  /* Recalculate offsets in case we had default captures.  */
+  tree dummy = NULL_TREE;
+  layout_class_type (TREE_TYPE (lambda), /*virtuals_p=*/&dummy);
+  gcc_assert (dummy == NULL_TREE);
+
+  finish_function_body (body);
+
+  {
+    /* Finish the function and generate code for it if necessary. */
+    /* 2 == inline_p */
+    tree fn = finish_function (2);
+    expand_or_defer_fn (fn);
+  }
+
+}
+
+/* Recompute the return type for LAMBDA with body of the form:
+     { return EXPR ; }  */
+
+void
+deduce_lambda_return_type (tree lambda, tree expr)
+{
+  tree fco = LAMBDA_EXPR_FUNCTION (lambda);
+  tree return_type;
+  tree result;
+
+  return_type = finish_decltype_type (
+      expr,
+      /*id_expression_or_member_access_p=*/false);
+
+  /********************************************
+   * Set the DECL_RESULT
+   * - start_preparsed_function
+   * + allocate_struct_function
+   ********************************************/
+  result = build_decl (
+      input_location,
+      RESULT_DECL,
+      /*name=*/0,
+      TYPE_MAIN_VARIANT (return_type));
+  /* TODO: are these necessary? */
+  DECL_ARTIFICIAL (result) = 1;
+  DECL_IGNORED_P (result) = 1;
+  cp_apply_type_quals_to_decl (
+      cp_type_quals (return_type),
+      result);
+
+  DECL_RESULT (fco) = result;
+  /* TREE_TYPE (FUNCTION_DECL) == METHOD_TYPE
+     TREE_TYPE (METHOD_TYPE)   == return-type */
+  TREE_TYPE (TREE_TYPE (fco)) = return_type;
+
+  if (!processing_template_decl && aggregate_value_p (result, fco))
+  {
+#ifdef PCC_STATIC_STRUCT_RETURN
+    cfun->returns_pcc_struct = 1;
+#endif
+    cfun->returns_struct = 1;
+  }
+
+}
+
+/* From an ID and INITIALIZER, create a capture (by reference if
+ * BY_REFERENCE_P is true), add it to the capture-list for LAMBDA,
+ * and return it.  */
+
+tree
+add_capture (tree lambda, tree id, tree initializer, bool by_reference_p)
+{
+  tree type;
+  tree member;
+
+  type = finish_decltype_type (
+      initializer,
+      /*id_expression_or_member_access_p=*/false);
+
+  if (by_reference_p)
+  {
+    if (TREE_CODE (type) != REFERENCE_TYPE)
+      error ("cannot capture %qE by reference", initializer);
+  }
+  else
+  {
+    /* May come as a reference, so strip it down if desired. */
+    type = non_reference (type);
+  }
+
+  /* Make member variable.  */
+  member = build_lang_decl (
+      FIELD_DECL,
+      id,
+      type);
+
+  LAMBDA_EXPR_CAPTURE_LIST (lambda) = tree_cons (
+      member,
+      initializer,
+      LAMBDA_EXPR_CAPTURE_LIST (lambda));
+
+  if (id == get_identifier ("__this"))
+  {
+    if (LAMBDA_EXPR_CAPTURES_THIS_P (lambda))
+      error ("already captured %<this%> in lambda expression");
+    LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
+  }
+
+  return member;
+
+}
+
+/* Similar to add_capture, except this works on a stack of nested lambdas.
+ * BY_REFERENCE_P in this case is derived from the default capture mode.
+ * Returns the capture for the lambda at the bottom of the stack.  */
+
+tree
+add_default_capture (tree lambda_stack, tree id, tree initializer)
+{
+  bool this_capture_p = (id == get_identifier ("__this"));
+
+  tree member = NULL_TREE;
+
+  tree saved_class_type = current_class_type;
+  tree saved_access_specifier = current_access_specifier;
+
+  tree node;
+
+  current_access_specifier = access_public_node;
+
+  for (node = lambda_stack;
+       node;
+       node = TREE_CHAIN (node))
+  {
+    tree lambda = TREE_VALUE (node);
+
+    member = add_capture (
+        lambda,
+        id,
+        initializer,
+        /*by_reference_p=*/
+        (!this_capture_p
+         && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_REFERENCE));
+
+    /* Push class being defined.  */
+    current_class_type = TREE_TYPE (lambda);
+    TYPE_BEING_DEFINED (current_class_type) = 1;
+
+    /* Add member.  */
+    finish_member_declaration (member);
+
+    /* Pop class being defined.  */
+    TYPE_BEING_DEFINED (current_class_type) = 0;
+
+    initializer = member;
+
+  }
+
+  current_class_type = saved_class_type;
+  current_access_specifier = saved_access_specifier;
+
+  return member;
+
+}
+
+/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an
+ * INDIRECT_REF, possibly adding it through default capturing.  */
+
+tree
+lambda_expr_this_capture (tree lambda)
+{
+  tree result;
+
+  tree this_capture = LAMBDA_EXPR_THIS_CAPTURE (lambda);
+
+  /* Try to default capture 'this' if we can.  */
+  if (!this_capture
+      && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
+  {
+    tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda));
+    tree lambda_stack = tree_cons (
+        NULL_TREE,
+        lambda,
+        NULL_TREE);
+
+    /* If we are in a lambda function, we can move out until we hit:
+     *   1. a non-lambda function
+     *   2. a lambda function capturing 'this'
+     *   3. a non-default capturing lambda function  */
+    while (LAMBDA_FUNCTION_P (containing_function))
+    {
+      tree lambda =
+        CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function));
+
+      if (LAMBDA_EXPR_THIS_CAPTURE (lambda)
+          || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_NONE)
+        break;
+
+      lambda_stack = tree_cons (
+          NULL_TREE,
+          lambda,
+          lambda_stack);
+
+      containing_function = decl_function_context (containing_function);
+    }
+
+    if (DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function))
+    {
+      this_capture = add_default_capture (
+          lambda_stack,
+          /*id=*/get_identifier ("__this"),
+          /* First parameter is 'this'.  */
+          /*initializer=*/DECL_ARGUMENTS (containing_function));
+    }
+
+  }
+
+  if (!this_capture)
+  {
+    error ("%<this%> was not captured for this lambda function");
+    result = error_mark_node;
+  }
+  else
+  {
+    result = finish_non_static_data_member (
+        this_capture,
+        current_class_ref,
+        /*qualifying_scope=*/NULL_TREE);
+  }
+
+  return result;
+
+}
+
 #include "gt-cp-semantics.h"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9e194fc..94a2f16 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1522,7 +1522,10 @@ no_linkage_check (tree t, bool relaxed_p)
 
   switch (TREE_CODE (t))
     {
+      /*
+      TODO: fix no linkage check on lambda functions properly
       tree fn;
+      */
 
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
@@ -1535,9 +1538,12 @@ no_linkage_check (tree t, bool relaxed_p)
     case ENUMERAL_TYPE:
       if (TYPE_ANONYMOUS_P (t))
 	return t;
+      /*
+      TODO: fix no linkage check on lambda functions properly
       fn = decl_function_context (TYPE_MAIN_DECL (t));
       if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
 	return t;
+      */
       return NULL_TREE;
 
     case ARRAY_TYPE:
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref-neg.C
new file mode 100644
index 0000000..7d1a1bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref-neg.C
@@ -0,0 +1,14 @@
+// { dg-options "-std=c++0x" }
+#include <cassert>
+
+int main() {
+  int i = 1, j = 2;
+  const int& ci = i;
+  [&ci, &j] () -> void { j = ci; } ();
+  assert(i == 1);
+  assert(j == 1);
+  [&ci] () -> void { ci = 0; } (); // { dg-error "" "cannot assign to const int&" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref.C
new file mode 100644
index 0000000..f9cb2d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-const-ref.C
@@ -0,0 +1,15 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+#include <cassert>
+
+int main() {
+  int i = 1, j = 2;
+  const int& ci = i;
+  [&ci, &j] () -> void { j = ci; } ();
+  assert(i == 1);
+  assert(j == 1);
+  //[&ci] () -> void { ci = 0; } (); { dg-error: cannot assign to const int& }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-neg.C
new file mode 100644
index 0000000..f48c6c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-neg.C
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+template<typename F>
+void call(const F& f) { f(); }	// { dg-error "discards qualifiers" }
+
+int main() {
+  call([] () -> void {});
+  call([] () mutable -> void {}); // { dg-message "" "`f' does not have const `operator()'" }
+
+  int i = -1;
+  call([&i] () -> void { i = 0; });
+  assert(i == 0);
+  call([i] () -> void { i = 0; }); // { dg-error "" "assignment to non-reference capture in const lambda" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const.C
new file mode 100644
index 0000000..5bceb92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const.C
@@ -0,0 +1,20 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+template<typename F>
+void call(const F& f) { f(); }
+
+int main() {
+  call([] () -> void {});
+  //call([] () mutable -> void {}); // { dg-error: "`f' does not have const `operator()'" }
+
+  int i = -1;
+  call([&i] () -> void { i = 0; });
+  assert(i == 0);
+  //call([i] () -> void { i = 0; }); // { dg-error: "assignment to non-reference capture in const lambda" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default-neg.C
new file mode 100644
index 0000000..0b6313b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default-neg.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+
+int main() {
+  int i;			// { dg-error "declared here" }
+  const char* s;
+  [=] () -> void { i; s; i; s; } ();
+
+  [] () -> void { i; } (); // { dg-error "" "`i' is not captured" }
+  [1] () -> void {} (); // { dg-error "expected identifier" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default.C
new file mode 100644
index 0000000..4d4faea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-default.C
@@ -0,0 +1,14 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+int main() {
+  int i;
+  const char* s;
+  [=] () -> void { i; s; i; s; } ();
+
+  //[] () -> void { i; } (); // { dg-error: "`i' is not in scope" }
+  //[1] () -> void {} (); // { dg-error: "expected identifier" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-neg.C
new file mode 100644
index 0000000..d990ee3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy-neg.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+
+int main() {
+  int i;			// { dg-error "declared here" }
+  const char* s;
+  [i, s] () -> void { i; s; } ();
+
+  [] () -> void { i; } (); // { dg-error "" "`i' is not captured" }
+  [1] () -> void {} (); // { dg-error "expected identifier" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy.C
new file mode 100644
index 0000000..d57a01d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-copy.C
@@ -0,0 +1,14 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+int main() {
+  int i;
+  const char* s;
+  [i, s] () -> void { i; s; } ();
+
+  //[] () -> void { i; } (); // { dg-error: "`i' is not in scope" }
+  //[1] () -> void {} (); // { dg-error: "expected identifier" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce.C
new file mode 100644
index 0000000..d173210
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce.C
@@ -0,0 +1,24 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+#include <cassert>
+
+int main() {
+  [] {};
+  [] {} ();
+  [] () {};
+  [] () {} ();
+  [] () { return "lambda"; };
+
+  int i = 1, j = 2;
+  [&i, j] () { i = j; } ();
+  assert(i == 2);
+  assert(j == 2);
+
+  i = [] () { return 3; } ();
+  assert(i == 3);
+
+  []{ return; };
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C
new file mode 100644
index 0000000..a93857e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class-neg.C
@@ -0,0 +1,35 @@
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+class C {
+  private:
+    int m_i;
+
+  public:
+    C() : m_i(-1) {
+      [] { this; } ();		// { dg-error "not captured" }
+      [this] () -> void { m_i = 0; } ();
+      assert(m_i == 0);
+      [this] () -> void { this->m_i = 1; } ();
+      assert(m_i == 1);
+      [&] () -> void { m_i = 2; } ();
+      assert(m_i == 2);
+      [&] () -> void { this->m_i = 3; } ();
+      assert(m_i == 3);
+      [=] () -> void { m_i = 4; } (); // copies 'this' or --copies-m_i--?
+      assert(m_i == 4);
+      [=] () -> void { this->m_i = 5; } ();
+      assert(m_i == 5);
+    }
+
+};
+
+int main() {
+  C c;
+
+  [this] () -> void {} (); // { dg-error "use of 'this' in non-member function" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C
new file mode 100644
index 0000000..54015fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-in-class.C
@@ -0,0 +1,36 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+class C {
+  private:
+    int m_i;
+
+  public:
+    C() : m_i(-1) {
+      //[] { this; } ();
+      [this] () -> void { m_i = 0; } ();
+      assert(m_i == 0);
+      [this] () -> void { this->m_i = 1; } ();
+      assert(m_i == 1);
+      [&] () -> void { m_i = 2; } ();
+      assert(m_i == 2);
+      [&] () -> void { this->m_i = 3; } ();
+      assert(m_i == 3);
+      [=] () -> void { m_i = 4; } (); // copies 'this' or --copies-m_i--?
+      assert(m_i == 4);
+      [=] () -> void { this->m_i = 5; } ();
+      assert(m_i == 5);
+    }
+
+};
+
+int main() {
+  C c;
+
+  //[this] () -> void {} (); // { dg-error: "cannot capture `this' outside of class method" }
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mixed.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mixed.C
new file mode 100644
index 0000000..14c4de9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mixed.C
@@ -0,0 +1,13 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+#include <cassert>
+
+int main() {
+  int i = 1, j = 2;
+  [&i, j] () mutable -> void { i = 0; j = 0; } ();
+  assert(i == 0);
+  assert(j == 2);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable.C
new file mode 100644
index 0000000..7065dfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable.C
@@ -0,0 +1,16 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+#include <cassert>
+
+int main() {
+  int i = 1;
+  const char* s1 = "hello";
+  const char* s2 = s1;
+  [i, s2] () mutable -> void { i = 2; s2 = "world"; } ();
+  //[i, s2] () -> void { i = 2; s2 = "world"; } (); // { dg-error: "assignment of data-member in read-only structure" }
+  assert(i == 1);
+  assert(s1 == s2);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
new file mode 100644
index 0000000..1689865
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested.C
@@ -0,0 +1,52 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+int main() {
+  int i = 1;
+
+  [] (int& i) -> void {
+    [&] () -> void {
+      i = 2;
+    } ();
+  } (i);
+
+  assert(i == 2);
+
+  [&] () -> void {
+    [&i] () -> void {
+      i = 3;
+    } ();
+  } ();
+
+  assert(i == 3);
+
+  [&] () -> void {
+    [&] () -> void {
+      i = 4;
+    } ();
+  } ();
+
+  assert(i == 4);
+  i = 4;
+
+  [&] () -> void {
+    [=] () mutable -> void {
+      i = 5;
+    } ();
+  } ();
+
+  assert(i == 4);
+
+  [=] () mutable -> void {
+    [&] () -> void {
+      i = 6;
+    } ();
+  } ();
+
+  assert(i == 4);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-const.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-const.C
new file mode 100644
index 0000000..9c2b119
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-non-const.C
@@ -0,0 +1,19 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+template<typename F>
+void call(F f) { f(); }
+
+int main() {
+  call([] () -> void {});
+  call([] () mutable -> void {});
+
+  int i = -1;
+  call([i] () mutable -> void { i = 0; });
+  assert(i == -1);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nop.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nop.C
new file mode 100644
index 0000000..b366ba1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nop.C
@@ -0,0 +1,19 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+#include <cassert>
+
+int main() {
+  int i = 1, j = 2;
+  [i, j] () -> void {} ();
+  assert(i == 1);
+  assert(j == 2);
+  [&i, &j] () -> void {} ();
+  assert(i == 1);
+  assert(j == 2);
+  [] (int x) -> void {} (1);
+  [] (int& x) -> void {} (i);
+  [] (int x, int y) -> void {} (i, j);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-pass.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-pass.C
new file mode 100644
index 0000000..a42de29
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-pass.C
@@ -0,0 +1,27 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+#include <algorithm>
+
+template <typename F, typename A1>
+void call(F f, const A1& arg1) {
+  f(arg1);
+}
+
+int main() {
+  int i = 1;
+  call(
+      [&i] (int j) -> void { i = j; },
+      2
+  );
+  assert(i == 2);
+
+  int A[] = {1, 2, 3, 4};
+  int sum = 0;
+  std::for_each(A, A+4, [&sum] (int n) -> void { sum += n; });
+  assert(sum == 10);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-recursive.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-recursive.C
new file mode 100644
index 0000000..c3c8008
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-recursive.C
@@ -0,0 +1,21 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+//#include <iostream>
+#include <functional>
+#include <cassert>
+
+int main() {
+
+  std::function<int(int)> fib = [&fib] (int n) -> int {
+    //std::cerr << "fib(" << n << ")\n";
+    if (n <= 2) return 1;
+    else        return fib(n-1) + fib(n-2);
+  };
+
+  assert(fib(5) == 5);
+  assert(fib(10) == 55);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref-default.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref-default.C
new file mode 100644
index 0000000..342e0ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref-default.C
@@ -0,0 +1,15 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+int main() {
+  int i = 1;
+  float j = 2.0;
+  [&] () -> void { i = 3; j = 4.0; } ();
+  assert(i == 3);
+  assert(j == 4.0);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref.C
new file mode 100644
index 0000000..34ba263
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ref.C
@@ -0,0 +1,15 @@
+// { dg-do "run" }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+int main() {
+  int i = 1;
+  float j = 2.0;
+  [&i, &j] () -> void { i = 3; j = 4.0; } ();
+  assert(i == 3);
+  assert(j == 4.0);
+
+  return 0;
+}
+
-- 
1.5.6.GIT


[-- Attachment #3: 0002-First-pass-polymorphic-lambda-support.-This-version.patch --]
[-- Type: application/octet-stream, Size: 4420 bytes --]

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


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-07-29 10:27 ` Adam Butcher
  2009-07-29 14:17   ` Ed Smith-Rowland
@ 2009-08-03 18:31   ` Jason Merrill
  2009-08-04  2:25     ` Adam Butcher
  1 sibling, 1 reply; 24+ messages in thread
From: Jason Merrill @ 2009-08-03 18:31 UTC (permalink / raw)
  To: adam.butcher; +Cc: Esben Mose Hansen, gcc

On 07/29/2009 06:27 AM, Adam Butcher wrote:
> Esben Mose Hansen writes:

>> I am completely new to gcc hacking, just
>> dying to get lambda into gcc 4.5 :)

> Me too on both counts!

Great!  Please feel free to ask me any questions you have directly.  Do 
you have copyright assignments on file yet?  I'll go ahead and merge the 
current trunk into the branch.

> Looking at the implementation in gcc/cp/{class.c,parser.c,semantics.c} it seems that, in implicit capture mode,
> references to enclosing scope identifiers are retrospectively added to the lambda class on first use in the lambda
> body.  This made me worry about the class structure changing as you progress through the parse of the lambda body.
> I.e. at the start of the body nothing is captured -- since nothing is referenced.  As you meet enclosing scope
> references, each is added as a capture member to the lambda class.  Is this okay or has something already decided on
> the size and structure of the class?

That should be OK; recent changes to the specification 
(http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2859.pdf) have 
clarified that parsing the lambda body doesn't depend on the current 
contents of the class: we parse the body, noting things that we need to 
capture, then later rewrite the body to access captured variables 
through the class.

> I figured (almost certainly naively and incorrectly) that it ought to be similar
> to the difference between:
>
>     struct X
>     {
>        int i;
>        void init_i() { i = 1; }
>     };
>
> and
>
>     struct X
>     {
>        void init_i() { i = 1; }
>        int i;
>     };

Not exactly; in the X example we don't parse the body of init_i until 
after the closing brace of X.  For a lambda we parse the body 
immediately, then build up the class appropriately, then rewrite the 
body of the function.

> +    /* relayout again -- to allow for implicit
> +     * parameters to have been added to the capture if it was a
> +     * 'default capture' -- note that this would not be necessary if
> +     * the stack-pointer variant was implemented -- since the layout
> +     * would be known.
> +     * Relayingout here might have nasty effect if one were to query
> +     * sizeof *this from within the body -- would that even be
> +     * possible -- *this would refer to the lambda or the enclosing
> +     * class instance -- if there was one.???
> +     *
> +     * NOTE: I think this is a redefinition error; I'm just faking that
> +     * it isn't by clearing the size node... need to use stack pointer
> +     * method.  But that will likely bring its own issues -- not with
> +     * class layout though.
> +     */
> +    TYPE_SIZE (type) = NULL_TREE;
> +    finish_struct_1 (type);

Something like this definitely seems necessary; for a lambda with 
implicit capture, we can't know the size of the class until we're done 
with the body.

> The way 'default reference capture' is implemented on the lambda branch seems to be kind of reactive.  I would expect
> that inheriting the stack somehow (maybe using just a stack pointer) would be better but without more investigation I
> don't know if that is possible or how one would go about doing it.

That should be possible, but seems more complicated than just capturing 
the variables individually.  We'd need to add some new generic tree 
codes meaning "give me the address of this stack frame" and "give me the 
address of this variable in this stack frame" for the front end to use 
in rewriting the lambda body.

Jason

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-07-29 10:27 ` Adam Butcher
@ 2009-07-29 14:17   ` Ed Smith-Rowland
  2009-08-03 18:31   ` Jason Merrill
  1 sibling, 0 replies; 24+ messages in thread
From: Ed Smith-Rowland @ 2009-07-29 14:17 UTC (permalink / raw)
  To: adam.butcher; +Cc: Esben Mose Hansen, gcc

Adam Butcher wrote:
> Hi
>
> Esben Mose Hansen writes:
>   
>> this program SEGFAULTs
>>
>> #include <algorithm>
>>
>> int main() {
>>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>>   int sum = 0;
>>   int f = 5;
>>   std::for_each(&numbers[0], &numbers[nn],  [&]  (int n)  {
>>     sum += n * f;
>>   });
>>
>> }
>> ...
>> I am completely new to gcc hacking, just
>> dying to get lambda into gcc 4.5 :)
>>
>>     
> Me to on both counts!  So much so that I've got a working copy of the latest lambda branch, svnmerged the latest 4.5.0
> trunk into it, fixed a few build issues and started poking around.  I have never ventured into gcc internals before so
> its all a bit alien at the mo.
>
>   
>> On Thursday 30 April 2009 19:19:31 Ian wrote:
>>     
>>> When I try to specify the capture it works ((&sum, &f) works too but f is
>>> const):
>>>
>>> #include <algorithm>
>>>
>>> int
>>> main(void)
>>> {
>>>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>>>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>>>   int sum = 0;
>>>   int f = 5;
>>>
>>>   //std::for_each(&numbers[0], &numbers[nn], [&](int n) { sum += n * f; });
>>>
>>>   std::for_each(&numbers[0], &numbers[nn], [&sum, f](int n) { sum += n * f;
>>> });
>>>
>>>   return 0;
>>> }
>>>       
>>  Yup. In fact, almost any other capture block than the [&] works :) I will try
>>  to look at those tree options when I get sober again.
>>
>>     
> It is crashing when invoking a copied 'implicit capture' lambda.  The same occurs with:
>
>   int main()
>   {
>      char i,j,k;
>      auto const& f = [&] { i = 1; j = 2; k = 3; };
>      auto g = f;
>      g();
>      return i+j+k;
>   }
>
> With explicit captures (i.e. specifying [&i,&j,&k] instead of [&] above) it works fine.  Also using f() (in place of
> g()) is fine so the code in the lambda and the call to it must be okay.  So I started looking into the instance data.
>
> The resulting lambda class in the above program is generated by the compiler to look something like the following in
> name and structure:
>
>    struct __lambda0
>    {
>       char &i,&j,&k;
>       void operator() () const
>       {
>          i = 1; j = 2; k = 3;
>       }
>    };
>
> Looking at the implementation in gcc/cp/{class.c,parser.c,semantics.c} it seems that, in implicit capture mode,
> references to enclosing scope identifiers are retrospectively added to the lambda class on first use in the lambda
> body.  This made me worry about the class structure changing as you progress through the parse of the lambda body. 
> I.e. at the start of the body nothing is captured -- since nothing is referenced.  As you meet enclosing scope
> references, each is added as a capture member to the lambda class.  Is this okay or has something already decided on
> the size and structure of the class?  I figured (almost certainly naively and incorrectly) that it ought to be similar
> to the difference between:
>
>    struct X
>    {
>       int i;
>       void init_i() { i = 1; }
>    };
>
> and
>
>    struct X
>    {
>       void init_i() { i = 1; }
>       int i;
>    };
>
> I changed the program above to check the sizes of the generated lambda class and it is indeed as expected (three
> pointers). So the class has the correct size -- why does it not copy?  Surely a bitwise copy in this case is
> sufficient and that ought to be auto-generated.  -- Except we're in compiler land here -- are we supposed to do the
> auto-generating?  To test the theory I added
>
>      memcpy(&g,&f,sizeof g);
>
> after the assignment (auto g = f) to force the instance data to be copied from f to g.  It worked!  So why is the
> compiler not generating suitable code for the lambda class copy -- the size is right, but no copy of instance data is
> made -- maybe its already decided that the size is zero (as it was before the lambda body) and generated 'do-nothing'
> copy constructors?
>
> I had a poke around in gcc/cp/{class.c,parser.c,semantics.c} and believe I have worked around the issue -- the proper
> solution I don't think is as straight-forward (or maybe its more straight-forward for a gcc guru?).
>
> Note that the following diff hunk is after an svnmerge of trunk commits into my wc of the lambda branch so offsets
> will likely be wrong.  I would give a full diff but my wc is in rather a messy state at the mo.  I have no idea
> whether there are any nasty side effects to doing this but it seems to do the copy correctly afterwards.  I have not
> looked into it much further at the mo.  Thought I'd just post my findings.
>
> ########### snip ##########################
> --- gcc/cp/parser.c	(revision 150148)
> +++ gcc/cp/parser.c	(working copy)
> @@ -6936,6 +6991,24 @@
>
>      cp_parser_lambda_body (parser, lambda_expr);
>
> +    /* relayout again -- to allow for implicit
> +     * parameters to have been added to the capture if it was a
> +     * 'default capture' -- note that this would not be necessary if
> +     * the stack-pointer variant was implemented -- since the layout
> +     * would be known.
> +     * Relayingout here might have nasty effect if one were to query
> +     * sizeof *this from within the body -- would that even be
> +     * possible -- *this would refer to the lambda or the enclosing
> +     * class instance -- if there was one.???
> +     *
> +     * NOTE: I think this is a redefinition error; I'm just faking that
> +     * it isn't by clearing the size node... need to use stack pointer
> +     * method.  But that will likely bring its own issues -- not with
> +     * class layout though.
> +     */
> +    TYPE_SIZE (type) = NULL_TREE;
> +    finish_struct_1 (type);
> +
>      parser->in_function_body = saved_in_function_body;
>      parser->num_template_parameter_lists = saved_num_template_parameter_lists;
>      --parser->num_classes_being_defined;
> #########################################
>
> The way 'default reference capture' is implemented on the lambda branch seems to be kind of reactive.  I would expect
> that inheriting the stack somehow (maybe using just a stack pointer) would be better but without more investigation I
> don't know if that is possible or how one would go about doing it.  There is also the problem that the lambda would
> want its own stack also so its unlikely that you'd be able to simply drop it into the same frame as the enclosing
> function (though it may not be any different to having a nested scope in a function in terms of identifier ref'ing). 
> Here is a comment I added into the code as I was going through -- apologies for not rewriting!
>
> gcc/cp/semantics.c:5308	(working copy)
> /*
>  * Rather than looping through the identifiers used in the scope of
>  * the lambda and synthesizing individual captures of them, it would
>  * be better to ref the stack frame as transparently as possible...
>  * e.g. given just three ints i, j and k in scope:
>  * Instead of transforming:
>  *
>  *    [&] { i = 1; j = 2; k = 3; };
>  *
>  * into
>  *
>  *    [&i,&j,&k] { i = 1; j = 2; k = 3; };
>  *
>  * and thus storing three pointers to int, transform it into:
>  *
>  *    [sp=enclosing-stack-pointer] { var-from-stack(i,sp) = 1;
>  *                                   var-from-stack(j,sp) = 2;
>  *                                   var-from-stack(k,sp) = 3; };
>  *
>  * and only store one pointer.  This presumes that var-from-stack
>  * can be achieved with no (or negligible) cost (i.e. no worse than
>  * the individually captured version above.  Since std algorithms
>  * generally take and return copies of the function object passed
>  * in it is useful to keep them as small as possible.  One note,
>  * are reference_closures still in the standard?
>  *
>  * I don't know if its possible but it may be possible to 'append'
>  * the lambda's stack to the existing scope rather than creating a
>  * new constrained scope -- from a logical point of view.  This
>  * might be difficult if the compiler's design doesn't lend itself
>  * to working like that.
>  */
>
> Sorry that this is a bit a of a brain dump.  I'm just finding my way around and there is obviously at least some
> interest here.  Maybe one of you could try adding the finish_struct_1() call and see how much further you get.
>
> Regards,
> Adam
>
>
>
>   
Greetings,

Excellent work!  Maybe we can get the branch up to the latest with your 
patch.  Maybe if you sent the patch to the branch maintainers we could 
reboot this effort.

I observed the same behavior where an explicit capture worked perfectly 
and the [&] capture blew up.  I had done some captures of intermediate 
compile files of the [&] capture and an explicit list of all the 
variables.  Nothing struck me but I'm not an assembly or tree guru 
either.  I'll try that again and do more research.

Question(s): I thought gcc has lambdas as an extension.  I've never used 
them myself.  I was wondering if this implementation was ported to g++ 
to make C++ lambda?  Does the C version do the implicit capture thing?  
Maybe the problem is solved elsewhere.

Ed


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
       [not found] <1248855585.29221.ezmlm@gcc.gnu.org>
@ 2009-07-29 10:27 ` Adam Butcher
  2009-07-29 14:17   ` Ed Smith-Rowland
  2009-08-03 18:31   ` Jason Merrill
  0 siblings, 2 replies; 24+ messages in thread
From: Adam Butcher @ 2009-07-29 10:27 UTC (permalink / raw)
  To: Esben Mose Hansen; +Cc: gcc

Hi

Esben Mose Hansen writes:
> this program SEGFAULTs
>
> #include <algorithm>
>
> int main() {
>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>   int sum = 0;
>   int f = 5;
>   std::for_each(&numbers[0], &numbers[nn],  [&]  (int n)  {
>     sum += n * f;
>   });
>
> }
> ...
> I am completely new to gcc hacking, just
> dying to get lambda into gcc 4.5 :)
>
Me to on both counts!  So much so that I've got a working copy of the latest lambda branch, svnmerged the latest 4.5.0
trunk into it, fixed a few build issues and started poking around.  I have never ventured into gcc internals before so
its all a bit alien at the mo.

> On Thursday 30 April 2009 19:19:31 Ian wrote:
> > When I try to specify the capture it works ((&sum, &f) works too but f is
> > const):
> >
> > #include <algorithm>
> >
> > int
> > main(void)
> > {
> >   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
> >   const std::size_t nn = sizeof(numbers)/sizeof(int);
> >   int sum = 0;
> >   int f = 5;
> >
> >   //std::for_each(&numbers[0], &numbers[nn], [&](int n) { sum += n * f; });
> >
> >   std::for_each(&numbers[0], &numbers[nn], [&sum, f](int n) { sum += n * f;
> > });
> >
> >   return 0;
> > }
>
>  Yup. In fact, almost any other capture block than the [&] works :) I will try
>  to look at those tree options when I get sober again.
>
It is crashing when invoking a copied 'implicit capture' lambda.  The same occurs with:

  int main()
  {
     char i,j,k;
     auto const& f = [&] { i = 1; j = 2; k = 3; };
     auto g = f;
     g();
     return i+j+k;
  }

With explicit captures (i.e. specifying [&i,&j,&k] instead of [&] above) it works fine.  Also using f() (in place of
g()) is fine so the code in the lambda and the call to it must be okay.  So I started looking into the instance data.

The resulting lambda class in the above program is generated by the compiler to look something like the following in
name and structure:

   struct __lambda0
   {
      char &i,&j,&k;
      void operator() () const
      {
         i = 1; j = 2; k = 3;
      }
   };

Looking at the implementation in gcc/cp/{class.c,parser.c,semantics.c} it seems that, in implicit capture mode,
references to enclosing scope identifiers are retrospectively added to the lambda class on first use in the lambda
body.  This made me worry about the class structure changing as you progress through the parse of the lambda body. 
I.e. at the start of the body nothing is captured -- since nothing is referenced.  As you meet enclosing scope
references, each is added as a capture member to the lambda class.  Is this okay or has something already decided on
the size and structure of the class?  I figured (almost certainly naively and incorrectly) that it ought to be similar
to the difference between:

   struct X
   {
      int i;
      void init_i() { i = 1; }
   };

and

   struct X
   {
      void init_i() { i = 1; }
      int i;
   };

I changed the program above to check the sizes of the generated lambda class and it is indeed as expected (three
pointers). So the class has the correct size -- why does it not copy?  Surely a bitwise copy in this case is
sufficient and that ought to be auto-generated.  -- Except we're in compiler land here -- are we supposed to do the
auto-generating?  To test the theory I added

     memcpy(&g,&f,sizeof g);

after the assignment (auto g = f) to force the instance data to be copied from f to g.  It worked!  So why is the
compiler not generating suitable code for the lambda class copy -- the size is right, but no copy of instance data is
made -- maybe its already decided that the size is zero (as it was before the lambda body) and generated 'do-nothing'
copy constructors?

I had a poke around in gcc/cp/{class.c,parser.c,semantics.c} and believe I have worked around the issue -- the proper
solution I don't think is as straight-forward (or maybe its more straight-forward for a gcc guru?).

Note that the following diff hunk is after an svnmerge of trunk commits into my wc of the lambda branch so offsets
will likely be wrong.  I would give a full diff but my wc is in rather a messy state at the mo.  I have no idea
whether there are any nasty side effects to doing this but it seems to do the copy correctly afterwards.  I have not
looked into it much further at the mo.  Thought I'd just post my findings.

########### snip ##########################
--- gcc/cp/parser.c	(revision 150148)
+++ gcc/cp/parser.c	(working copy)
@@ -6936,6 +6991,24 @@

     cp_parser_lambda_body (parser, lambda_expr);

+    /* relayout again -- to allow for implicit
+     * parameters to have been added to the capture if it was a
+     * 'default capture' -- note that this would not be necessary if
+     * the stack-pointer variant was implemented -- since the layout
+     * would be known.
+     * Relayingout here might have nasty effect if one were to query
+     * sizeof *this from within the body -- would that even be
+     * possible -- *this would refer to the lambda or the enclosing
+     * class instance -- if there was one.???
+     *
+     * NOTE: I think this is a redefinition error; I'm just faking that
+     * it isn't by clearing the size node... need to use stack pointer
+     * method.  But that will likely bring its own issues -- not with
+     * class layout though.
+     */
+    TYPE_SIZE (type) = NULL_TREE;
+    finish_struct_1 (type);
+
     parser->in_function_body = saved_in_function_body;
     parser->num_template_parameter_lists = saved_num_template_parameter_lists;
     --parser->num_classes_being_defined;
#########################################

The way 'default reference capture' is implemented on the lambda branch seems to be kind of reactive.  I would expect
that inheriting the stack somehow (maybe using just a stack pointer) would be better but without more investigation I
don't know if that is possible or how one would go about doing it.  There is also the problem that the lambda would
want its own stack also so its unlikely that you'd be able to simply drop it into the same frame as the enclosing
function (though it may not be any different to having a nested scope in a function in terms of identifier ref'ing). 
Here is a comment I added into the code as I was going through -- apologies for not rewriting!

gcc/cp/semantics.c:5308	(working copy)
/*
 * Rather than looping through the identifiers used in the scope of
 * the lambda and synthesizing individual captures of them, it would
 * be better to ref the stack frame as transparently as possible...
 * e.g. given just three ints i, j and k in scope:
 * Instead of transforming:
 *
 *    [&] { i = 1; j = 2; k = 3; };
 *
 * into
 *
 *    [&i,&j,&k] { i = 1; j = 2; k = 3; };
 *
 * and thus storing three pointers to int, transform it into:
 *
 *    [sp=enclosing-stack-pointer] { var-from-stack(i,sp) = 1;
 *                                   var-from-stack(j,sp) = 2;
 *                                   var-from-stack(k,sp) = 3; };
 *
 * and only store one pointer.  This presumes that var-from-stack
 * can be achieved with no (or negligible) cost (i.e. no worse than
 * the individually captured version above.  Since std algorithms
 * generally take and return copies of the function object passed
 * in it is useful to keep them as small as possible.  One note,
 * are reference_closures still in the standard?
 *
 * I don't know if its possible but it may be possible to 'append'
 * the lambda's stack to the existing scope rather than creating a
 * new constrained scope -- from a logical point of view.  This
 * might be difficult if the compiler's design doesn't lend itself
 * to working like that.
 */

Sorry that this is a bit a of a brain dump.  I'm just finding my way around and there is obviously at least some
interest here.  Maybe one of you could try adding the finish_struct_1() call and see how much further you get.

Regards,
Adam


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-04-30 19:43 Smith-Rowland, Edward M
@ 2009-04-30 21:57 ` Esben Mose Hansen
  0 siblings, 0 replies; 24+ messages in thread
From: Esben Mose Hansen @ 2009-04-30 21:57 UTC (permalink / raw)
  To: Smith-Rowland, Edward M, gcc

On Thursday 30 April 2009 19:19:31 you wrote:
> When I try to specify the capture it works ((&sum, &f) works too but f is
> const):
>
> #include <algorithm>
>
> int
> main(void)
> {
>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>   int sum = 0;
>   int f = 5;
>
>   //std::for_each(&numbers[0], &numbers[nn], [&](int n) { sum += n * f; });
>
>   std::for_each(&numbers[0], &numbers[nn], [&sum, f](int n) { sum += n * f;
> });
>
>   return 0;
> }

Yup. In fact, almost any other capture block than the [&] works :) I will try 
to look at those tree options when I get sober again.

-- 
Kind regards, Esben

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
@ 2009-04-30 19:43 Smith-Rowland, Edward M
  2009-04-30 21:57 ` Esben Mose Hansen
  0 siblings, 1 reply; 24+ messages in thread
From: Smith-Rowland, Edward M @ 2009-04-30 19:43 UTC (permalink / raw)
  To: kde, gcc


Esben Mose Hansen <kde@mosehansen.dk> writes:

> this program SEGFAULTs
>
> #include <algorithm>
>
> int main() {
>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>   int sum = 0;
>   int f = 5;
>   std::for_each(&numbers[0], &numbers[nn],  [&]  (int n)  { 
>     sum += n * f; 
>   });
>
> }
>
> Now, my assembly days are some 15 years past, but the disassembly is
>
> 0x08048424 <_ZZ4mainENK9__lambda0clEiz+0>:      push   %ebp
> 0x08048425 <_ZZ4mainENK9__lambda0clEiz+1>:      mov    %esp,%ebp
> 0x08048427 <_ZZ4mainENK9__lambda0clEiz+3>:      mov    0x8(%ebp),%eax
> 0x0804842a <_ZZ4mainENK9__lambda0clEiz+6>:      mov    0x4(%eax),%eax
> 0x0804842d <_ZZ4mainENK9__lambda0clEiz+9>:      mov    0x8(%ebp),%edx
> 0x08048430 <_ZZ4mainENK9__lambda0clEiz+12>:     mov    0x4(%edx),%edx
> 0x08048433 <_ZZ4mainENK9__lambda0clEiz+15>:     mov    (%edx),%ecx
> 0x08048435 <_ZZ4mainENK9__lambda0clEiz+17>:     mov    0x8(%ebp),%edx
> 0x08048438 <_ZZ4mainENK9__lambda0clEiz+20>:     mov    (%edx),%edx
> 0x0804843a <_ZZ4mainENK9__lambda0clEiz+22>:     mov    (%edx),%edx
> 0x0804843c <_ZZ4mainENK9__lambda0clEiz+24>:     imul   0xc(%ebp),%edx
> 0x08048440 <_ZZ4mainENK9__lambda0clEiz+28>:     lea    (%ecx,%edx,1),%edx
> => SEGFAULT 0x08048443 <_ZZ4mainENK9__lambda0clEiz+31>:     mov    %edx,(%eax)
> 0x08048445 <_ZZ4mainENK9__lambda0clEiz+33>:     pop    %ebp
> 0x08048446 <_ZZ4mainENK9__lambda0clEiz+34>:     ret
>
> I have marked the segfault spot. I also find 0x0804843a suspicious, but then I 
> don't even know how to print register values in gcc. 
>
> Any pointers to where I should dig? I am completely new to gcc hacking, just 
> dying to get lambda into gcc 4.5 :)
>
> P.S: Shouldn't gcc show the actual lambda function code ( sum+= f*c; ) instead 
> of the assembly code in any case?

When I try to specify the capture it works ((&sum, &f) works too but f is const):

#include <algorithm>

int
main(void)
{
  int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  const std::size_t nn = sizeof(numbers)/sizeof(int);
  int sum = 0;
  int f = 5;

  //std::for_each(&numbers[0], &numbers[nn], [&](int n) { sum += n * f; });

  std::for_each(&numbers[0], &numbers[nn], [&sum, f](int n) { sum += n * f; });

  return 0;
}

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [lambda] Segmentation fault in simple lambda program
  2009-04-29 22:07 Esben Mose Hansen
@ 2009-04-30 11:54 ` Ian Lance Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ian Lance Taylor @ 2009-04-30 11:54 UTC (permalink / raw)
  To: Esben Mose Hansen; +Cc: gcc

Esben Mose Hansen <kde@mosehansen.dk> writes:

> this program SEGFAULTs
>
> #include <algorithm>
>
> int main() {
>   int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>   const std::size_t nn = sizeof(numbers)/sizeof(int);
>   int sum = 0;
>   int f = 5;
>   std::for_each(&numbers[0], &numbers[nn],  [&]  (int n)  { 
>     sum += n * f; 
>   });
>
> }
>
> Now, my assembly days are some 15 years past, but the disassembly is
>
> 0x08048424 <_ZZ4mainENK9__lambda0clEiz+0>:      push   %ebp
> 0x08048425 <_ZZ4mainENK9__lambda0clEiz+1>:      mov    %esp,%ebp
> 0x08048427 <_ZZ4mainENK9__lambda0clEiz+3>:      mov    0x8(%ebp),%eax
> 0x0804842a <_ZZ4mainENK9__lambda0clEiz+6>:      mov    0x4(%eax),%eax
> 0x0804842d <_ZZ4mainENK9__lambda0clEiz+9>:      mov    0x8(%ebp),%edx
> 0x08048430 <_ZZ4mainENK9__lambda0clEiz+12>:     mov    0x4(%edx),%edx
> 0x08048433 <_ZZ4mainENK9__lambda0clEiz+15>:     mov    (%edx),%ecx
> 0x08048435 <_ZZ4mainENK9__lambda0clEiz+17>:     mov    0x8(%ebp),%edx
> 0x08048438 <_ZZ4mainENK9__lambda0clEiz+20>:     mov    (%edx),%edx
> 0x0804843a <_ZZ4mainENK9__lambda0clEiz+22>:     mov    (%edx),%edx
> 0x0804843c <_ZZ4mainENK9__lambda0clEiz+24>:     imul   0xc(%ebp),%edx
> 0x08048440 <_ZZ4mainENK9__lambda0clEiz+28>:     lea    (%ecx,%edx,1),%edx
> => SEGFAULT 0x08048443 <_ZZ4mainENK9__lambda0clEiz+31>:     mov    %edx,(%eax)
> 0x08048445 <_ZZ4mainENK9__lambda0clEiz+33>:     pop    %ebp
> 0x08048446 <_ZZ4mainENK9__lambda0clEiz+34>:     ret
>
> I have marked the segfault spot. I also find 0x0804843a suspicious, but then I 
> don't even know how to print register values in gcc. 
>
> Any pointers to where I should dig? I am completely new to gcc hacking, just 
> dying to get lambda into gcc 4.5 :)
>
> P.S: Shouldn't gcc show the actual lambda function code ( sum+= f*c; ) instead 
> of the assembly code in any case?

Since lambda is primarily a front-end construct, you may find it more
useful to use the -fdump-tree-XXX options and to look at the tree dumps
to make sure that they look OK.  I haven't looked at the lambda branch,
but I assume that it creates nested functions, which do work in other
languages.

Ian

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [lambda] Segmentation fault in simple lambda program
@ 2009-04-29 22:07 Esben Mose Hansen
  2009-04-30 11:54 ` Ian Lance Taylor
  0 siblings, 1 reply; 24+ messages in thread
From: Esben Mose Hansen @ 2009-04-29 22:07 UTC (permalink / raw)
  To: gcc

Hi,

this program SEGFAULTs

#include <algorithm>

int main() {
  int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  const std::size_t nn = sizeof(numbers)/sizeof(int);
  int sum = 0;
  int f = 5;
  std::for_each(&numbers[0], &numbers[nn],  [&]  (int n)  { 
    sum += n * f; 
  });

}

Now, my assembly days are some 15 years past, but the disassembly is

0x08048424 <_ZZ4mainENK9__lambda0clEiz+0>:      push   %ebp
0x08048425 <_ZZ4mainENK9__lambda0clEiz+1>:      mov    %esp,%ebp
0x08048427 <_ZZ4mainENK9__lambda0clEiz+3>:      mov    0x8(%ebp),%eax
0x0804842a <_ZZ4mainENK9__lambda0clEiz+6>:      mov    0x4(%eax),%eax
0x0804842d <_ZZ4mainENK9__lambda0clEiz+9>:      mov    0x8(%ebp),%edx
0x08048430 <_ZZ4mainENK9__lambda0clEiz+12>:     mov    0x4(%edx),%edx
0x08048433 <_ZZ4mainENK9__lambda0clEiz+15>:     mov    (%edx),%ecx
0x08048435 <_ZZ4mainENK9__lambda0clEiz+17>:     mov    0x8(%ebp),%edx
0x08048438 <_ZZ4mainENK9__lambda0clEiz+20>:     mov    (%edx),%edx
0x0804843a <_ZZ4mainENK9__lambda0clEiz+22>:     mov    (%edx),%edx
0x0804843c <_ZZ4mainENK9__lambda0clEiz+24>:     imul   0xc(%ebp),%edx
0x08048440 <_ZZ4mainENK9__lambda0clEiz+28>:     lea    (%ecx,%edx,1),%edx
=> SEGFAULT 0x08048443 <_ZZ4mainENK9__lambda0clEiz+31>:     mov    %edx,(%eax)
0x08048445 <_ZZ4mainENK9__lambda0clEiz+33>:     pop    %ebp
0x08048446 <_ZZ4mainENK9__lambda0clEiz+34>:     ret

I have marked the segfault spot. I also find 0x0804843a suspicious, but then I 
don't even know how to print register values in gcc. 

Any pointers to where I should dig? I am completely new to gcc hacking, just 
dying to get lambda into gcc 4.5 :)

P.S: Shouldn't gcc show the actual lambda function code ( sum+= f*c; ) instead 
of the assembly code in any case?

Thanks for your help!

-- 
Kind regards, Esben

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2009-08-06 13:50 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-06 13:52 [lambda] Segmentation fault in simple lambda program John Freeman
     [not found] <1248855585.29221.ezmlm@gcc.gnu.org>
2009-07-29 10:27 ` Adam Butcher
2009-07-29 14:17   ` Ed Smith-Rowland
2009-08-03 18:31   ` Jason Merrill
2009-08-04  2:25     ` Adam Butcher
2009-08-04  4:11       ` Jason Merrill
2009-08-04  4:39         ` John Freeman
2009-08-04  5:39         ` John Freeman
2009-08-04 15:33           ` Richard Henderson
2009-08-04 22:45           ` John Freeman
2009-08-06 12:40             ` Adam Butcher
2009-08-04  9:07         ` Adam Butcher
2009-08-04 13:35           ` Adam Butcher
2009-08-04 13:44           ` John Freeman
2009-08-04 14:18             ` Jason Merrill
2009-08-04 14:46               ` John Freeman
2009-08-04 14:57                 ` Jason Merrill
2009-08-04 16:14                   ` John Freeman
2009-08-04 14:49           ` Jason Merrill
2009-08-04 16:17             ` John Freeman
  -- strict thread matches above, loose matches on Subject: below --
2009-04-30 19:43 Smith-Rowland, Edward M
2009-04-30 21:57 ` Esben Mose Hansen
2009-04-29 22:07 Esben Mose Hansen
2009-04-30 11:54 ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).