From f66c6c2a975c62d2af14002d27093a8da3a98f18 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Sun, 6 Oct 2024 14:21:16 +0800 Subject: [PATCH] move `determineSize`/`finalizeSize` to `dsymbolsem.d` --- compiler/src/dmd/aggregate.d | 143 +------------ compiler/src/dmd/aggregate.h | 3 - compiler/src/dmd/dclass.d | 110 ---------- compiler/src/dmd/dstruct.d | 121 ----------- compiler/src/dmd/dsymbolsem.d | 374 ++++++++++++++++++++++++++++++++++ compiler/src/dmd/frontend.h | 3 - compiler/src/dmd/mtype.d | 1 + compiler/src/dmd/safe.d | 1 + 8 files changed, 377 insertions(+), 379 deletions(-) diff --git a/compiler/src/dmd/aggregate.d b/compiler/src/dmd/aggregate.d index 277621650002..649dba8f0747 100644 --- a/compiler/src/dmd/aggregate.d +++ b/compiler/src/dmd/aggregate.d @@ -187,155 +187,14 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return fields.length - isNested() - (vthis2 !is null); } - /*************************************** - * Collect all instance fields, then determine instance size. - * Returns: - * false if failed to determine the size. - */ - extern (D) final bool determineSize(const ref Loc loc) - { - //printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok); - - // The previous instance size finalizing had: - if (type.ty == Terror || errors) - return false; // failed already - if (sizeok == Sizeok.done) - return true; // succeeded - - if (!members) - { - .error(loc, "%s `%s` unknown size", kind, toPrettyChars); - return false; - } - - if (_scope) - dsymbolSemantic(this, null); - - // Determine the instance size of base class first. - if (auto cd = isClassDeclaration()) - { - cd = cd.baseClass; - if (cd && !cd.determineSize(loc)) - goto Lfail; - } - - // Determine instance fields when sizeok == Sizeok.none - if (!this.determineFields()) - goto Lfail; - if (sizeok != Sizeok.done) - finalizeSize(); - - // this aggregate type has: - if (type.ty == Terror) - return false; // marked as invalid during the finalizing. - if (sizeok == Sizeok.done) - return true; // succeeded to calculate instance size. - - Lfail: - // There's unresolvable forward reference. - if (type != Type.terror) - error(loc, "%s `%s` no size because of forward reference", kind, toPrettyChars); - // Don't cache errors from speculative semantic, might be resolvable later. - // https://issues.dlang.org/show_bug.cgi?id=16574 - if (!global.gag) - { - type = Type.terror; - errors = true; - } - return false; - } - - abstract void finalizeSize(); - override final uinteger_t size(const ref Loc loc) { //printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok); - bool ok = determineSize(loc); + bool ok = determineSize(this, loc); //printf("-AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok); return ok ? structsize : SIZE_INVALID; } - /*************************************** - * Calculate field[i].overlapped and overlapUnsafe, and check that all of explicit - * field initializers have unique memory space on instance. - * Returns: - * true if any errors happen. - */ - extern (D) final bool checkOverlappedFields() - { - //printf("AggregateDeclaration::checkOverlappedFields() %s\n", toChars()); - assert(sizeok == Sizeok.done); - size_t nfields = fields.length; - if (isNested()) - { - auto cd = isClassDeclaration(); - if (!cd || !cd.baseClass || !cd.baseClass.isNested()) - nfields--; - if (vthis2 && !(cd && cd.baseClass && cd.baseClass.vthis2)) - nfields--; - } - bool errors = false; - - // Fill in missing any elements with default initializers - foreach (i; 0 .. nfields) - { - auto vd = fields[i]; - if (vd.errors) - { - errors = true; - continue; - } - - const vdIsVoidInit = vd._init && vd._init.isVoidInitializer(); - - // Find overlapped fields with the hole [vd.offset .. vd.offset.size()]. - foreach (j; 0 .. nfields) - { - if (i == j) - continue; - auto v2 = fields[j]; - if (v2.errors) - { - errors = true; - continue; - } - if (!vd.isOverlappedWith(v2)) - continue; - - // vd and v2 are overlapping. - vd.overlapped = true; - v2.overlapped = true; - - if (!MODimplicitConv(vd.type.mod, v2.type.mod)) - v2.overlapUnsafe = true; - if (!MODimplicitConv(v2.type.mod, vd.type.mod)) - vd.overlapUnsafe = true; - - if (i > j) - continue; - - if (!v2._init) - continue; - - if (v2._init.isVoidInitializer()) - continue; - - if (vd._init && !vdIsVoidInit && v2._init) - { - .error(loc, "overlapping default initialization for field `%s` and `%s`", v2.toChars(), vd.toChars()); - errors = true; - } - else if (v2._init && i < j) - { - .error(v2.loc, "union field `%s` with default initialization `%s` must be before field `%s`", - v2.toChars(), dmd.hdrgen.toChars(v2._init), vd.toChars()); - errors = true; - } - } - } - return errors; - } - /*************************************** * Fill out remainder of elements[] with default initializers for fields[]. * Params: diff --git a/compiler/src/dmd/aggregate.h b/compiler/src/dmd/aggregate.h index c972f0a6631f..5b30b8f23165 100644 --- a/compiler/src/dmd/aggregate.h +++ b/compiler/src/dmd/aggregate.h @@ -117,7 +117,6 @@ class AggregateDeclaration : public ScopeDsymbol Sizeok sizeok; // set when structsize contains valid data virtual Scope *newScope(Scope *sc); - virtual void finalizeSize() = 0; uinteger_t size(const Loc &loc) override final; bool fill(const Loc &loc, Expressions &elements, bool ctorinit); Type *getType() override final; @@ -171,7 +170,6 @@ class StructDeclaration : public AggregateDeclaration static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; const char *kind() const override; - void finalizeSize() override final; bool isPOD(); bool zeroInit() const; // !=0 if initialize with 0 fill bool zeroInit(bool v); @@ -288,7 +286,6 @@ class ClassDeclaration : public AggregateDeclaration virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseInfoComplete(); - void finalizeSize() override; bool hasMonitor(); bool isFuncHidden(FuncDeclaration *fd); bool isCOMclass() const; diff --git a/compiler/src/dmd/dclass.d b/compiler/src/dmd/dclass.d index 74074d7078cd..b58786c1202a 100644 --- a/compiler/src/dmd/dclass.d +++ b/compiler/src/dmd/dclass.d @@ -496,116 +496,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return null; } - final override void finalizeSize() - { - assert(sizeok != Sizeok.done); - - // Set the offsets of the fields and determine the size of the class - if (baseClass) - { - assert(baseClass.sizeok == Sizeok.done); - - alignsize = baseClass.alignsize; - if (classKind == ClassKind.cpp) - structsize = target.cpp.derivedClassOffset(baseClass); - else - structsize = baseClass.structsize; - } - else if (classKind == ClassKind.objc) - structsize = 0; // no hidden member for an Objective-C class - else if (isInterfaceDeclaration()) - { - if (interfaces.length == 0) - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - } - } - else - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - if (hasMonitor()) - structsize += target.ptrsize; // allow room for __monitor - } - - //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - size_t bi = 0; // index into vtblInterfaces[] - - /**** - * Runs through the inheritance graph to set the BaseClass.offset fields. - * Recursive in order to account for the size of the interface classes, if they are - * more than just interfaces. - * Params: - * cd = interface to look at - * baseOffset = offset of where cd will be placed - * Returns: - * subset of instantiated size used by cd for interfaces - */ - uint membersPlace(ClassDeclaration cd, uint baseOffset) - { - //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset); - uint offset = baseOffset; - - foreach (BaseClass* b; cd.interfaces) - { - if (b.sym.sizeok != Sizeok.done) - b.sym.finalizeSize(); - assert(b.sym.sizeok == Sizeok.done); - - if (!b.sym.alignsize) - b.sym.alignsize = target.ptrsize; - offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset); - assert(bi < vtblInterfaces.length); - - BaseClass* bv = (*vtblInterfaces)[bi]; - if (b.sym.interfaces.length == 0) - { - //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset); - bv.offset = offset; - ++bi; - // All the base interfaces down the left side share the same offset - for (BaseClass* b2 = bv; b2.baseInterfaces.length; ) - { - b2 = &b2.baseInterfaces[0]; - b2.offset = offset; - //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset); - } - } - membersPlace(b.sym, offset); - //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize); - offset += b.sym.structsize; - if (alignsize < b.sym.alignsize) - alignsize = b.sym.alignsize; - } - return offset - baseOffset; - } - - structsize += membersPlace(this, structsize); - - if (isInterfaceDeclaration()) - { - sizeok = Sizeok.done; - return; - } - - // FIXME: Currently setFieldOffset functions need to increase fields - // to calculate each variable offsets. It can be improved later. - fields.setDim(0); - - FieldState fieldState; - fieldState.offset = structsize; - foreach (s; *members) - { - s.setFieldOffset(this, &fieldState, false); - } - - sizeok = Sizeok.done; - - // Calculate fields[i].overlapped - checkOverlappedFields(); - } - /************** * Returns: true if there's a __monitor field */ diff --git a/compiler/src/dmd/dstruct.d b/compiler/src/dmd/dstruct.d index 26a9de54393d..dda423e5e09e 100644 --- a/compiler/src/dmd/dstruct.d +++ b/compiler/src/dmd/dstruct.d @@ -35,7 +35,6 @@ import dmd.identifier; import dmd.location; import dmd.mtype; import dmd.opover; -import dmd.target; import dmd.tokens; import dmd.typesem; import dmd.typinf; @@ -149,126 +148,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration return "struct"; } - override final void finalizeSize() - { - //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - assert(sizeok != Sizeok.done); - - if (sizeok == Sizeok.inProcess) - { - return; - } - sizeok = Sizeok.inProcess; - - //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok); - - fields.setDim(0); // workaround - - // Set the offsets of the fields and determine the size of the struct - FieldState fieldState; - bool isunion = isUnionDeclaration() !is null; - for (size_t i = 0; i < members.length; i++) - { - Dsymbol s = (*members)[i]; - s.setFieldOffset(this, &fieldState, isunion); - } - if (type.ty == Terror) - { - errors = true; - return; - } - - if (structsize == 0) - { - hasNoFields = true; - alignsize = 1; - - // A fine mess of what size a zero sized struct should be - final switch (classKind) - { - case ClassKind.d: - case ClassKind.cpp: - structsize = 1; - break; - - case ClassKind.c: - case ClassKind.objc: - if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS) - { - /* Undocumented MS behavior for: - * struct S { int :0; }; - */ - structsize = 4; - } - else - structsize = 0; - break; - } - } - - // Round struct size up to next alignsize boundary. - // This will ensure that arrays of structs will get their internals - // aligned properly. - if (alignment.isDefault() || alignment.isPack()) - structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - else - structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1); - - sizeok = Sizeok.done; - - //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize); - - if (errors) - return; - - // Calculate fields[i].overlapped - if (checkOverlappedFields()) - { - errors = true; - return; - } - - // Determine if struct is all zeros or not - zeroInit = true; - auto lastOffset = -1; - foreach (vd; fields) - { - // First skip zero sized fields - if (vd.type.size(vd.loc) == 0) - continue; - - // only consider first sized member of an (anonymous) union - if (vd.overlapped && vd.offset == lastOffset) - continue; - lastOffset = vd.offset; - - if (vd._init) - { - if (vd._init.isVoidInitializer()) - /* Treat as 0 for the purposes of putting the initializer - * in the BSS segment, or doing a mass set to 0 - */ - continue; - - // Examine init to see if it is all 0s. - auto exp = vd.getConstInitializer(); - if (!exp || !_isZeroInit(exp)) - { - zeroInit = false; - break; - } - } - else if (!vd.type.isZeroInit(loc)) - { - zeroInit = false; - break; - } - } - - - argTypes = target.toArgTypes(type); - } - /// Compute cached type properties for `TypeStruct` extern(D) final void determineTypeProperties() { diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index 4395ff81ab08..1dffd2d1f87a 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -7720,3 +7720,377 @@ private Expression callScopeDtor(VarDeclaration vd, Scope* sc) } return e; } + +/*************************************** + * Collect all instance fields, then determine instance size. + * Returns: + * false if failed to determine the size. + */ +bool determineSize(AggregateDeclaration ad, const ref Loc loc) +{ + //printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok); + + // The previous instance size finalizing had: + if (ad.type.ty == Terror || ad.errors) + return false; // failed already + if (ad.sizeok == Sizeok.done) + return true; // succeeded + + if (!ad.members) + { + .error(loc, "%s `%s` unknown size", ad.kind, ad.toPrettyChars); + return false; + } + + if (ad._scope) + dsymbolSemantic(ad, null); + + // Determine the instance size of base class first. + if (auto cd = ad.isClassDeclaration()) + { + cd = cd.baseClass; + if (cd && !cd.determineSize(loc)) + goto Lfail; + } + + // Determine instance fields when sizeok == Sizeok.none + if (!ad.determineFields()) + goto Lfail; + if (ad.sizeok != Sizeok.done) + finalizeSize(ad); + + // this aggregate type has: + if (ad.type.ty == Terror) + return false; // marked as invalid during the finalizing. + if (ad.sizeok == Sizeok.done) + return true; // succeeded to calculate instance size. + +Lfail: + // There's unresolvable forward reference. + if (ad.type != Type.terror) + error(loc, "%s `%s` no size because of forward reference", ad.kind, ad.toPrettyChars); + // Don't cache errors from speculative semantic, might be resolvable later. + // https://issues.dlang.org/show_bug.cgi?id=16574 + if (!global.gag) + { + ad.type = Type.terror; + ad.errors = true; + } + return false; +} + +private void finalizeSize(AggregateDeclaration ad) +{ + if (StructDeclaration sd = ad.isStructDeclaration()) + finalizeSize(sd); + else if (ClassDeclaration cd = ad.isClassDeclaration()) + finalizeSize(cd); +} +private void finalizeSize(StructDeclaration sd) +{ + //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); + assert(sd.sizeok != Sizeok.done); + + if (sd.sizeok == Sizeok.inProcess) + { + return; + } + sd.sizeok = Sizeok.inProcess; + + //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok); + + sd.fields.setDim(0); // workaround + + // Set the offsets of the fields and determine the size of the struct + FieldState fieldState; + bool isunion = sd.isUnionDeclaration() !is null; + for (size_t i = 0; i < sd.members.length; i++) + { + Dsymbol s = (*sd.members)[i]; + s.setFieldOffset(sd, &fieldState, isunion); + } + if (sd.type.ty == Terror) + { + sd.errors = true; + return; + } + + if (sd.structsize == 0) + { + sd.hasNoFields = true; + sd.alignsize = 1; + + // A fine mess of what size a zero sized struct should be + final switch (sd.classKind) + { + case ClassKind.d: + case ClassKind.cpp: + sd.structsize = 1; + break; + + case ClassKind.c: + case ClassKind.objc: + if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS) + { + /* Undocumented MS behavior for: + * struct S { int :0; }; + */ + sd.structsize = 4; + } + else + sd.structsize = 0; + break; + } + } + + // Round struct size up to next alignsize boundary. + // This will ensure that arrays of structs will get their internals + // aligned properly. + if (sd.alignment.isDefault() || sd.alignment.isPack()) + sd.structsize = (sd.structsize + sd.alignsize - 1) & ~(sd.alignsize - 1); + else + sd.structsize = (sd.structsize + sd.alignment.get() - 1) & ~(sd.alignment.get() - 1); + + sd.sizeok = Sizeok.done; + + //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize); + + if (sd.errors) + return; + + // Calculate fields[i].overlapped + if (sd.checkOverlappedFields()) + { + sd.errors = true; + return; + } + + // Determine if struct is all zeros or not + sd.zeroInit = true; + auto lastOffset = -1; + foreach (vd; sd.fields) + { + // First skip zero sized fields + if (vd.type.size(vd.loc) == 0) + continue; + + // only consider first sized member of an (anonymous) union + if (vd.overlapped && vd.offset == lastOffset) + continue; + lastOffset = vd.offset; + + if (vd._init) + { + if (vd._init.isVoidInitializer()) + /* Treat as 0 for the purposes of putting the initializer + * in the BSS segment, or doing a mass set to 0 + */ + continue; + + // Examine init to see if it is all 0s. + auto exp = vd.getConstInitializer(); + if (!exp || !_isZeroInit(exp)) + { + sd.zeroInit = false; + break; + } + } + else if (!vd.type.isZeroInit(sd.loc)) + { + sd.zeroInit = false; + break; + } + } + sd.argTypes = target.toArgTypes(sd.type); +} +private void finaliseSize(ClassDeclaration cd) +{ + assert(cd.sizeok != Sizeok.done); + + // Set the offsets of the fields and determine the size of the class + if (cd.baseClass) + { + assert(cd.baseClass.sizeok == Sizeok.done); + + cd.alignsize = cd.baseClass.alignsize; + if (cd.classKind == ClassKind.cpp) + cd.structsize = target.cpp.derivedClassOffset(cd.baseClass); + else + cd.structsize = cd.baseClass.structsize; + } + else if (cd.classKind == ClassKind.objc) + cd.structsize = 0; // no hidden member for an Objective-C class + else if (cd.isInterfaceDeclaration()) + { + if (cd.interfaces.length == 0) + { + cd.alignsize = target.ptrsize; + cd.structsize = target.ptrsize; // allow room for __vptr + } + } + else + { + cd.alignsize = target.ptrsize; + cd.structsize = target.ptrsize; // allow room for __vptr + if (cd.hasMonitor()) + cd.structsize += target.ptrsize; // allow room for __monitor + } + + //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); + size_t bi = 0; // index into vtblInterfaces[] + + /**** + * Runs through the inheritance graph to set the BaseClass.offset fields. + * Recursive in order to account for the size of the interface classes, if they are + * more than just interfaces. + * Params: + * cd = interface to look at + * baseOffset = offset of where cd will be placed + * Returns: + * subset of instantiated size used by cd for interfaces + */ + uint membersPlace(ClassDeclaration cd, uint baseOffset) + { + //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset); + uint offset = baseOffset; + + foreach (BaseClass* b; cd.interfaces) + { + if (b.sym.sizeok != Sizeok.done) + b.sym.finalizeSize(); + assert(b.sym.sizeok == Sizeok.done); + + if (!b.sym.alignsize) + b.sym.alignsize = target.ptrsize; + offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset); + assert(bi < cd.vtblInterfaces.length); + + BaseClass* bv = (*cd.vtblInterfaces)[bi]; + if (b.sym.interfaces.length == 0) + { + //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset); + bv.offset = offset; + ++bi; + // All the base interfaces down the left side share the same offset + for (BaseClass* b2 = bv; b2.baseInterfaces.length; ) + { + b2 = &b2.baseInterfaces[0]; + b2.offset = offset; + //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset); + } + } + membersPlace(b.sym, offset); + //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize); + offset += b.sym.structsize; + if (cd.alignsize < b.sym.alignsize) + cd.alignsize = b.sym.alignsize; + } + return offset - baseOffset; + } + + cd.structsize += membersPlace(cd, cd.structsize); + + if (cd.isInterfaceDeclaration()) + { + cd.sizeok = Sizeok.done; + return; + } + + // FIXME: Currently setFieldOffset functions need to increase fields + // to calculate each variable offsets. It can be improved later. + cd.fields.setDim(0); + + FieldState fieldState; + fieldState.offset = cd.structsize; + foreach (s; *cd.members) + { + s.setFieldOffset(cd, &fieldState, false); + } + + cd.sizeok = Sizeok.done; + + // Calculate fields[i].overlapped + cd.checkOverlappedFields(); +} + +/*************************************** + * Calculate field[i].overlapped and overlapUnsafe, and check that all of explicit + * field initializers have unique memory space on instance. + * Returns: + * true if any errors happen. + */ +private bool checkOverlappedFields(AggregateDeclaration ad) +{ + //printf("AggregateDeclaration::checkOverlappedFields() %s\n", toChars()); + assert(ad.sizeok == Sizeok.done); + size_t nfields = ad.fields.length; + if (ad.isNested()) + { + auto cd = ad.isClassDeclaration(); + if (!cd || !cd.baseClass || !cd.baseClass.isNested()) + nfields--; + if (cd.vthis2 && !(cd && cd.baseClass && cd.baseClass.vthis2)) + nfields--; + } + bool errors = false; + + // Fill in missing any elements with default initializers + foreach (i; 0 .. nfields) + { + auto vd = ad.fields[i]; + if (vd.errors) + { + errors = true; + continue; + } + + const vdIsVoidInit = vd._init && vd._init.isVoidInitializer(); + + // Find overlapped fields with the hole [vd.offset .. vd.offset.size()]. + foreach (j; 0 .. nfields) + { + if (i == j) + continue; + auto v2 = ad.fields[j]; + if (v2.errors) + { + errors = true; + continue; + } + if (!vd.isOverlappedWith(v2)) + continue; + + // vd and v2 are overlapping. + vd.overlapped = true; + v2.overlapped = true; + + if (!MODimplicitConv(vd.type.mod, v2.type.mod)) + v2.overlapUnsafe = true; + if (!MODimplicitConv(v2.type.mod, vd.type.mod)) + vd.overlapUnsafe = true; + + if (i > j) + continue; + + if (!v2._init) + continue; + + if (v2._init.isVoidInitializer()) + continue; + + if (vd._init && !vdIsVoidInit && v2._init) + { + .error(ad.loc, "overlapping default initialization for field `%s` and `%s`", v2.toChars(), vd.toChars()); + errors = true; + } + else if (v2._init && i < j) + { + .error(v2.loc, "union field `%s` with default initialization `%s` must be before field `%s`", + v2.toChars(), dmd.hdrgen.toChars(v2._init), vd.toChars()); + errors = true; + } + } + } + return errors; +} + diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index e5daa3ae1eda..8f7473453830 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -6145,7 +6145,6 @@ class AggregateDeclaration : public ScopeDsymbol bool disableNew; Sizeok sizeok; virtual Scope* newScope(Scope* sc); - virtual void finalizeSize() = 0; uinteger_t size(const Loc& loc) final override; bool fill(const Loc& loc, Array& elements, bool ctorinit); Type* getType() final override; @@ -6528,7 +6527,6 @@ class ClassDeclaration : public AggregateDeclaration virtual bool isBaseOf(ClassDeclaration* cd, int32_t* poffset); bool isBaseInfoComplete() const; - void finalizeSize() final override; bool hasMonitor(); bool isFuncHidden(FuncDeclaration* fd); bool isCOMclass() const; @@ -7285,7 +7283,6 @@ class StructDeclaration : public AggregateDeclaration static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject); StructDeclaration* syntaxCopy(Dsymbol* s) override; const char* kind() const override; - void finalizeSize() final override; bool isPOD(); bool hasCopyConstruction(); StructDeclaration* isStructDeclaration() final override; diff --git a/compiler/src/dmd/mtype.d b/compiler/src/dmd/mtype.d index 7243a9998cca..f890bd8899ef 100644 --- a/compiler/src/dmd/mtype.d +++ b/compiler/src/dmd/mtype.d @@ -26,6 +26,7 @@ import dmd.declaration; import dmd.denum; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem : determineSize; import dmd.dtemplate; import dmd.enumsem; import dmd.errors; diff --git a/compiler/src/dmd/safe.d b/compiler/src/dmd/safe.d index bb4e3f49873b..24d874585516 100644 --- a/compiler/src/dmd/safe.d +++ b/compiler/src/dmd/safe.d @@ -21,6 +21,7 @@ import dmd.dcast : implicitConvTo; import dmd.dclass; import dmd.declaration; import dmd.dscope; +import dmd.dsymbolsem : determineSize; import dmd.errors; import dmd.expression; import dmd.func;