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; return d;
} }
Expression* Parser::ParseInitExpression(Declaration* dtype) Expression* Parser::ParseInitExpression(Declaration* dtype, bool inner)
{ {
Expression* exp = nullptr; Expression* exp = nullptr;
Declaration* dec; Declaration* dec;
@ -1676,8 +1676,33 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
else else
mErrors->Error(mScanner->mLocation, EERR_UNDEFINED_OBJECT, "Constant for undefined anonymous type"); 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 = new Declaration(mScanner->mLocation, DT_CONST_STRUCT);
dec->mBase = dtype; dec->mBase = dtype;
dec->mSize = dtype->mSize; dec->mSize = dtype->mSize;
@ -1732,7 +1757,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
ConsumeToken(TK_ASSIGN); ConsumeToken(TK_ASSIGN);
} }
Expression* texp = ParseInitExpression(dtype->mBase); Expression* texp = ParseInitExpression(dtype->mBase, true);
texp = texp->ConstantFold(mErrors, mDataSection); texp = texp->ConstantFold(mErrors, mDataSection);
for (int i = 0; i < nrep; i++) for (int i = 0; i < nrep; i++)
{ {
@ -1748,8 +1773,15 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
size += dtype->mBase->mSize; size += dtype->mBase->mSize;
} }
if (inner && (dtype->mFlags & DTF_DEFINED) && size >= dtype->mSize)
break;
if (!ConsumeTokenIf(TK_COMMA)) if (!ConsumeTokenIf(TK_COMMA))
break; break;
if (inner && mScanner->mToken == TK_OPEN_BRACKET)
{
mScanner->UngetToken(TK_COMMA);
break;
}
if (mScanner->mToken == TK_CLOSE_BRACE) if (mScanner->mToken == TK_CLOSE_BRACE)
break; break;
} }
@ -1826,6 +1858,8 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
while (!mdec && path.Size()) while (!mdec && path.Size())
mdec = path.Pop()->mParams; mdec = path.Pop()->mParams;
} }
else if (inner)
break;
else if (!ConsumeTokenIf(TK_COMMA)) else if (!ConsumeTokenIf(TK_COMMA))
break; break;
@ -1834,34 +1868,17 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
} }
} }
if (!inner)
{
ConsumeTokenIf(TK_COMMA);
ConsumeToken(TK_CLOSE_BRACE); ConsumeToken(TK_CLOSE_BRACE);
}
if (last) if (last)
last->mNext = nullptr; last->mNext = nullptr;
else else
dec->mParams = nullptr; 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 else
{ {
exp = ParseRExpression(); exp = ParseRExpression();

View File

@ -71,7 +71,7 @@ protected:
Declaration* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr);
Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp);
Expression* ParseInitExpression(Declaration* dtype); Expression* ParseInitExpression(Declaration* dtype, bool inner = false);
Expression* ParseDeclarationExpression(Declaration* pdec); Expression* ParseDeclarationExpression(Declaration* pdec);
Declaration* ParsePostfixDeclaration(void); 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; 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) void Scanner::NextToken(void)
{ {
if (mReplay) if (mReplay)

View File

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