[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