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