diff --git a/compiler/src/dmd/aggregate.d b/compiler/src/dmd/aggregate.d index 982e914f9dd3..becc864b4de4 100644 --- a/compiler/src/dmd/aggregate.d +++ b/compiler/src/dmd/aggregate.d @@ -25,7 +25,7 @@ import dmd.declaration; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, determineFields, search; +import dmd.dsymbolsem : dsymbolSemantic, determineFields, search, determineSize; import dmd.dtemplate; import dmd.errors; import dmd.expression; @@ -187,70 +187,12 @@ 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; } diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index e7e054930cc1..c2f8bdfc036f 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -7647,3 +7647,61 @@ 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) + ad.finalizeSize(); + + // 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; +} diff --git a/compiler/src/dmd/mtype.d b/compiler/src/dmd/mtype.d index 7243a9998cca..d40b92b17a1a 100644 --- a/compiler/src/dmd/mtype.d +++ b/compiler/src/dmd/mtype.d @@ -30,6 +30,7 @@ import dmd.dtemplate; import dmd.enumsem; import dmd.errors; import dmd.expression; +import dmd.dsymbolsem : determineSize; import dmd.globals; import dmd.hdrgen; import dmd.id; 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;