[cfe-commits] r126116 - /cfe/trunk/lib/Sema/SemaInit.cpp
Douglas Gregor
dgregor at apple.com
Mon Feb 21 11:35:48 PST 2011
On Feb 21, 2011, at 12:45 AM, Abramo Bagnara wrote:
> Il 21/02/2011 08:57, John McCall ha scritto:
>> Author: rjmccall
>> Date: Mon Feb 21 01:57:55 2011
>> New Revision: 126116
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=126116&view=rev
>> Log:
>> Reorganize subelement initialization checking, no functionality change.
>>
>
> While you're on this area I'd like to submit you a long standing problem
> in current implementation of subelement initialization expansion.
>
> We think that the idea to expand the array range initialization is a
> very bad one for at least a few reason:
>
> 1) it needs an unlimited amount of AST nodes (and in real cases a lot of
> time/memory)
>
> 2) it change the semantic when an array range is initialized with an
> expression with side effects.
>
> I believe this is one of the reason why now clang is forced to refuse to
> generate code for:
>
> int f();
>
> int g() {
> int a[] = { [0 ... 10] = f() };
> }
>
> Our proposal would be to keep syntatical array range initialization and
> implicitly generated ones (due to holes in initialization sequences) in
> the form of array range initializer also in semantic initializer list.
Doing so is extremely complicated. Sema does a lot of work to detangle designated-initializers and form the semantic initializer list, which initializes elements in subobject order (which is also the order in which GCC initializes subobjects). It copes with such horrible things as:
#include <stdio.h>
int f() { printf("f()\n"); return 1; }
int g() { printf("g()\n"); return 2; }
struct Point {
int x, y;
};
int main() {
int i;
struct Point points[6] = {
[3 ... 5].x = f(),
[2 ... 4].y = g(),
};
for (i = 0; i != 6; ++i)
printf("{%d, %d}\n", points[i].x, points[i].y);
}
Note how I've interleaved the two array-range designators, so the subobject initialization actually looks a bit like this:
{ { uninit, uninit}, {uninit, uninit}, {uninit, g()}, {f(), g()}, {f(), g()}, {g(), uninit} }
and where the values of g() and f() are cached after being computed (effectively). If we run this code with GCC, we get the output
g()
f()
{0, 0}
{0, 0}
{0, 2}
{1, 2}
{1, 2}
{1, 0}
I don't see a way that we can cleanly describe the initialization behavior of this example in the AST without expanding the subobject initializations in the semantic view of the initializer list.
- Doug
More information about the cfe-commits
mailing list