Fix flat initializer for stacked arrays

This commit is contained in:
drmortalwombat 2024-09-18 14:14:11 +02:00
parent b3be121f41
commit 47531ac5e8
4 changed files with 52 additions and 27 deletions

View File

@ -1658,7 +1658,7 @@ uint8* Parser::ParseStringLiteral(int & msize)
return d;
}
Expression* Parser::ParseInitExpression(Declaration* dtype)
Expression* Parser::ParseInitExpression(Declaration* dtype, bool inner)
{
Expression* exp = nullptr;
Declaration* dec;
@ -1676,8 +1676,33 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
else
mErrors->Error(mScanner->mLocation, EERR_UNDEFINED_OBJECT, "Constant for undefined anonymous type");
}
if (ConsumeTokenIf(TK_OPEN_BRACE))
if (mScanner->mToken == TK_STRING && dtype->mType == DT_TYPE_ARRAY && dtype->mBase->mType == DT_TYPE_INTEGER && dtype->mBase->mSize == 1)
{
int ds = dtype->mSize;
uint8* d = ParseStringLiteral(ds);
if (!(dtype->mFlags & DTF_DEFINED))
{
dtype->mFlags |= DTF_DEFINED;
dtype->mSize = int(ds);
}
dec = new Declaration(mScanner->mLocation, DT_CONST_DATA);
dec->mBase = dtype;
dec->mSize = dtype->mSize;
dec->mSection = mDataSection;
dec->mData = d;
if (ds > dtype->mSize + 1)
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "String constant is too large for char array");
}
else if ((inner && !dtype->mDefaultConstructor) || ConsumeTokenIf(TK_OPEN_BRACE))
{
if (inner && ConsumeTokenIf(TK_OPEN_BRACE))
inner = false;
dec = new Declaration(mScanner->mLocation, DT_CONST_STRUCT);
dec->mBase = dtype;
dec->mSize = dtype->mSize;
@ -1732,7 +1757,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
ConsumeToken(TK_ASSIGN);
}
Expression* texp = ParseInitExpression(dtype->mBase);
Expression* texp = ParseInitExpression(dtype->mBase, true);
texp = texp->ConstantFold(mErrors, mDataSection);
for (int i = 0; i < nrep; i++)
{
@ -1748,8 +1773,15 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
size += dtype->mBase->mSize;
}
if (inner && (dtype->mFlags & DTF_DEFINED) && size >= dtype->mSize)
break;
if (!ConsumeTokenIf(TK_COMMA))
break;
if (inner && mScanner->mToken == TK_OPEN_BRACKET)
{
mScanner->UngetToken(TK_COMMA);
break;
}
if (mScanner->mToken == TK_CLOSE_BRACE)
break;
}
@ -1826,6 +1858,8 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
while (!mdec && path.Size())
mdec = path.Pop()->mParams;
}
else if (inner)
break;
else if (!ConsumeTokenIf(TK_COMMA))
break;
@ -1834,34 +1868,17 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
}
}
ConsumeToken(TK_CLOSE_BRACE);
if (!inner)
{
ConsumeTokenIf(TK_COMMA);
ConsumeToken(TK_CLOSE_BRACE);
}
if (last)
last->mNext = nullptr;
else
dec->mParams = nullptr;
}
else if (mScanner->mToken == TK_STRING && dtype->mType == DT_TYPE_ARRAY && dtype->mBase->mType == DT_TYPE_INTEGER && dtype->mBase->mSize == 1)
{
int ds = dtype->mSize;
uint8* d = ParseStringLiteral(ds);
if (!(dtype->mFlags & DTF_DEFINED))
{
dtype->mFlags |= DTF_DEFINED;
dtype->mSize = int(ds);
}
dec = new Declaration(mScanner->mLocation, DT_CONST_DATA);
dec->mBase = dtype;
dec->mSize = dtype->mSize;
dec->mSection = mDataSection;
dec->mData = d;
if (ds > dtype->mSize + 1)
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "String constant is too large for char array");
}
else
{
exp = ParseRExpression();

View File

@ -71,7 +71,7 @@ protected:
Declaration* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr);
Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp);
Expression* ParseInitExpression(Declaration* dtype);
Expression* ParseInitExpression(Declaration* dtype, bool inner = false);
Expression* ParseDeclarationExpression(Declaration* pdec);
Declaration* ParsePostfixDeclaration(void);

View File

@ -478,6 +478,12 @@ bool Scanner::IsIntegerToken(void) const
return mToken == TK_INTEGER || mToken == TK_INTEGERU || mToken == TK_INTEGERL || mToken == TK_INTEGERUL;
}
void Scanner::UngetToken(Token token)
{
mUngetToken = mToken;
mToken = token;
}
void Scanner::NextToken(void)
{
if (mReplay)

View File

@ -240,6 +240,7 @@ public:
const char* TokenName(Token token) const;
void NextToken(void);
void UngetToken(Token token);
void BeginRecord(void);
TokenSequence* CompleteRecord(void);
@ -266,6 +267,7 @@ public:
uint8 * mTokenEmbed;
int mTokenEmbedSize;
Token mUndoToken;
Token mToken;
double mTokenNumber;
int64 mTokenInteger;