[C++0x patch] implement range-based for loops
Rodrigo Rivas
rodrigorivascosta@gmail.com
Sat Sep 11 02:13:00 GMT 2010
> Those suffixes are to avoid clashes in the assembler; it seems a bit
> excessive to use for names that have no linkage. As long as the names
> aren't exactly the same as the ones in the standard, I think we're fine.
> Let's go with __for_range, __for_begin, __for_end.
Well, there will be clashes in the debugger inside of nested
range-based-for loops:
for (int x : {1,2,3})
for (char c : "abd")
{
//breakpoint here!
}
(gdb) info locals
c = 97 'a'
__for_range = @0x8048634
__for_begin = 0x8048634 "abd"
__for_end = 0x8048638 "%d %c\n"
x = 1
__for_range = @0xbffff0fc
__for_begin = 0xbffff104
__for_end = 0xbffff110
(gdb) print __for_range
$1 = (char (&)[4]) @0x8048634: "abd"
But there you are unable to print the other __for_range, etc.
With suffixes, however, it is cooler:
(gdb) info locals
c = 97 'a'
__for_range_1 = @0x8048634
__for_begin_1 = 0x8048634 "abd"
__for_end_1 = 0x8048638 "%d %c\n"
x = 1
__for_range_0 = @0xbffff0fc
__for_begin_0 = 0xbffff104
__for_end_0 = 0xbffff110
(gdb) print __for_range_1
$1 = (char (&)[4]) @0x8048634: "abd"
(gdb) print __for_range_0
$2 = (std::initializer_list<int> &) @0xbffff0fc: {
_M_array = 0xbffff104,
_M_len = 3
}
If you think that it doesn't worth it, well... actually I don't care
so much about debugger symbols anyway.
>> + bool scoped;
>>
>> + if (TREE_CODE (for_stmt) == RANGE_FOR_STMT)
>> + {
>> + RANGE_FOR_BODY (for_stmt) = do_poplevel (RANGE_FOR_BODY
>> (for_stmt));
>> + scoped = true;
>> + }
>> + else
>> + {
>> + FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt));
>> + scoped = flag_new_for_scope > 0;
>> + }
>> +
>> /* Pop the scope for the body of the loop. */
>> - if (flag_new_for_scope > 0)
>> + if (scoped)
>
> I think this will do the wrong thing (push but no pop) with -fno-for-scope
> outside a template, since we don't create a RANGE_FOR_STMT in that case.
I've double checked it, and I think that the code is correct.
In case of a range-for outside a template we call begin_for_stmt()
instead of begin_range_for_stmt(). It pushes iff flag_new_for_scope >
0.
Then it calls cp_convert_range_for() that in turn does
finish_for_init_stmt(), that pushes the FOR_BODY.
When the loop finishes finish_for_stmt() (quoted) goes to the "else",
pops the FOR_BODY and iff flag_new_for_scope > 0 pops the for_scope.
So, with -fno-for-scope, one push and one pop. Without it, two pushes
and two pops.
If the template case, it calls the begin_range_for_stmt() that always
pushes the for_scope, then finish_range_for_decl() pushes the
RANGE_FOR_BODY, and the finish_for_stmt() pops twice.
The template instantiation case is parallel to the non template one:
begin_for_stmt()/cp_convert_range_for()/finish_for_stmt().
I feel that my English is a bit thick today, so sorry if I'm hard to
understand...
Frankly, I though that the code was simpler when
begin_range_for_stmt() obeyed the -fno-for-scope, it was like more
symmetric. But again, this option hardly matters any more. Also, if
you like, I can add a testcase with this option.
Regards.
Rodrigo.
More information about the Gcc-patches
mailing list