@@ -7026,12 +7026,14 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7026
7026
AggregateDeclaration ad;
7027
7027
FieldState* fieldState;
7028
7028
bool isunion;
7029
+ LINK linkage;
7029
7030
7030
7031
this (AggregateDeclaration ad, FieldState* fieldState, bool isunion) @safe
7031
7032
{
7032
7033
this .ad = ad;
7033
7034
this .fieldState = fieldState;
7034
7035
this .isunion = isunion;
7036
+ this .linkage = LINK .d;
7035
7037
}
7036
7038
7037
7039
override void visit (Dsymbol d) {}
@@ -7114,8 +7116,8 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7114
7116
7115
7117
const sz = t.size(vd.loc);
7116
7118
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
7119
7121
vd.offset = placeField(vd.loc,
7120
7122
fieldState.offset,
7121
7123
memsize, memalignsize, vd.alignment,
@@ -7153,8 +7155,8 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7153
7155
7154
7156
const sz = t.size(bfd.loc);
7155
7157
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
7158
7160
if (log) printf(" memsize: %u memalignsize: %u\n " , memsize, memalignsize);
7159
7161
7160
7162
if (bfd.fieldWidth == 0 && ! anon)
@@ -7167,7 +7169,20 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7167
7169
assert (0 , " unsupported bit-field style" );
7168
7170
7169
7171
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
7171
7186
7172
7187
void startNewField ()
7173
7188
{
@@ -7208,19 +7223,16 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7208
7223
7209
7224
if (bfd.fieldWidth == 0 )
7210
7225
{
7211
- if (! isMicrosoftStyle && ! isunion)
7226
+ if (! isunion)
7212
7227
{
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
+ }
7224
7236
}
7225
7237
7226
7238
fieldState.inFlight = false ;
@@ -7229,7 +7241,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7229
7241
7230
7242
if (! fieldState.inFlight)
7231
7243
{
7232
- // printf("not in flight\n");
7244
+ if (log) printf(" not in flight\n " );
7233
7245
startNewField();
7234
7246
}
7235
7247
else if (! isMicrosoftStyle)
@@ -7296,6 +7308,11 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
7296
7308
fieldState.bitOffset = pastField;
7297
7309
}
7298
7310
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
+
7299
7316
// printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize);
7300
7317
// printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
7301
7318
// 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
7315
7332
atd.include(null ).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
7316
7333
}
7317
7334
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
+
7318
7343
override void visit (AnonDeclaration anond)
7319
7344
{
7320
7345
// printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", anond);
0 commit comments