Hi all,
Based on previous discussion on the mailing list, clang currently lacks support
for C99 partial re-initialization behavior:
Reference: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-April/029188.html
Reference: http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_253.htm
I am proposing the following patch hopefully to fix this problem.
Given the following code snippet,
struct P1 { char x[6]; }; struct LP1 { struct P1 p1; }; struct LP1 l = { .p1 = { "foo" }, .p1.x[2] = 'x' }; // this example is adapted from the example for "struct fred x[]" in DR-253; // currently clang produces in l: { "\0\0x" }, // whereas gcc 4.8 produces { "fox" }; // with this fix, clang will also produce: { "fox" };
The idea is that upon seeing the second initializer, we will add a member to
the InitListExpr corresponding to ".p1" to hold the expression "{ "foo" }",
whereas one child field of the InitListExpr will hold "x". We keep this
structure till the CodeGen phase where we evaluate "{ "foo" }" and recursively
pass down its (evaluated) values as needed to the child fields of ".p1". The
recursion will stop at the child fields which are initialized with a
brace-enclosed list (if they exist).
From the Sema phase till the codeGen phase, the initializers for "l.p1" are
stored in two separate places: the new PrevInitExpr member of the top-level
InitListExpr, and the various child elements of the InitListExpr. This makes
it more complicated to do synatic/semantic checking of the initializer list.
This proposed patch does not cover all the semantic checking cases, but a
subsequent patch might be needed to do all the semantic checking on the new
PrevInitExpr member.
In the case where a string literal appears in place of "{ "foo" }", clang
evaluates it to a llvm::ConstantDataArray, which is not very easy to pass down
its components down to the child fields. In this proposal, I implemented a
method to build a llvm::ConstantArray out of a given ConstantDataArray. This is
the only part of the patch implemented in the llvm backend and will need to be
committed before the other parts. Or, maybe there are better ways to solve this?
Could someone take a look at the patch?
- Gao
Put the * on the right, please, and capitalize as lBraceLoc / rBraceLoc.