add __traits getBitfieldOffset and getBitfieldWidth (#17043)

This commit is contained in:
Walter Bright 2024-11-10 11:22:59 -08:00 committed by GitHub
parent e17cc3a28f
commit b70e66033c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 82 additions and 0 deletions

View file

@ -0,0 +1,16 @@
Add __traits getBitfieldOffset and getBitfieldWidth
This completes the introspection capabilities of builtin bitfields. For example:
---
struct S
{
int a,b;
int :2, c:3;
}
static assert(__traits(getBitfieldOffset, S.b) == 0);
static assert(__traits(getBitfieldOffset, S.c) == 2);
static assert(__traits(getBitfieldWidth, S.b) == 32);
static assert(__traits(getBitfieldWidth, S.c) == 3);
---

View file

@ -8924,6 +8924,8 @@ struct Id final
static Identifier* hasMember;
static Identifier* identifier;
static Identifier* fullyQualifiedName;
static Identifier* getBitfieldOffset;
static Identifier* getBitfieldWidth;
static Identifier* getProtection;
static Identifier* getVisibility;
static Identifier* parent;

View file

@ -484,6 +484,8 @@ immutable Msgtable[] msgtable =
{ "hasMember" },
{ "identifier" },
{ "fullyQualifiedName" },
{ "getBitfieldOffset" },
{ "getBitfieldWidth" },
{ "getProtection" },
{ "getVisibility" },
{ "parent" },

View file

@ -776,6 +776,43 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
return se.expressionSemantic(sc);
}
if (e.ident == Id.getBitfieldOffset || e.ident == Id.getBitfieldWidth)
{
if (dim != 1)
return dimError(1);
auto o = (*e.args)[0];
auto s = getDsymbolWithoutExpCtx(o);
if (!s)
{
error(e.loc, "bitfield symbol expected not `%s`", o.toChars());
return ErrorExp.get();
}
auto vd = s.toAlias.isVarDeclaration();
if (!vd || !(vd.storage_class & STC.field))
{
error(e.loc, "bitfield symbol expected not %s `%s`", s.kind, s.toPrettyChars);
return ErrorExp.get();
}
uint fieldWidth;
uint bitOffset;
if (auto bf = vd.isBitFieldDeclaration())
{
fieldWidth = bf.fieldWidth;
bitOffset = bf.bitOffset;
}
else // just a regular field
{
const sz = size(vd.type);
assert(sz < uint.max / 8); // overflow check
fieldWidth = cast(uint)sz * 8;
bitOffset = 0;
}
uint value = e.ident == Id.getBitfieldOffset ? bitOffset : fieldWidth;
return new IntegerExp(e.loc, value, Type.tuns32);
}
if (e.ident == Id.getProtection || e.ident == Id.getVisibility)
{
if (dim != 1)

View file

@ -0,0 +1,25 @@
/* REQUIRED_ARGS: -preview=bitfields
* TEST_OUTPUT:
---
fail_compilation/biterrors5.d(23): Error: bitfield symbol expected not struct `biterrors5.S`
fail_compilation/biterrors5.d(24): Error: bitfield symbol expected not variable `biterrors5.test0.i`
---
*/
struct S
{
int a,b;
int :2, c:3;
}
static assert(__traits(getBitfieldOffset, S.b) == 0);
static assert(__traits(getBitfieldWidth, S.b) == 32);
static assert(__traits(getBitfieldOffset, S.c) == 2);
static assert(__traits(getBitfieldWidth, S.c) == 3);
void test0()
{
int i;
i = __traits(getBitfieldOffset, S);
i = __traits(getBitfieldOffset, i);
}