Skip to content

Commit

Permalink
add __traits getBitfieldOffset and getBitfieldWidth (#17043)
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright authored Nov 10, 2024
1 parent e17cc3a commit b70e660
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 0 deletions.
16 changes: 16 additions & 0 deletions changelog/dmd.getBitfieldInfo.dd
Original file line number Diff line number Diff line change
@@ -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);
---
2 changes: 2 additions & 0 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/id.d
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ immutable Msgtable[] msgtable =
{ "hasMember" },
{ "identifier" },
{ "fullyQualifiedName" },
{ "getBitfieldOffset" },
{ "getBitfieldWidth" },
{ "getProtection" },
{ "getVisibility" },
{ "parent" },
Expand Down
37 changes: 37 additions & 0 deletions compiler/src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
25 changes: 25 additions & 0 deletions compiler/test/fail_compilation/biterrors5.d
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit b70e660

Please sign in to comment.