Skip to content

Commit

Permalink
Handle extending string literal length to the target static array type
Browse files Browse the repository at this point in the history
Both expression initializers and struct literal arguments should support implicit string lengthen.
  • Loading branch information
9rnsr committed Dec 29, 2014
1 parent eec3d9e commit f606bd4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
13 changes: 8 additions & 5 deletions src/init.c
Expand Up @@ -873,12 +873,15 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
if (exp->op == TOKstring && tb->ty == Tsarray && ti->ty == Tsarray)
if (exp->op == TOKstring && tb->ty == Tsarray)
{
StringExp *se = (StringExp *)exp;
if (!se->committed && se->type->ty == Tsarray &&
((TypeSArray *)se->type)->dim->toInteger() <
((TypeSArray *)t)->dim->toInteger())
Type *typeb = se->type->toBasetype();
TY tynto = tb->nextOf()->ty;
if (!se->committed &&
(typeb->ty == Tarray || typeb->ty == Tsarray) &&
(tynto == Tchar || tynto == Twchar || tynto == Tdchar) &&
se->length(tb->nextOf()->size()) < ((TypeSArray *)tb)->dim->toInteger())
{
exp = se->castTo(sc, t);
goto L1;
Expand Down Expand Up @@ -951,9 +954,9 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
}
exp = exp->implicitCastTo(sc, t);
}
L1:
if (exp->op == TOKerror)
return this;
L1:
if (needInterpret)
exp = exp->ctfeInterpret();
else
Expand Down
42 changes: 33 additions & 9 deletions src/struct.c
Expand Up @@ -1023,22 +1023,46 @@ bool StructDeclaration::fit(Loc loc, Scope *sc, Expressions *elements, Type *sty
}
offset = (unsigned)(v->offset + v->type->size());

Type *telem = v->type;
Type *t = v->type;
if (stype)
telem = telem->addMod(stype->mod);
Type *origType = telem;
while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
t = t->addMod(stype->mod);
Type *origType = t;
Type *tb = t->toBasetype();

/* Look for case of initializing a static array with a too-short
* string literal, such as:
* char[5] foo = "abc";
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
if (e->op == TOKstring && tb->ty == Tsarray)
{
StringExp *se = (StringExp *)e;
Type *typeb = se->type->toBasetype();
TY tynto = tb->nextOf()->ty;
if (!se->committed &&
(typeb->ty == Tarray || typeb->ty == Tsarray) &&
(tynto == Tchar || tynto == Twchar || tynto == Tdchar) &&
se->length(tb->nextOf()->size()) < ((TypeSArray *)tb)->dim->toInteger())
{
e = se->castTo(sc, t);
goto L1;
}
}

while (!e->implicitConvTo(t) && tb->ty == Tsarray)
{
/* Static array initialization, as in:
* T[3][5] = e;
*/
telem = telem->toBasetype()->nextOf();
t = tb->nextOf();
tb = t->toBasetype();
}
if (!e->implicitConvTo(t))
t = origType; // restore type for better diagnostic

if (!e->implicitConvTo(telem))
telem = origType; // restore type for better diagnostic

e = e->implicitCastTo(sc, telem);
e = e->implicitCastTo(sc, t);
L1:
if (e->op == TOKerror)
return false;

Expand Down

0 comments on commit f606bd4

Please sign in to comment.