mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
fix Issue 24262 - Assert error with bit fields (#15864)
This commit is contained in:
parent
e1197fc765
commit
ec34292ead
2 changed files with 70 additions and 18 deletions
|
@ -6522,13 +6522,13 @@ elem *toElemStructLit(StructLiteralExp sle, ref IRState irs, EXP op, Symbol *sym
|
|||
// CTFE may fill the hidden pointer by NullExp.
|
||||
{
|
||||
VarDeclaration vbf;
|
||||
foreach (i, el; *sle.elements)
|
||||
foreach (i, element; *sle.elements)
|
||||
{
|
||||
if (!el)
|
||||
if (!element)
|
||||
continue;
|
||||
|
||||
VarDeclaration v = sle.sd.fields[i];
|
||||
assert(!v.isThisDeclaration() || el.op == EXP.null_);
|
||||
assert(!v.isThisDeclaration() || element.op == EXP.null_);
|
||||
|
||||
elem *e1;
|
||||
if (tybasic(stmp.Stype.Tty) == TYnptr)
|
||||
|
@ -6539,50 +6539,73 @@ elem *toElemStructLit(StructLiteralExp sle, ref IRState irs, EXP op, Symbol *sym
|
|||
{
|
||||
e1 = el_ptr(stmp);
|
||||
}
|
||||
e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset));
|
||||
|
||||
elem *ep = toElem(el, irs);
|
||||
elem *ep = toElem(element, irs);
|
||||
|
||||
Type t1b = v.type.toBasetype();
|
||||
Type t2b = el.type.toBasetype();
|
||||
Type t2b = element.type.toBasetype();
|
||||
if (t1b.ty == Tsarray)
|
||||
{
|
||||
e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset));
|
||||
if (t2b.implicitConvTo(t1b))
|
||||
{
|
||||
elem *esize = el_long(TYsize_t, t1b.size());
|
||||
ep = array_toPtr(el.type, ep);
|
||||
ep = array_toPtr(element.type, ep);
|
||||
e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
|
||||
}
|
||||
else
|
||||
{
|
||||
elem *edim = el_long(TYsize_t, t1b.size() / t2b.size());
|
||||
e1 = setArray(el, e1, edim, t2b, ep, irs, op == EXP.construct ? EXP.blit : op);
|
||||
e1 = setArray(element, e1, edim, t2b, ep, irs, op == EXP.construct ? EXP.blit : op);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tym_t ty = totym(v.type);
|
||||
e1 = el_una(OPind, ty, e1);
|
||||
if (tybasic(ty) == TYstruct)
|
||||
const tym_t tym = totym(v.type);
|
||||
auto voffset = v.offset;
|
||||
uint bitfieldArg;
|
||||
uint bitOffset;
|
||||
auto bf = v.isBitFieldDeclaration();
|
||||
if (bf)
|
||||
{
|
||||
const szbits = tysize(tym) * 8;
|
||||
bitOffset = bf.bitOffset;
|
||||
if (bitOffset + bf.fieldWidth > szbits)
|
||||
{
|
||||
const advance = bitOffset / szbits;
|
||||
voffset += advance;
|
||||
bitOffset -= advance * 8;
|
||||
assert(bitOffset + bf.fieldWidth <= szbits);
|
||||
}
|
||||
bitfieldArg = bf.fieldWidth * 256 + bitOffset;
|
||||
|
||||
//printf("2bitOffset %u fieldWidth %u bits %u\n", bitOffset, bf.fieldWidth, szbits);
|
||||
assert(bitOffset + bf.fieldWidth <= szbits);
|
||||
}
|
||||
|
||||
e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, voffset));
|
||||
e1 = el_una(OPind, tym, e1);
|
||||
if (tybasic(tym) == TYstruct)
|
||||
{
|
||||
e1.ET = Type_toCtype(v.type);
|
||||
if (auto bf = v.isBitFieldDeclaration())
|
||||
assert(!bf);
|
||||
}
|
||||
if (bf)
|
||||
{
|
||||
if (!vbf || vbf.offset + vbf.type.size() <= v.offset)
|
||||
{
|
||||
/* Initialize entire location the bitfield is in
|
||||
* ep = (ep & ((1 << bf.fieldWidth) - 1)) << bf.bitOffset
|
||||
*/
|
||||
tym_t e1ty = e1.Ety;
|
||||
auto ex = el_bin(OPand, e1ty, ep, el_long(e1ty, (1L << bf.fieldWidth) - 1));
|
||||
ep = el_bin(OPshl, e1ty, ex, el_long(e1ty, bf.bitOffset));
|
||||
auto ex = el_bin(OPand, tym, ep, el_long(tym, (1L << bf.fieldWidth) - 1));
|
||||
ep = el_bin(OPshl, tym, ex, el_long(tym, bitOffset));
|
||||
vbf = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert special bitfield operator
|
||||
auto mos = el_long(TYuint, bf.fieldWidth * 256 + bf.bitOffset);
|
||||
//printf("2bitOffset %u fieldWidth %u bits %u\n", bf.bitOffset, bf.fieldWidth, tysize(e1.Ety) * 8);
|
||||
assert(bf.bitOffset + bf.fieldWidth <= tysize(e1.Ety) * 8);
|
||||
// Insert special bitfield operator
|
||||
auto mos = el_long(TYuint, bitfieldArg);
|
||||
e1 = el_bin(OPbit, e1.Ety, e1, mos);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,6 +254,34 @@ _Static_assert(test7s2() == -2, "3");
|
|||
|
||||
/******************************************/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24257
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
struct Entry
|
||||
{
|
||||
unsigned id : 15;
|
||||
_Bool done : 1;
|
||||
};
|
||||
|
||||
struct State
|
||||
{
|
||||
struct Entry e;
|
||||
};
|
||||
|
||||
void test24257()
|
||||
{
|
||||
int i = 72;
|
||||
struct State s = (struct State){i};
|
||||
if (s.e.id != 72)
|
||||
{
|
||||
printf("error %d\n", __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************/
|
||||
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
|
@ -263,6 +291,7 @@ int main()
|
|||
test5();
|
||||
test6();
|
||||
test7();
|
||||
test24257();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue