From 13e1ed3e7bb3540fcb17141fbbd3496d29e3f7bc Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 22 Sep 2023 10:29:52 +0800 Subject: [PATCH] Fixed compound initialization with omitted enclosing curly braces when an array/struct/union to initialize is nested. --- src/cc65/initdata.c | 26 +++++++++++++++++-------- test/val/bug2135.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 test/val/bug2135.c diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index 619fe4897..f63e9e95c 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 */ diff --git a/test/val/bug2135.c b/test/val/bug2135.c new file mode 100644 index 000000000..1da0d2316 --- /dev/null +++ b/test/val/bug2135.c @@ -0,0 +1,47 @@ +/* Bug #2135 - Compound initialization consumes wrong amount of initializers with omitted +** enclosing curly braces when an array/struct/union to initialize is itself +** a member/element of a struct/union/array. +*/ + +#include +#include + +struct s { + union { + int8_t a[2][2]; + char c[sizeof (int8_t) * 2 * 2 + sizeof (int16_t) * 4]; + }; + int16_t b[4]; +}; +struct s x = { 1, 2, 3, 4, 5, 6 }; +struct s y = { {{{1, 2}, {3, 4}}}, {5, 6} }; + +unsigned failures; + +int main(void) +{ + unsigned i, j; + + for (i = 0; i < 2; ++i) + { + for (j = 0; j < 2; ++j) + { + if (x.a[i][j] != y.a[i][j]) + { + ++failures; + printf("x.a[%u][%u] = %d\n, expected %d\n", i, j, x.a[i][j], y.a[i][j]); + } + } + } + + for (i = 0; i < 4; ++i) + { + if (x.b[i] != y.b[i]) + { + ++failures; + printf("x.b[%u] = %d\n, expected %d\n", i, x.b[i], y.b[i]); + } + } + + return failures; +}