From 068d87a036f0efd4c67e49878e76aecc15f250fb Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 31 Oct 2024 18:58:51 -0700 Subject: [PATCH] add __traits getBitfieldOffset and getBitfieldWidth --- changelog/dmd.getBitfieldInfo.dd | 16 ++++++++++ compiler/src/dmd/frontend.h | 2 ++ compiler/src/dmd/id.d | 2 ++ compiler/src/dmd/traits.d | 35 +++++++++++++++++++++ compiler/test/fail_compilation/biterrors5.d | 25 +++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 changelog/dmd.getBitfieldInfo.dd create mode 100644 compiler/test/fail_compilation/biterrors5.d diff --git a/changelog/dmd.getBitfieldInfo.dd b/changelog/dmd.getBitfieldInfo.dd new file mode 100644 index 000000000000..8d797184cdb8 --- /dev/null +++ b/changelog/dmd.getBitfieldInfo.dd @@ -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); +--- diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 4162052b111f..659bd5af576a 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -8923,6 +8923,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; diff --git a/compiler/src/dmd/id.d b/compiler/src/dmd/id.d index f676361d958b..b60172d0518d 100644 --- a/compiler/src/dmd/id.d +++ b/compiler/src/dmd/id.d @@ -484,6 +484,8 @@ immutable Msgtable[] msgtable = { "hasMember" }, { "identifier" }, { "fullyQualifiedName" }, + { "getBitfieldOffset" }, + { "getBitfieldWidth" }, { "getProtection" }, { "getVisibility" }, { "parent" }, diff --git a/compiler/src/dmd/traits.d b/compiler/src/dmd/traits.d index 7b32209fd2ef..5bf7d7ce8007 100644 --- a/compiler/src/dmd/traits.d +++ b/compiler/src/dmd/traits.d @@ -776,6 +776,41 @@ 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 + { + fieldWidth = cast(uint)size(vd.type) * 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) diff --git a/compiler/test/fail_compilation/biterrors5.d b/compiler/test/fail_compilation/biterrors5.d new file mode 100644 index 000000000000..2665d69cc98e --- /dev/null +++ b/compiler/test/fail_compilation/biterrors5.d @@ -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); +}