Skip to content

Commit 35c808e

Browse files
committed
Improve wording of some errors around bitfields
1 parent c6549dc commit 35c808e

10 files changed

Lines changed: 109 additions & 42 deletions

File tree

compiler/src/dmd/dsymbolsem.d

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3174,10 +3174,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
31743174
if (dsym.semanticRun >= PASS.semanticdone)
31753175
return;
31763176

3177-
if (dsym.isAnonymous() && dsym._init)
3177+
const bool isAnonymous = dsym.isAnonymous();
3178+
if (isAnonymous && dsym._init)
31783179
{
3179-
.error(dsym.loc, "anonymous bitfield cannot have default initializer");
3180+
.error(dsym._init.loc, "anonymous bitfield cannot have default initializer");
31803181
dsym._init = null;
3182+
dsym.errors = true;
31813183
}
31823184

31833185
visit(cast(VarDeclaration)dsym);
@@ -3201,29 +3203,47 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
32013203
if (!dsym.type.isIntegral())
32023204
{
32033205
// C11 6.7.2.1-5
3204-
error(dsym.loc, "bitfield type `%s` is not an integer type", dsym.type.toChars());
3206+
if (isAnonymous)
3207+
error(dsym.loc, "anonymous bitfield cannot be of non-integral type `%s`", dsym.type.toChars());
3208+
else
3209+
error(dsym.loc, "bitfield `%s` cannot be of non-integral type `%s`", dsym.toChars(), dsym.type.toChars());
32053210
dsym.errors = true;
3211+
return;
32063212
}
32073213
if (!width.isIntegerExp())
32083214
{
32093215
error(width.loc, "bitfield width `%s` is not an integer constant", dsym.width.toChars());
32103216
dsym.errors = true;
32113217
}
32123218
const uwidth = width.toInteger(); // uwidth is unsigned
3213-
if (uwidth == 0 && !dsym.isAnonymous())
3219+
if (uwidth == 0 && !isAnonymous)
32143220
{
3215-
error(width.loc, "bitfield `%s` has zero width", dsym.toChars());
3221+
error(dsym.loc, "bitfield `%s` cannot have zero width", dsym.toChars());
32163222
dsym.errors = true;
32173223
}
3218-
const sz = dsym.type.size();
3219-
if (sz == SIZE_INVALID)
3220-
dsym.errors = true;
3221-
const max_width = sz * 8;
3222-
if (uwidth > max_width)
3224+
if (cast(long)uwidth < 0)
32233225
{
3224-
error(width.loc, "width `%lld` of bitfield `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
3226+
if (isAnonymous)
3227+
error(width.loc, "anonymous bitfield has negative width `%lld`", cast(long)uwidth);
3228+
else
3229+
error(width.loc, "bitfield `%s` has negative width `%lld`", dsym.toChars(), cast(long)uwidth);
32253230
dsym.errors = true;
32263231
}
3232+
else
3233+
{
3234+
const sz = dsym.type.size();
3235+
if (sz == SIZE_INVALID)
3236+
dsym.errors = true;
3237+
const max_width = sz * 8;
3238+
if (uwidth > max_width)
3239+
{
3240+
if (isAnonymous)
3241+
error(width.loc, "width `%lld` of anonymous bitfield does not fit in type `%s`", cast(long)uwidth, dsym.type.toChars());
3242+
else
3243+
error(width.loc, "width `%lld` of bitfield `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
3244+
dsym.errors = true;
3245+
}
3246+
}
32273247
dsym.fieldWidth = cast(uint)uwidth;
32283248
}
32293249

@@ -7046,10 +7066,20 @@ bool determineFields(AggregateDeclaration ad)
70467066
{
70477067
if (ad == tvs.sym)
70487068
{
7069+
if (ad.type.ty == Terror || ad.errors)
7070+
return 1; // failed already
7071+
70497072
const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
7050-
.error(ad.loc, "%s `%s` cannot have field `%s` with %ssame struct type", ad.kind, ad.toPrettyChars, v.toChars(), psz);
7051-
ad.type = Type.terror;
7052-
ad.errors = true;
7073+
if (!v.isAnonymous())
7074+
.error(v.loc, "%s `%s` cannot have field `%s` with %ssame struct type", ad.kind, ad.toPrettyChars, v.toChars(), psz);
7075+
else
7076+
.error(v.loc, "%s `%s` cannot have anonymous field with %ssame struct type", ad.kind, ad.toPrettyChars, psz);
7077+
// Don't cache errors from speculative semantic
7078+
if (!global.gag)
7079+
{
7080+
ad.type = Type.terror;
7081+
ad.errors = true;
7082+
}
70537083
return 1;
70547084
}
70557085
}
@@ -8439,10 +8469,9 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
84398469
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
84408470
if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
84418471

8442-
if (bfd.fieldWidth == 0 && !anon)
8443-
error(bfd.loc, "named bit fields cannot have 0 width");
8444-
if (bfd.fieldWidth > memsize * 8)
8445-
error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth);
8472+
// Handled in dsymbolSemantic as errors
8473+
assert(bfd.fieldWidth != 0 || anon, "named bit fields cannot have 0 width");
8474+
assert(bfd.fieldWidth <= memsize * 8, "bit field width is larger than type");
84468475

84478476
const style = target.c.bitFieldStyle;
84488477
if (style != TargetC.BitFieldStyle.MS && style != TargetC.BitFieldStyle.Gcc_Clang)

compiler/src/dmd/parse.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4505,6 +4505,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
45054505
isAliasDeclaration = true;
45064506
}
45074507

4508+
const typeLoc = token.loc;
45084509
AST.Type ts;
45094510

45104511
if (!autodecl)
@@ -4794,7 +4795,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
47944795
{
47954796
if (storage_class)
47964797
error("storage class not allowed for bitfield declaration");
4797-
s = new AST.BitFieldDeclaration(loc, t, ident, width, _init);
4798+
s = new AST.BitFieldDeclaration(ident.isAnonymous() ? typeLoc : loc, t, ident, width, _init);
47984799
}
47994800
else
48004801
{

compiler/src/dmd/semantic2.d

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,14 @@ private extern(C++) final class Semantic2Visitor : Visitor
351351
if (!bounds.contains(value))
352352
{
353353
const uwidth = bfd.fieldWidth;
354-
error(ei.loc, "bitfield initializer `%s` does not fit in %d bit%s",
355-
ei.exp.toChars(), cast(int) uwidth, uwidth == 1 ? "".ptr : "s".ptr);
354+
error(ei.loc, "default initializer `%s` is not representable as bitfield type `%s:%lld`",
355+
ei.exp.toChars(), bfd.type.toBasetype().toChars(), cast(long)uwidth);
356+
if (isUnsigned)
357+
errorSupplemental(bfd.loc, "bitfield `%s` default initializer must be a value between `%llu..%llu`",
358+
bfd.toChars(), bounds.imin.value, bounds.imax.value);
359+
else
360+
errorSupplemental(bfd.loc, "bitfield `%s` default initializer must be a value between `%lld..%lld`",
361+
bfd.toChars(), bounds.imin.value, bounds.imax.value);
356362
}
357363
}
358364

compiler/test/fail_compilation/biterrors2.d

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
fail_compilation/biterrors2.d(100): Error: variable `biterrors2.a` - bitfield must be member of struct, union, or class
55
int a : 2;
66
^
7-
fail_compilation/biterrors2.d(104): Error: bitfield `b` has zero width
7+
fail_compilation/biterrors2.d(104): Error: bitfield `b` cannot have zero width
88
int b:0;
9-
^
10-
fail_compilation/biterrors2.d(105): Error: bitfield type `float` is not an integer type
9+
^
10+
fail_compilation/biterrors2.d(105): Error: bitfield `c` cannot be of non-integral type `float`
1111
float c:3;
1212
^
1313
---
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* TEST_OUTPUT:
3+
---
4+
fail_compilation/biterrors6.d(12): Error: anonymous bitfield cannot be of non-integral type `noreturn`
5+
fail_compilation/biterrors6.d(13): Error: anonymous bitfield has negative width `-1`
6+
fail_compilation/biterrors6.d(14): Error: bitfield `n` cannot be of non-integral type `noreturn`
7+
fail_compilation/biterrors6.d(15): Error: bitfield `i` has negative width `-500`
8+
---
9+
*/
10+
struct S
11+
{
12+
noreturn : -1;
13+
int : -1;
14+
noreturn n : -500;
15+
int i : -500;
16+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* TEST_OUTPUT:
3+
---
4+
fail_compilation/biterrors7.d(10): Error: struct `biterrors7.S` cannot have anonymous field with same struct type
5+
fail_compilation/biterrors7.d(10): Error: anonymous bitfield cannot be of non-integral type `S`
6+
---
7+
*/
8+
struct S
9+
{
10+
S : S();
11+
}

compiler/test/fail_compilation/bitfields2.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* TEST_OUTPUT:
22
---
3-
fail_compilation/bitfields2.c(103): Error: bitfield type `float` is not an integer type
3+
fail_compilation/bitfields2.c(103): Error: bitfield `a` cannot be of non-integral type `float`
44
fail_compilation/bitfields2.c(104): Error: bitfield width `3.0` is not an integer constant
5-
fail_compilation/bitfields2.c(105): Error: bitfield `c` has zero width
5+
fail_compilation/bitfields2.c(105): Error: bitfield `c` cannot have zero width
66
fail_compilation/bitfields2.c(106): Error: width `60` of bitfield `d` does not fit in type `int`
77
---
88
*/

compiler/test/fail_compilation/fail20779.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/*
44
TEST_OUTPUT:
55
---
6-
fail_compilation/fail20779.d(12): Error: struct `fail20779.X` cannot have field `x` with same struct type
6+
fail_compilation/fail20779.d(14): Error: struct `fail20779.X` cannot have field `x` with same struct type
77
---
88
*/
99

compiler/test/fail_compilation/fail22384.d

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
/*
22
TEST_OUTPUT:
33
---
4-
fail_compilation/fail22384.d(32): Error: bitfield `z` has zero width
5-
fail_compilation/fail22384.d(36): Error: bitfield type `float` is not an integer type
6-
fail_compilation/fail22384.d(36): Error: bitfield `f` has zero width
7-
fail_compilation/fail22384.d(37): Error: bitfield type `float` is not an integer type
8-
fail_compilation/fail22384.d(38): Error: bitfield type `float` is not an integer type
9-
fail_compilation/fail22384.d(39): Error: bitfield type `float` is not an integer type
10-
fail_compilation/fail22384.d(44): Error: anonymous bitfield cannot have default initializer
11-
fail_compilation/fail22384.d(21): Error: bitfield initializer `4294967295u` does not fit in 4 bits
12-
fail_compilation/fail22384.d(26): Error: bitfield initializer `E.B` does not fit in 2 bits
13-
fail_compilation/fail22384.d(30): Error: bitfield initializer `4` does not fit in 3 bits
14-
fail_compilation/fail22384.d(31): Error: bitfield initializer `65` does not fit in 7 bits
15-
fail_compilation/fail22384.d(43): Error: cannot implicitly convert expression `4.2F` of type `float` to `int`
16-
fail_compilation/fail22384.d(45): Error: bitfield initializer `65` does not fit in 7 bits
17-
fail_compilation/fail22384.d(46): Error: cannot implicitly convert expression `42` of type `int` to `bool`
4+
fail_compilation/fail22384.d(36): Error: bitfield `z` cannot have zero width
5+
fail_compilation/fail22384.d(40): Error: bitfield `f` cannot be of non-integral type `float`
6+
fail_compilation/fail22384.d(41): Error: bitfield `f2` cannot be of non-integral type `float`
7+
fail_compilation/fail22384.d(42): Error: bitfield `f3` cannot be of non-integral type `float`
8+
fail_compilation/fail22384.d(43): Error: bitfield `f4` cannot be of non-integral type `float`
9+
fail_compilation/fail22384.d(48): Error: anonymous bitfield cannot have default initializer
10+
fail_compilation/fail22384.d(25): Error: default initializer `4294967295u` is not representable as bitfield type `uint:4`
11+
fail_compilation/fail22384.d(25): bitfield `d` default initializer must be a value between `0..15`
12+
fail_compilation/fail22384.d(30): Error: default initializer `E.B` is not representable as bitfield type `int:2`
13+
fail_compilation/fail22384.d(30): bitfield `b` default initializer must be a value between `-2..1`
14+
fail_compilation/fail22384.d(34): Error: default initializer `4` is not representable as bitfield type `int:3`
15+
fail_compilation/fail22384.d(34): bitfield `x` default initializer must be a value between `-4..3`
16+
fail_compilation/fail22384.d(35): Error: default initializer `65` is not representable as bitfield type `int:7`
17+
fail_compilation/fail22384.d(35): bitfield `y` default initializer must be a value between `-64..63`
18+
fail_compilation/fail22384.d(47): Error: cannot implicitly convert expression `4.2F` of type `float` to `int`
19+
fail_compilation/fail22384.d(49): Error: default initializer `65` is not representable as bitfield type `int:7`
20+
fail_compilation/fail22384.d(49): bitfield `j` default initializer must be a value between `-64..63`
21+
fail_compilation/fail22384.d(50): Error: cannot implicitly convert expression `42` of type `int` to `bool`
1822
---
1923
*/
2024
struct S {

compiler/test/fail_compilation/fail8691.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
TEST_OUTPUT:
33
---
4-
fail_compilation/fail8691.d(7): Error: struct `fail8691.Foo` cannot have field `f` with static array of same struct type
4+
fail_compilation/fail8691.d(9): Error: struct `fail8691.Foo` cannot have field `f` with static array of same struct type
55
---
66
*/
77
struct Foo

0 commit comments

Comments
 (0)