Repository: cc65/cc65 (C)

Issue:
cc65: Error in initialization of compound data
The following legal code causes the compiler to emit invalid data:

```C
struct s { char a[1]; int b; };
struct s x = { 1, 2 };
```

When using fully bracketed initializers, the code would be identical to 

```C
struct s { char a[1]; int b; };
struct s x = { { 1 }, 2 };
```

cc65 version 2.18 tries to read both values as array elements and outputs an error, because it sees two initializers for an array of size one:

```
test.c(2): Error: '{' expected
test.c(2): Error: Too many initializers
test.c(2): Error: '}' expected
```

The current git version translates the code without an error, so it looks like the problem has been fixed but this is wrong - as the assembly shows:

```
_x:
        .byte   $01     ; a[0]
        .byte   $02     ; a[1]
        .res    2,$00   ; b
```

(comments by me).

So while the old version complained about too many initializers, the current version silently reads and outputs all of them, even if there are no corresponding array elements.



Fix (patch):
diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c
index 619fe4897a..f63e9e95cd 100644
--- a/src/cc65/initdata.c
+++ b/src/cc65/initdata.c
@@ -343,8 +343,8 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
         /* Char array initialized by string constant */
         int NeedParen;
 
-        /* If we initializer is enclosed in brackets, remember this fact and
-        ** skip the opening bracket.
+        /* If the initializer is enclosed in curly braces, remember this fact
+        ** and skip the opening one.
         */
         NeedParen = (CurTok.Tok == TOK_LCURLY);
         if (NeedParen) {
@@ -377,7 +377,9 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
 
     } else {
 
-        /* Arrays can be initialized without a pair of curly braces */
+        /* An array can be initialized without a pair of enclosing curly braces
+        ** if it is itself a member of a struct/union or an element of an array.
+        */
         if (*Braces == 0 || CurTok.Tok == TOK_LCURLY) {
             /* Consume the opening curly brace */
             HasCurly = ConsumeLCurly ();
@@ -387,14 +389,22 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
         /* Initialize the array members */
         Count = 0;
         while (CurTok.Tok != TOK_RCURLY) {
-            /* Flexible array members may not be initialized within
-            ** an array (because the size of each element may differ
-            ** otherwise).
+            /* Flexible array members cannot be initialized within an array.
+            ** (Otherwise the size of each element may differ.)
             */
             ParseInitInternal (ElementType, Braces, 0);
             ++Count;
-            if (CurTok.Tok != TOK_COMMA)
+            if (CurTok.Tok != TOK_COMMA) {
+                break;
+            }
+
+            if (!HasCurly && ElementCount > 0 && Count >= ElementCount) {
+                /* If the array is initialized without enclosing curly braces,
+                ** it only accepts how many elements initializers up to its
+                ** count of elements, leaving any following initializers out.
+                */
                 break;
+            }
             NextToken ();
         }
 
@@ -491,7 +501,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
                 Error ("Excess elements in %s initializer", GetBasicTypeName (T));
                 SkipInitializer (HasCurly);
             }
-            return SI.Offs;
+            break;
         }
 
         /* Check for special members that don't consume the initializer */