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

Reply via email to