diff options
Diffstat (limited to 'gcc/d/dmd/dstruct.d')
-rw-r--r-- | gcc/d/dmd/dstruct.d | 220 |
1 files changed, 53 insertions, 167 deletions
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index df4d07a..d07be2f 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -3,12 +3,12 @@ * * Specification: $(LINK2 https://dlang.org/spec/struct.html, Structs, Unions) * - * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dstruct.d, _dstruct.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dstruct.d, _dstruct.d) * Documentation: https://dlang.org/phobos/dmd_dstruct.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dstruct.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dstruct.d */ module dmd.dstruct; @@ -23,11 +23,12 @@ import dmd.declaration; import dmd.dmodule; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem; +import dmd.dsymbolsem : search, setFieldOffset; import dmd.dtemplate; import dmd.errors; import dmd.expression; import dmd.func; +import dmd.funcsem; import dmd.globals; import dmd.id; import dmd.identifier; @@ -36,7 +37,7 @@ import dmd.mtype; import dmd.opover; import dmd.target; import dmd.tokens; -import dmd.typesem; +import dmd.typesem : isZeroInit, merge, size, hasPointers; import dmd.typinf; import dmd.visitor; @@ -65,126 +66,6 @@ FuncDeclaration search_toString(StructDeclaration sd) return fd; } -/*************************************** - * Request additional semantic analysis for TypeInfo generation. - * Params: - * sc = context - * t = type that TypeInfo is being generated for - */ -extern (D) void semanticTypeInfo(Scope* sc, Type t) -{ - if (sc) - { - if (sc.intypeof) - return; - if (!sc.needsCodegen()) - return; - } - - if (!t) - return; - - void visitVector(TypeVector t) - { - semanticTypeInfo(sc, t.basetype); - } - - void visitAArray(TypeAArray t) - { - semanticTypeInfo(sc, t.index); - semanticTypeInfo(sc, t.next); - } - - void visitStruct(TypeStruct t) - { - //printf("semanticTypeInfo.visit(TypeStruct = %s)\n", t.toChars()); - StructDeclaration sd = t.sym; - - /* Step 1: create TypeInfoDeclaration - */ - if (!sc) // inline may request TypeInfo. - { - Scope scx; - scx.eSink = global.errorSink; - scx._module = sd.getModule(); - getTypeInfoType(sd.loc, t, &scx); - sd.requestTypeInfo = true; - } - else if (!sc.minst) - { - // don't yet have to generate TypeInfo instance if - // the typeid(T) expression exists in speculative scope. - } - else - { - getTypeInfoType(sd.loc, t, sc); - sd.requestTypeInfo = true; - - // https://issues.dlang.org/show_bug.cgi?id=15149 - // if the typeid operand type comes from a - // result of auto function, it may be yet speculative. - // unSpeculative(sc, sd); - } - - /* Step 2: If the TypeInfo generation requires sd.semantic3, run it later. - * This should be done even if typeid(T) exists in speculative scope. - * Because it may appear later in non-speculative scope. - */ - if (!sd.members) - return; // opaque struct - if (!sd.xeq && !sd.xcmp && !sd.postblit && !sd.tidtor && !sd.xhash && !search_toString(sd)) - return; // none of TypeInfo-specific members - - // If the struct is in a non-root module, run semantic3 to get - // correct symbols for the member function. - if (sd.semanticRun >= PASS.semantic3) - { - // semantic3 is already done - } - else if (TemplateInstance ti = sd.isInstantiated()) - { - if (ti.minst && !ti.minst.isRoot()) - Module.addDeferredSemantic3(sd); - } - else - { - if (sd.inNonRoot()) - { - //printf("deferred sem3 for TypeInfo - sd = %s, inNonRoot = %d\n", sd.toChars(), sd.inNonRoot()); - Module.addDeferredSemantic3(sd); - } - } - } - - void visitTuple(TypeTuple t) - { - if (t.arguments) - { - foreach (arg; *t.arguments) - { - semanticTypeInfo(sc, arg.type); - } - } - } - - /* Note structural similarity of this Type walker to that in isSpeculativeType() - */ - - Type tb = t.toBasetype(); - switch (tb.ty) - { - case Tvector: visitVector(tb.isTypeVector()); break; - case Taarray: visitAArray(tb.isTypeAArray()); break; - case Tstruct: visitStruct(tb.isTypeStruct()); break; - case Ttuple: visitTuple (tb.isTypeTuple()); break; - - case Tclass: - case Tenum: break; - - default: semanticTypeInfo(sc, tb.nextOf()); break; - } -} - enum StructFlags : int { none = 0x0, @@ -220,9 +101,10 @@ extern (C++) class StructDeclaration : AggregateDeclaration bool hasIdentityEquals; // true if has identity opEquals bool hasNoFields; // has no fields bool hasCopyCtor; // copy constructor + bool hasMoveCtor; // move constructor bool hasPointerField; // members with indirections bool hasVoidInitPointers; // void-initialized unsafe fields - bool hasSystemFields; // @system members + bool hasUnsafeBitpatterns; // @system members, pointers, bool bool hasFieldWithInvariant; // invariants bool computedTypeProperties;// the above 3 fields are computed // Even if struct is defined as non-root symbol, some built-in operations @@ -234,9 +116,10 @@ extern (C++) class StructDeclaration : AggregateDeclaration import dmd.common.bitfields : generateBitFields; mixin(generateBitFields!(BitFields, ushort)); - extern (D) this(const ref Loc loc, Identifier id, bool inObject) + extern (D) this(Loc loc, Identifier id, bool inObject) { super(loc, id); + this.dsym = DSYM.structDeclaration; zeroInit = false; // assume false until we do semantic processing ispod = ThreeState.none; // For forward references @@ -249,7 +132,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration } } - static StructDeclaration create(const ref Loc loc, Identifier id, bool inObject) + static StructDeclaration create(Loc loc, Identifier id, bool inObject) { return new StructDeclaration(loc, id, inObject); } @@ -290,11 +173,12 @@ extern (C++) class StructDeclaration : AggregateDeclaration { Dsymbol s = (*members)[i]; s.setFieldOffset(this, &fieldState, isunion); - } - if (type.ty == Terror) - { - errors = true; - return; + if (type.ty == Terror) + { + errorSupplemental(s.loc, "error on member `%s`", s.toPrettyChars); + errors = true; + return; + } } if (structsize == 0) @@ -319,11 +203,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration */ structsize = 4; } - else if (target.c.bitFieldStyle == TargetC.BitFieldStyle.DM) - { - structsize = 0; - alignsize = 0; - } else structsize = 0; break; @@ -354,8 +233,18 @@ extern (C++) class StructDeclaration : AggregateDeclaration // 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()) @@ -364,10 +253,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration */ continue; - // Zero size fields are zero initialized - if (vd.type.size(vd.loc) == 0) - continue; - // Examine init to see if it is all 0s. auto exp = vd.getConstInitializer(); if (!exp || !_isZeroInit(exp)) @@ -395,13 +280,16 @@ extern (C++) class StructDeclaration : AggregateDeclaration foreach (vd; fields) { if (vd.storage_class & STC.ref_ || vd.hasPointers()) + { hasPointerField = true; + hasUnsafeBitpatterns = true; + } if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers()) hasVoidInitPointers = true; - if (vd.storage_class & STC.system || vd.type.hasSystemFields()) - hasSystemFields = true; + if (vd.storage_class & STC.system || vd.type.hasUnsafeBitpatterns()) + hasUnsafeBitpatterns = true; if (!vd._init && vd.type.hasVoidInitPointers()) hasVoidInitPointers = true; @@ -432,13 +320,22 @@ extern (C++) class StructDeclaration : AggregateDeclaration if (ispod != ThreeState.none) return (ispod == ThreeState.yes); - ispod = ThreeState.yes; - import dmd.clone; - bool hasCpCtorLocal; - needCopyCtor(this, hasCpCtorLocal); - if (enclosing || search(this, loc, Id.postblit) || search(this, loc, Id.dtor) || hasCpCtorLocal) + bool hasCpCtorLocal; + bool hasMoveCtorLocal; + bool needCopyCtor; + bool needMoveCtor; + needCopyOrMoveCtor(this, hasCpCtorLocal, hasMoveCtorLocal, needCopyCtor, needMoveCtor); + + if (enclosing || // is nested + search(this, loc, Id.postblit) || // has postblit + search(this, loc, Id.dtor) || // has destructor + /* This is commented out because otherwise buildkite vibe.d: + `canCAS!Task` fails to compile + */ + //hasMoveCtorLocal || // has move constructor + hasCpCtorLocal) // has copy constructor { ispod = ThreeState.no; return false; @@ -454,12 +351,9 @@ extern (C++) class StructDeclaration : AggregateDeclaration return false; } - Type tv = v.type.baseElemOf(); - if (tv.ty == Tstruct) + if (auto ts = v.type.baseElemOf().isTypeStruct()) { - TypeStruct ts = cast(TypeStruct)tv; - StructDeclaration sd = ts.sym; - if (!sd.isPOD()) + if (!ts.sym.isPOD()) { ispod = ThreeState.no; return false; @@ -467,7 +361,8 @@ extern (C++) class StructDeclaration : AggregateDeclaration } } - return (ispod == ThreeState.yes); + ispod = ThreeState.yes; + return true; } /*************************************** @@ -480,11 +375,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration return postblit || hasCopyCtor; } - override final inout(StructDeclaration) isStructDeclaration() inout @nogc nothrow pure @safe - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -609,7 +499,7 @@ bool _isZeroInit(Expression exp) case EXP.string_: { - StringExp se = cast(StringExp)exp; + auto se = cast(StringExp)exp; if (se.type.toBasetype().ty == Tarray) // if initializing a dynamic array return se.len == 0; @@ -646,9 +536,10 @@ bool _isZeroInit(Expression exp) */ extern (C++) final class UnionDeclaration : StructDeclaration { - extern (D) this(const ref Loc loc, Identifier id) + extern (D) this(Loc loc, Identifier id) { super(loc, id, false); + this.dsym = DSYM.unionDeclaration; } override UnionDeclaration syntaxCopy(Dsymbol s) @@ -664,11 +555,6 @@ extern (C++) final class UnionDeclaration : StructDeclaration return "union"; } - override inout(UnionDeclaration) isUnionDeclaration() inout - { - return this; - } - override void accept(Visitor v) { v.visit(this); |