Skip to content

Commit

Permalink
Merge pull request #5462 from 9rnsr/fix15681
Browse files Browse the repository at this point in the history
[REG2.067] Issue 15681 - Nested user type enum not retaining value properly
  • Loading branch information
MartinNowak committed Feb 23, 2016
2 parents ea553ad + 1d13794 commit 21c35b0
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 26 deletions.
65 changes: 43 additions & 22 deletions src/ctfeexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -368,32 +368,41 @@ extern (C++) UnionExp copyLiteral(Expression e)
* case: block assignment is permitted inside struct literals, eg,
* an int[4] array can be initialized with a single int.
*/
StructLiteralExp se = cast(StructLiteralExp)e;
Expressions* oldelems = se.elements;
auto sle = cast(StructLiteralExp)e;
auto oldelems = sle.elements;
auto newelems = new Expressions();
newelems.setDim(oldelems.dim);
for (size_t i = 0; i < newelems.dim; i++)
foreach (i, ref el; *newelems)
{
Expression m = (*oldelems)[i];
// We need the struct definition to detect block assignment
AggregateDeclaration sd = se.sd;
VarDeclaration v = sd.fields[i];
auto v = sle.sd.fields[i];
auto m = (*oldelems)[i];

// If it is a void assignment, use the default initializer
if (!m)
m = voidInitLiteral(v.type, v).copy();
if ((v.type.ty != m.type.ty) && v.type.ty == Tsarray)

if (v.type.ty == Tarray || v.type.ty == Taarray)
{
// Block assignment from inside struct literals
TypeSArray tsa = cast(TypeSArray)v.type;
uinteger_t length = tsa.dim.toInteger();
m = createBlockDuplicatedArrayLiteral(e.loc, v.type, m, cast(size_t)length);
// Don't have to copy array references
}
else if (v.type.ty != Tarray && v.type.ty != Taarray) // NOTE: do not copy array references
else
{
// Buzilla 15681: Copy the source element always.
m = copyLiteral(m).copy();
(*newelems)[i] = m;

// Block assignment from inside struct literals
if (v.type.ty != m.type.ty && v.type.ty == Tsarray)
{
auto tsa = cast(TypeSArray)v.type;
auto len = cast(size_t)tsa.dim.toInteger();
m = createBlockDuplicatedArrayLiteral(e.loc, v.type, m, len);
}
}
el = m;
}
emplaceExp!(StructLiteralExp)(&ue, e.loc, se.sd, newelems, se.stype);
StructLiteralExp r = cast(StructLiteralExp)ue.exp();
emplaceExp!(StructLiteralExp)(&ue, e.loc, sle.sd, newelems, sle.stype);
auto r = cast(StructLiteralExp)ue.exp();
r.type = e.type;
r.ownedByCtfe = OWNEDctfe;
r.origin = (cast(StructLiteralExp)e).origin;
Expand Down Expand Up @@ -582,21 +591,33 @@ extern (C++) uinteger_t resolveArrayLength(Expression e)
/******************************
* Helper for NewExp
* Create an array literal consisting of 'elem' duplicated 'dim' times.
* Params:
* loc = source location where the interpretation occurs
* type = target type of the result
* elem = the source of array element, it will be owned by the result
* dim = element number of the result
* Returns:
* Constructed ArrayLiteralExp
*/
extern (C++) ArrayLiteralExp createBlockDuplicatedArrayLiteral(Loc loc, Type type, Expression elem, size_t dim)
{
auto elements = new Expressions();
elements.setDim(dim);
bool mustCopy = needToCopyLiteral(elem);
if (type.ty == Tsarray && type.nextOf().ty == Tsarray && elem.type.ty != Tsarray)
{
// If it is a multidimensional array literal, do it recursively
elem = createBlockDuplicatedArrayLiteral(loc, type.nextOf(), elem, cast(size_t)(cast(TypeSArray)type.nextOf()).dim.toInteger());
mustCopy = true;
auto tsa = cast(TypeSArray)type.nextOf();
auto len = cast(size_t)tsa.dim.toInteger();
elem = createBlockDuplicatedArrayLiteral(loc, type.nextOf(), elem, len);
}
for (size_t i = 0; i < dim; i++)

// Buzilla 15681
auto tb = elem.type.toBasetype();
const mustCopy = tb.ty == Tstruct || tb.ty == Tsarray;

auto elements = new Expressions();
elements.setDim(dim);
foreach (i, ref el; *elements)
{
(*elements)[i] = mustCopy ? copyLiteral(elem).copy() : elem;
el = mustCopy && i ? copyLiteral(elem).copy() : elem;
}
auto ale = new ArrayLiteralExp(loc, elements);
ale.type = type;
Expand Down
14 changes: 10 additions & 4 deletions src/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -2891,9 +2891,15 @@ public:
assert(argnum == arguments.dim - 1);
if (elemType.ty == Tchar || elemType.ty == Twchar || elemType.ty == Tdchar)
{
return createBlockDuplicatedStringLiteral(loc, newtype, cast(uint)elemType.defaultInitLiteral(loc).toInteger(), len, cast(ubyte)elemType.size());
const ch = cast(dchar)elemType.defaultInitLiteral(loc).toInteger();
const sz = cast(ubyte)elemType.size();
return createBlockDuplicatedStringLiteral(loc, newtype, ch, len, sz);
}
else
{
auto el = interpret(elemType.defaultInitLiteral(loc), istate);
return createBlockDuplicatedArrayLiteral(loc, newtype, el, len);
}
return createBlockDuplicatedArrayLiteral(loc, newtype, elemType.defaultInitLiteral(loc), len);
}

override void visit(NewExp e)
Expand Down Expand Up @@ -5916,8 +5922,8 @@ public:
if (v.type.ty != result.type.ty && v.type.ty == Tsarray)
{
// Block assignment from inside struct literals
TypeSArray tsa = cast(TypeSArray)v.type;
size_t len = cast(size_t)tsa.dim.toInteger();
auto tsa = cast(TypeSArray)v.type;
auto len = cast(size_t)tsa.dim.toInteger();
result = createBlockDuplicatedArrayLiteral(ex.loc, v.type, ex, len);
(*se.elements)[i] = result;
}
Expand Down
30 changes: 30 additions & 0 deletions test/runnable/interpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -3394,6 +3394,35 @@ void test14862()
assert(g14862.data == 123UL); // OK <- fail
}

/************************************************/
// 15681

void test15681()
{
static struct A { float value; }

static struct S
{
A[2] values;

this(float)
{
values[0].value = 0;
values[1].value = 1;
}
}

auto s1 = S(1.0f);
assert(s1.values[0].value == 0); // OK
assert(s1.values[1].value == 1); // OK

enum s2 = S(1.0f);
static assert(s2.values[0].value == 0); // OK <- NG
static assert(s2.values[1].value == 1); // OK
assert(s2.values[0].value == 0); // OK <- NG
assert(s2.values[1].value == 1); // OK
}

/************************************************/

int main()
Expand Down Expand Up @@ -3516,6 +3545,7 @@ int main()
test9954();
test14140();
test14862();
test15681();

printf("Success\n");
return 0;
Expand Down

0 comments on commit 21c35b0

Please sign in to comment.