Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit df48ab6

Browse files
committedFeb 10, 2025·
flag non-portable bitfields
1 parent 2489ab7 commit df48ab6

File tree

2 files changed

+43
-36
lines changed

2 files changed

+43
-36
lines changed
 

‎compiler/src/dmd/dsymbolsem.d

+43-18
Original file line numberDiff line numberDiff line change
@@ -7026,12 +7026,14 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
70267026
AggregateDeclaration ad;
70277027
FieldState* fieldState;
70287028
bool isunion;
7029+
LINK linkage;
70297030

70307031
this(AggregateDeclaration ad, FieldState* fieldState, bool isunion) @safe
70317032
{
70327033
this.ad = ad;
70337034
this.fieldState = fieldState;
70347035
this.isunion = isunion;
7036+
this.linkage = LINK.d;
70357037
}
70367038

70377039
override void visit(Dsymbol d) {}
@@ -7114,8 +7116,8 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
71147116

71157117
const sz = t.size(vd.loc);
71167118
assert(sz != SIZE_INVALID && sz < uint.max);
7117-
uint memsize = cast(uint)sz; // size of member
7118-
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
7119+
const memsize = cast(uint)sz; // size of member
7120+
const memalignsize = target.fieldalign(t); // size of member for alignment purposes
71197121
vd.offset = placeField(vd.loc,
71207122
fieldState.offset,
71217123
memsize, memalignsize, vd.alignment,
@@ -7153,8 +7155,8 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
71537155

71547156
const sz = t.size(bfd.loc);
71557157
assert(sz != SIZE_INVALID && sz < uint.max);
7156-
uint memsize = cast(uint)sz; // size of member
7157-
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
7158+
const uint memsize = cast(uint)sz; // size of member
7159+
const uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
71587160
if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
71597161

71607162
if (bfd.fieldWidth == 0 && !anon)
@@ -7167,7 +7169,20 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
71677169
assert(0, "unsupported bit-field style");
71687170

71697171
const isMicrosoftStyle = style == TargetC.BitFieldStyle.MS;
7170-
const contributesToAggregateAlignment = target.c.contributesToAggregateAlignment(bfd);
7172+
7173+
/**
7174+
* Indicates whether the specified bit-field contributes to the alignment
7175+
* of the containing aggregate.
7176+
* E.g., (not all) ARM ABIs do NOT ignore anonymous (incl. 0-length)
7177+
* bit-fields.
7178+
*/
7179+
const bool contributesToAggregateAlignment = isMicrosoftStyle || !bfd.isAnonymous; // sufficient for supported architectures
7180+
7181+
/* Flag bitfield non-portable layouts that differ between MicrosoftStyle and non-MicrosoftStyle
7182+
* unless it's C semantics.
7183+
*/
7184+
const checkPortable = !ad.isCsymbol() && linkage == LINK.d;
7185+
bool isPortable = true; // start out assuming portable
71717186

71727187
void startNewField()
71737188
{
@@ -7208,19 +7223,16 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72087223

72097224
if (bfd.fieldWidth == 0)
72107225
{
7211-
if (!isMicrosoftStyle && !isunion)
7226+
if (!isunion)
72127227
{
7213-
// Use type of zero width field to align to next field
7214-
fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
7215-
ad.structsize = fieldState.offset;
7216-
}
7217-
else if (isMicrosoftStyle && fieldState.inFlight && !isunion)
7218-
{
7219-
// documentation says align to next int
7220-
//const alsz = cast(uint)Type.tint32.size();
7221-
const alsz = memsize; // but it really does this
7222-
fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
7223-
ad.structsize = fieldState.offset;
7228+
if (!isMicrosoftStyle || fieldState.inFlight)
7229+
{
7230+
const alsz = isMicrosoftStyle
7231+
? memsize // documentation says align to next int but memsize is actually used
7232+
: memalignsize; // use type of zero width field to align to next field
7233+
fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
7234+
ad.structsize = fieldState.offset;
7235+
}
72247236
}
72257237

72267238
fieldState.inFlight = false;
@@ -7229,7 +7241,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72297241

72307242
if (!fieldState.inFlight)
72317243
{
7232-
//printf("not in flight\n");
7244+
if (log) printf("not in flight\n");
72337245
startNewField();
72347246
}
72357247
else if (!isMicrosoftStyle)
@@ -7296,6 +7308,11 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72967308
fieldState.bitOffset = pastField;
72977309
}
72987310

7311+
if (checkPortable && !isPortable)
7312+
{
7313+
error(bfd.loc, "bitfield layout not portable among supported C compilers, wrap with `extern (C)` or `extern (C++)`");
7314+
}
7315+
72997316
//printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
73007317
//printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
73017318
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
@@ -7315,6 +7332,14 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
73157332
atd.include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
73167333
}
73177334

7335+
override void visit(LinkDeclaration atd)
7336+
{
7337+
LINK save = linkage;
7338+
linkage = atd.linkage;
7339+
atd.include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
7340+
linkage = save;
7341+
}
7342+
73187343
override void visit(AnonDeclaration anond)
73197344
{
73207345
//printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", anond);

‎compiler/src/dmd/target.d

-18
Original file line numberDiff line numberDiff line change
@@ -1463,24 +1463,6 @@ struct TargetC
14631463
crtDestructorsSupported = false;
14641464
}
14651465
}
1466-
1467-
/**
1468-
* Indicates whether the specified bit-field contributes to the alignment
1469-
* of the containing aggregate.
1470-
* E.g., (not all) ARM ABIs do NOT ignore anonymous (incl. 0-length)
1471-
* bit-fields.
1472-
*/
1473-
extern (C++) bool contributesToAggregateAlignment(BitFieldDeclaration bfd)
1474-
{
1475-
if (bitFieldStyle == BitFieldStyle.MS)
1476-
return true;
1477-
if (bitFieldStyle == BitFieldStyle.Gcc_Clang)
1478-
{
1479-
// sufficient for DMD's currently supported architectures
1480-
return !bfd.isAnonymous();
1481-
}
1482-
assert(0);
1483-
}
14841466
}
14851467

14861468
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)
Please sign in to comment.