diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-01-05 14:24:49 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-01-05 14:24:49 +0100 |
commit | a676a516701789730aa482bcef4adcb683ba0140 (patch) | |
tree | 6c5b56d13162e537bae0ed373a9addf9be73af56 /gcc/d/dmd | |
parent | 3dfad340cb140d64b8c0ecab05fa329238ebd06b (diff) | |
download | gcc-a676a516701789730aa482bcef4adcb683ba0140.zip gcc-a676a516701789730aa482bcef4adcb683ba0140.tar.gz gcc-a676a516701789730aa482bcef4adcb683ba0140.tar.bz2 |
d: Merge upstream dmd, druntime 07bc5b9b3c, phobos de1dea109
Synchronizing with the upstream release of v2.109.0.
D front-end changes:
- Import dmd v2.109.0.
D runtime changes:
- Import druntime v2.109.0.
Phobos changes:
- Import phobos v2.109.0.
gcc/d/ChangeLog:
* decl.cc (DeclVisitor::finish_vtable): Update for new front-end
interface.
* dmd/MERGE: Merge upstream dmd 07bc5b9b3c.
* dmd/VERSION: Bump version to v2.109.0.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 07bc5b9b3c.
* src/MERGE: Merge upstream phobos de1dea109.
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r-- | gcc/d/dmd/MERGE | 2 | ||||
-rw-r--r-- | gcc/d/dmd/README.md | 2 | ||||
-rw-r--r-- | gcc/d/dmd/VERSION | 2 | ||||
-rw-r--r-- | gcc/d/dmd/cxxfrontend.d | 6 | ||||
-rw-r--r-- | gcc/d/dmd/declaration.h | 2 | ||||
-rw-r--r-- | gcc/d/dmd/dmodule.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/dstruct.d | 5 | ||||
-rw-r--r-- | gcc/d/dmd/dsymbolsem.d | 22 | ||||
-rw-r--r-- | gcc/d/dmd/dtemplate.d | 11 | ||||
-rw-r--r-- | gcc/d/dmd/enumsem.d | 5 | ||||
-rw-r--r-- | gcc/d/dmd/expression.h | 1 | ||||
-rw-r--r-- | gcc/d/dmd/expressionsem.d | 23 | ||||
-rw-r--r-- | gcc/d/dmd/func.d | 317 | ||||
-rw-r--r-- | gcc/d/dmd/funcsem.d | 377 | ||||
-rw-r--r-- | gcc/d/dmd/gluelayer.d | 6 | ||||
-rw-r--r-- | gcc/d/dmd/hdrgen.d | 3 | ||||
-rw-r--r-- | gcc/d/dmd/id.d | 3 | ||||
-rw-r--r-- | gcc/d/dmd/mtype.d | 13 | ||||
-rw-r--r-- | gcc/d/dmd/semantic3.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/statementsem.d | 5 | ||||
-rw-r--r-- | gcc/d/dmd/target.d | 5 | ||||
-rw-r--r-- | gcc/d/dmd/target.h | 5 | ||||
-rw-r--r-- | gcc/d/dmd/templatesem.d | 10 | ||||
-rw-r--r-- | gcc/d/dmd/traits.d | 11 | ||||
-rw-r--r-- | gcc/d/dmd/typesem.d | 40 |
25 files changed, 482 insertions, 398 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 46d435e..77e8562 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -c11e1d1708646c9ac81ac2aafb57fa1ef5d289ad +07bc5b9b3c81cc0d4314e0040de981124b363ea5 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md index d784d07..baac0d7 100644 --- a/gcc/d/dmd/README.md +++ b/gcc/d/dmd/README.md @@ -201,11 +201,9 @@ Note that these groups have no strict meaning, the category assignments are a bi | [libelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libelf.d) | Library in ELF format (Unix) | | [libmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmach.d) | Library in Mach-O format (macOS) | | [libmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmscoff.d) | Library in COFF format (32/64-bit Windows) | -| [libomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libomf.d) | Library in OMF format (legacy 32-bit Windows) | | [scanelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanelf.d) | Extract symbol names from a library in ELF format | | [scanmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmach.d) | Extract symbol names from a library in Mach-O format | | [scanmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmscoff.d) | Extract symbol names from a library in COFF format | -| [scanomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanomf.d) | Extract symbol names from a library in OMF format | ### Code generation / back-end interfacing diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION index 99582f5..3d80c3d 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.108.1 +v2.109.0 diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d index c0805b8..403588b 100644 --- a/gcc/d/dmd/cxxfrontend.d +++ b/gcc/d/dmd/cxxfrontend.d @@ -265,6 +265,12 @@ bool functionSemantic3(FuncDeclaration fd) return dmd.funcsem.functionSemantic3(fd); } +MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names) +{ + import dmd.funcsem; + return dmd.funcsem.leastAsSpecialized(f, g, names); +} + /*********************************************************** * hdrgen.d */ diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index 998beba9..fdfe8a8 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -34,6 +34,7 @@ namespace dmd { bool functionSemantic(FuncDeclaration* fd); bool functionSemantic3(FuncDeclaration* fd); + MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names); } //enum STC : ulong from astenums.d: @@ -706,7 +707,6 @@ public: bool overloadInsert(Dsymbol *s) override; bool inUnittest(); - static MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names); LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc); const char *toPrettyChars(bool QualifyTypes = false) override; const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure' diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index a1a337b..005f1c9 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -766,7 +766,7 @@ extern (C++) final class Module : Package { filetype = FileType.c; - global.compileEnv.masm = target.os == Target.OS.Windows && !target.omfobj; // Microsoft inline assembler format + global.compileEnv.masm = target.os == Target.OS.Windows; // Microsoft inline assembler format scope p = new CParser!AST(this, buf, cast(bool) docfile, global.errorSink, target.c, &defines, &global.compileEnv); global.compileEnv.masm = false; p.nextToken(); diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index 339b223..416bd57 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -320,11 +320,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration */ structsize = 4; } - else if (target.c.bitFieldStyle == TargetC.BitFieldStyle.DM) - { - structsize = 0; - alignsize = 0; - } else structsize = 0; break; diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 65a1b04..4a21b14 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -7259,25 +7259,6 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor return; } } - else if (style == TargetC.BitFieldStyle.DM) - { - if (anon && bfd.fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0)) - return; // this probably should be a bug in DMC - if (ad.alignsize == 0) - ad.alignsize = 1; - if (bfd.fieldWidth == 0) - { - if (fieldState.inFlight && !isunion) - { - const alsz = memsize; - fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); - ad.structsize = fieldState.offset; - } - - fieldState.inFlight = false; - return; - } - } if (!fieldState.inFlight) { @@ -7307,8 +7288,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor } } } - else if (style == TargetC.BitFieldStyle.DM || - style == TargetC.BitFieldStyle.MS) + else if (style == TargetC.BitFieldStyle.MS) { if (memsize != fieldState.fieldSize || fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8) diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index fb11821..33ec6b1 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -751,6 +751,17 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol return buf.extractChars(); } + /**************************** + * Similar to `toChars`, but does not print the template constraints + */ + const(char)* toCharsNoConstraints() const + { + HdrGenState hgs = { skipConstraints: true }; + OutBuffer buf; + toCharsMaybeConstraints(this, buf, hgs); + return buf.extractChars(); + } + override Visibility visible() pure nothrow @nogc @safe { return visibility; diff --git a/gcc/d/dmd/enumsem.d b/gcc/d/dmd/enumsem.d index 3886ca2..c67ac61 100644 --- a/gcc/d/dmd/enumsem.d +++ b/gcc/d/dmd/enumsem.d @@ -325,7 +325,10 @@ void enumSemantic(Scope* sc, EnumDeclaration ed) if (EnumMember em = s.isEnumMember()) { em.type = commonType; - em.value = em.value.castTo(sc, commonType); + // optimize out the cast so that other parts of the compiler can + // assume that an integral enum's members are `IntegerExp`s. + // https://issues.dlang.org/show_bug.cgi?id=24504 + em.value = em.value.castTo(sc, commonType).optimize(WANTvalue); } }); } diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 1ff6c4c..ad79281 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -889,6 +889,7 @@ public: // Possible to cast to one type while painting to another type Type *to; // type to cast to unsigned char mod; // MODxxxxx + d_bool trusted; // assume cast is safe CastExp *syntaxCopy() override; bool isLvalue() override; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 3502a1c..481806d 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -14306,14 +14306,16 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) if (auto te = exp.e1.isTupleExp()) { - if (exp.ident == Id.offsetof) + if (exp.ident == Id.offsetof || + exp.ident == Id.bitoffsetof || + exp.ident == Id.bitwidth) { /* 'distribute' the .offsetof to each of the tuple elements. */ auto exps = new Expressions(te.exps.length); foreach (i, e; (*te.exps)[]) { - (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof); + (*exps)[i] = new DotIdExp(e.loc, e, exp.ident); } // Don't evaluate te.e0 in runtime Expression e = new TupleExp(exp.loc, null, exps); @@ -14636,6 +14638,8 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag) !cfile && (exp.ident == Id._mangleof || exp.ident == Id.offsetof || + exp.ident == Id.bitoffsetof || + exp.ident == Id.bitwidth || exp.ident == Id._init || exp.ident == Id.stringof) )) @@ -15282,6 +15286,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) Expression visitStructLiteral(StructLiteralExp exp) { + if (!exp.elements) + return exp; + foreach (ref element; *exp.elements) { if (element) @@ -15300,6 +15307,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) if (exp.lowering) exp.lowering = exp.lowering.resolveLoc(loc, sc); + if (!exp.arguments) + return exp; + foreach (ref element; *exp.arguments) { if (element) @@ -15311,6 +15321,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) Expression visitCall(CallExp exp) { + if (!exp.arguments) + return exp; + foreach (ref element; *exp.arguments) { if (element) @@ -15324,6 +15337,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) { exp.e1 = exp.e1.resolveLoc(loc, sc); + if (!exp.arguments) + return exp; + foreach (ref element; *exp.arguments) { if (element) @@ -15357,6 +15373,9 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) if (exp.basis) exp.basis = exp.basis.resolveLoc(loc, sc); + if (!exp.elements) + return exp; + foreach (ref element; *exp.elements) { if (element) diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index f3d7aba..cb19b14 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -424,27 +424,6 @@ extern (C++) class FuncDeclaration : Declaration } /**************************************************** - * Determine if 'this' overrides fd. - * Return !=0 if it does. - */ - extern (D) final int overrides(FuncDeclaration fd) - { - int result = 0; - if (fd.ident == ident) - { - const cov = type.covariant(fd.type); - if (cov != Covariant.distinct) - { - ClassDeclaration cd1 = toParent().isClassDeclaration(); - ClassDeclaration cd2 = fd.toParent().isClassDeclaration(); - if (cd1 && cd2 && cd2.isBaseOf(cd1, null)) - result = 1; - } - } - return result; - } - - /**************************************************** * Overload this FuncDeclaration with the new one f. * Return true if successful; i.e. no conflict. */ @@ -547,91 +526,6 @@ extern (C++) class FuncDeclaration : Declaration return false; } - /************************************* - * Determine partial specialization order of functions `f` vs `g`. - * This is very similar to TemplateDeclaration::leastAsSpecialized(). - * Params: - * f = first function - * g = second function - * names = names of parameters - * Returns: - * match 'this' is at least as specialized as g - * 0 g is more specialized than 'this' - */ - static MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names) - { - enum LOG_LEASTAS = 0; - static if (LOG_LEASTAS) - { - import core.stdc.stdio : printf; - printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null"); - printf("%s, %s\n", f.type.toChars(), g.type.toChars()); - } - - /* This works by calling g() with f()'s parameters, and - * if that is possible, then f() is at least as specialized - * as g() is. - */ - - TypeFunction tf = f.type.toTypeFunction(); - TypeFunction tg = g.type.toTypeFunction(); - - /* If both functions have a 'this' pointer, and the mods are not - * the same and g's is not const, then this is less specialized. - */ - if (f.needThis() && g.needThis() && tf.mod != tg.mod) - { - if (f.isCtorDeclaration()) - { - if (!MODimplicitConv(tg.mod, tf.mod)) - return MATCH.nomatch; - } - else - { - if (!MODimplicitConv(tf.mod, tg.mod)) - return MATCH.nomatch; - } - } - - /* Create a dummy array of arguments out of the parameters to f() - */ - Expressions args; - foreach (u, p; tf.parameterList) - { - Expression e; - if (p.isReference()) - { - e = new IdentifierExp(Loc.initial, p.ident); - e.type = p.type; - } - else - e = p.type.defaultInitLiteral(Loc.initial); - args.push(e); - } - - MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1); - if (m > MATCH.nomatch) - { - /* A variadic parameter list is less specialized than a - * non-variadic one. - */ - if (tf.parameterList.varargs && !tg.parameterList.varargs) - goto L1; // less specialized - - static if (LOG_LEASTAS) - { - printf(" matches %d, so is least as specialized\n", m); - } - return m; - } - L1: - static if (LOG_LEASTAS) - { - printf(" doesn't match, so is not as specialized\n"); - } - return MATCH.nomatch; - } - /******************************** * Searches for a label with the given identifier. This function will insert a new * `LabelDsymbol` into `labtab` if it does not contain a mapping for `ident`. @@ -1607,27 +1501,6 @@ extern (C++) class FuncDeclaration : Declaration return false; } - /**************************************************** - * Determine whether an 'out' contract is declared inside - * the given function or any of its overrides. - * Params: - * fd = the function to search - * Returns: - * true found an 'out' contract - */ - static bool needsFensure(FuncDeclaration fd) @safe - { - if (fd.fensures) - return true; - - foreach (fdv; fd.foverrides) - { - if (needsFensure(fdv)) - return true; - } - return false; - } - /********************************************* * Returns: the function's parameter list, and whether * it is variadic or not. @@ -1684,179 +1557,6 @@ extern (C++) class FuncDeclaration : Declaration return fd; } - /+ - + Checks the parameter and return types iff this is a `main` function. - + - + The following signatures are allowed for a `D main`: - + - Either no or a single parameter of type `string[]` - + - Return type is either `void`, `int` or `noreturn` - + - + The following signatures are standard C: - + - `int main()` - + - `int main(int, char**)` - + - + This function accepts the following non-standard extensions: - + - `char** envp` as a third parameter - + - `void` / `noreturn` as return type - + - + This function will issue errors for unexpected arguments / return types. - +/ - extern (D) final void checkMain() - { - if (ident != Id.main || isMember() || isNested()) - return; // Not a main function - - TypeFunction tf = type.toTypeFunction(); - - Type retType = tf.nextOf(); - if (!retType) - { - // auto main(), check after semantic - assert(this.inferRetType); - return; - } - - /// Checks whether `t` is equivalent to `char**` - /// Ignores qualifiers and treats enums according to their base type - static bool isCharPtrPtr(Type t) - { - auto tp = t.toBasetype().isTypePointer(); - if (!tp) - return false; - - tp = tp.next.toBasetype().isTypePointer(); - if (!tp) - return false; - - return tp.next.toBasetype().ty == Tchar; - } - - // Neither of these qualifiers is allowed because they affect the ABI - enum invalidSTC = STC.out_ | STC.ref_ | STC.lazy_; - - const nparams = tf.parameterList.length; - bool argerr; - - const linkage = resolvedLinkage(); - if (linkage == LINK.d) - { - if (nparams == 1) - { - auto fparam0 = tf.parameterList[0]; - auto t = fparam0.type.toBasetype(); - if (t.ty != Tarray || - t.nextOf().ty != Tarray || - t.nextOf().nextOf().ty != Tchar || - fparam0.storageClass & invalidSTC) - { - argerr = true; - } - } - - if (tf.parameterList.varargs || nparams >= 2 || argerr) - .error(loc, "%s `%s` parameter list must be empty or accept one parameter of type `string[]`", kind, toPrettyChars); - } - - else if (linkage == LINK.c) - { - if (nparams == 2 || nparams == 3) - { - // Argument count must be int - auto argCount = tf.parameterList[0]; - argerr |= !!(argCount.storageClass & invalidSTC); - argerr |= argCount.type.toBasetype().ty != Tint32; - - // Argument pointer must be char** - auto argPtr = tf.parameterList[1]; - argerr |= !!(argPtr.storageClass & invalidSTC); - argerr |= !isCharPtrPtr(argPtr.type); - - // `char** environ` is a common extension, see J.5.1 of the C standard - if (nparams == 3) - { - auto envPtr = tf.parameterList[2]; - argerr |= !!(envPtr.storageClass & invalidSTC); - argerr |= !isCharPtrPtr(envPtr.type); - } - } - else - argerr = nparams != 0; - - // Disallow variadic main() - except for K&R declarations in C files. - // E.g. int main(), int main(argc, argv) int argc, char** argc { ... } - if (tf.parameterList.varargs && (!this.isCsymbol() || (!tf.parameterList.hasIdentifierList && nparams))) - argerr |= true; - - if (argerr) - { - .error(loc, "%s `%s` parameters must match one of the following signatures", kind, toPrettyChars); - loc.errorSupplemental("`main()`"); - loc.errorSupplemental("`main(int argc, char** argv)`"); - loc.errorSupplemental("`main(int argc, char** argv, char** environ)` [POSIX extension]"); - } - } - else - return; // Neither C nor D main, ignore (should probably be an error) - - // Allow enums with appropriate base types (same ABI) - retType = retType.toBasetype(); - - if (retType.ty != Tint32 && retType.ty != Tvoid && retType.ty != Tnoreturn) - .error(loc, "%s `%s` must return `int`, `void` or `noreturn`, not `%s`", kind, toPrettyChars, tf.nextOf().toChars()); - } - - /*********************************************** - * Check all return statements for a function to verify that returning - * using NRVO is possible. - * - * Returns: - * `false` if the result cannot be returned by hidden reference. - */ - extern (D) final bool checkNRVO() - { - if (!isNRVO() || returns is null) - return false; - - auto tf = type.toTypeFunction(); - if (tf.isref) - return false; - - foreach (rs; *returns) - { - if (auto ve = rs.exp.isVarExp()) - { - auto v = ve.var.isVarDeclaration(); - if (!v || v.isReference()) - return false; - else if (nrvo_var is null) - { - // Variables in the data segment (e.g. globals, TLS or not), - // parameters and closure variables cannot be NRVOed. - if (v.isDataseg() || v.isParameter() || v.toParent2() != this) - return false; - if (v.nestedrefs.length && needsClosure()) - return false; - // don't know if the return storage is aligned - version (MARS) - { - if (alignSectionVars && (*alignSectionVars).contains(v)) - return false; - } - // The variable type needs to be equivalent to the return type. - if (!v.type.equivalent(tf.next)) - return false; - //printf("Setting nrvo to %s\n", v.toChars()); - nrvo_var = v; - } - else if (nrvo_var != v) - return false; - } - else //if (!exp.isLvalue()) // keep NRVO-ability - return false; - } - return true; - } - override final inout(FuncDeclaration) isFuncDeclaration() inout { return this; @@ -2067,23 +1767,6 @@ unittest } /************************************** - * Returns an indirect type one step from t. - */ -Type getIndirection(Type t) -{ - t = t.baseElemOf(); - if (t.ty == Tarray || t.ty == Tpointer) - return t.nextOf().toBasetype(); - if (t.ty == Taarray || t.ty == Tclass) - return t; - if (t.ty == Tstruct) - return t.hasPointers() ? t : null; // TODO - - // should consider TypeDelegate? - return null; -} - -/************************************** * Performs type-based alias analysis between a newly created value and a pre- * existing memory reference: * diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d index e058deb..ee36a16 100644 --- a/gcc/d/dmd/funcsem.d +++ b/gcc/d/dmd/funcsem.d @@ -65,6 +65,10 @@ import dmd.tokens; import dmd.typesem; import dmd.visitor; +version (IN_GCC) {} +else version (IN_LLVM) {} +else version = MARS; + /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO. */ extern (C++) final class NrvoWalker : StatementRewriteWalker @@ -742,7 +746,10 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) { if (fdv.isFuture()) { - deprecation(funcdecl.loc, "`@__future` base class method `%s` is being overridden by `%s`; rename the latter", fdv.toPrettyChars(), funcdecl.toPrettyChars()); + deprecation(funcdecl.loc, "method `%s` implicitly overrides `@__future` base class method; rename the former", + funcdecl.toPrettyChars()); + deprecationSupplemental(fdv.loc, "base method `%s` defined here", + fdv.toPrettyChars()); // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[] goto Lintro; } @@ -1743,10 +1750,24 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) // max num of overloads to print (-v or -verror-supplements overrides this). const uint DisplayLimit = global.params.v.errorSupplementCount(); const(char)* constraintsTip; - // determine if the first candidate was printed - int printed; - bool matchSymbol(Dsymbol s, bool print, bool single_candidate = false) + int printed = 0; // number of candidates printed + int count = 0; // total candidates + bool child; // true if inside an eponymous template + const(char)* errorPrefix() @safe + { + if (child) + return " - Containing: "; + + // align with blank spaces after first message + enum plural = "Candidates are: "; + enum spaces = " "; + if (printed) + return spaces; + + return (count == 1) ? "Candidate is: " : plural; + } + bool matchSymbol(Dsymbol s, bool print) { if (auto fd = s.isFuncDeclaration()) { @@ -1762,16 +1783,14 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) return true; auto tf = cast(TypeFunction) fd.type; OutBuffer buf; - buf.writestring(fd.toPrettyChars()); + buf.writestring(child ? fd.toChars() : fd.toPrettyChars()); buf.writestring(parametersTypeToChars(tf.parameterList)); if (tf.mod) { buf.writeByte(' '); buf.MODtoBuffer(tf.mod); } - .errorSupplemental(fd.loc, - printed ? " `%s`" : - single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars()); + .errorSupplemental(fd.loc, "%s`%s`", errorPrefix(), buf.peekChars()); } else if (auto td = s.isTemplateDeclaration()) { @@ -1779,35 +1798,43 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) if (!print) return true; + + // td.onemember may not have overloads set + // (see fail_compilation/onemember_overloads.d) + // assume if more than one member it is overloaded internally + bool recurse = td.onemember && td.members.length > 1; OutBuffer buf; HdrGenState hgs; hgs.skipConstraints = true; + hgs.showOneMember = !recurse; toCharsMaybeConstraints(td, buf, hgs); const tmsg = buf.peekChars(); - const cmsg = td.getConstraintEvalError(constraintsTip); - - // add blank space if there are multiple candidates - // the length of the blank space is `strlen("Candidates are: ")` + const cmsg = child ? null : td.getConstraintEvalError(constraintsTip); if (cmsg) - { - .errorSupplemental(td.loc, - printed ? " `%s`\n%s" : - single_candidate ? "Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s", - tmsg, cmsg); - } + .errorSupplemental(td.loc, "%s`%s`\n%s", errorPrefix(), tmsg, cmsg); else + .errorSupplemental(td.loc, "%s`%s`", errorPrefix(), tmsg); + + if (recurse) { - .errorSupplemental(td.loc, - printed ? " `%s`" : - single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", - tmsg); + child = true; + foreach (d; *td.members) + { + if (d.ident != td.ident) + continue; + + if (auto fd2 = d.isFuncDeclaration()) + matchSymbol(fd2, print); + else if (auto td2 = d.isTemplateDeclaration()) + matchSymbol(td2, print); + } + child = false; } } return true; } // determine if there's > 1 candidate - int count = 0; overloadApply(declaration, (s) { if (matchSymbol(s, false)) count++; @@ -1817,7 +1844,7 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) overloadApply(declaration, (s) { if (global.params.v.verbose || printed < DisplayLimit) { - if (matchSymbol(s, true, count == 1)) + if (matchSymbol(s, true)) printed++; } else @@ -1928,6 +1955,112 @@ FuncDeclaration overloadExactMatch(FuncDeclaration thisfd, Type t) return fd; } +/**************************************************** + * Determine if fd1 overrides fd2. + * Return !=0 if it does. + */ +int overrides(FuncDeclaration fd1, FuncDeclaration fd2) +{ + int result = 0; + if (fd1.ident == fd2.ident) + { + const cov = fd1.type.covariant(fd2.type); + if (cov != Covariant.distinct) + { + ClassDeclaration cd1 = fd1.toParent().isClassDeclaration(); + ClassDeclaration cd2 = fd2.toParent().isClassDeclaration(); + if (cd1 && cd2 && cd2.isBaseOf(cd1, null)) + result = 1; + } + } + return result; +} + +/************************************* + * Determine partial specialization order of functions `f` vs `g`. + * This is very similar to TemplateDeclaration::leastAsSpecialized(). + * Params: + * f = first function + * g = second function + * names = names of parameters + * Returns: + * match 'this' is at least as specialized as g + * 0 g is more specialized than 'this' + */ +MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names) +{ + enum LOG_LEASTAS = 0; + static if (LOG_LEASTAS) + { + import core.stdc.stdio : printf; + printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null"); + printf("%s, %s\n", f.type.toChars(), g.type.toChars()); + } + + /* This works by calling g() with f()'s parameters, and + * if that is possible, then f() is at least as specialized + * as g() is. + */ + + TypeFunction tf = f.type.toTypeFunction(); + TypeFunction tg = g.type.toTypeFunction(); + + /* If both functions have a 'this' pointer, and the mods are not + * the same and g's is not const, then this is less specialized. + */ + if (f.needThis() && g.needThis() && tf.mod != tg.mod) + { + if (f.isCtorDeclaration()) + { + if (!MODimplicitConv(tg.mod, tf.mod)) + return MATCH.nomatch; + } + else + { + if (!MODimplicitConv(tf.mod, tg.mod)) + return MATCH.nomatch; + } + } + + /* Create a dummy array of arguments out of the parameters to f() + */ + Expressions args; + foreach (u, p; tf.parameterList) + { + Expression e; + if (p.isReference()) + { + e = new IdentifierExp(Loc.initial, p.ident); + e.type = p.type; + } + else + e = p.type.defaultInitLiteral(Loc.initial); + args.push(e); + } + + MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1); + if (m > MATCH.nomatch) + { + /* A variadic parameter list is less specialized than a + * non-variadic one. + */ + if (tf.parameterList.varargs && !tg.parameterList.varargs) + goto L1; // less specialized + + static if (LOG_LEASTAS) + { + printf(" matches %d, so is least as specialized\n", m); + } + return m; + } +L1: + static if (LOG_LEASTAS) + { + printf(" doesn't match, so is not as specialized\n"); + } + return MATCH.nomatch; +} + /******************************************** * Find function in overload list that matches to the 'this' modifier. * There's four result types. @@ -2494,6 +2627,27 @@ void buildEnsureRequire(FuncDeclaration thisfd) } /**************************************************** + * Determine whether an 'out' contract is declared inside + * the given function or any of its overrides. + * Params: + * fd = the function to search + * Returns: + * true found an 'out' contract + */ +bool needsFensure(FuncDeclaration fd) @safe +{ + if (fd.fensures) + return true; + + foreach (fdv; fd.foverrides) + { + if (needsFensure(fdv)) + return true; + } + return false; +} + +/**************************************************** * Merge into this function the 'out' contracts of all it overrides. * 'out's are AND'd together, i.e. all of them need to pass. */ @@ -2515,7 +2669,7 @@ Statement mergeFensure(FuncDeclaration fd, Statement sf, Identifier oid, Express * https://issues.dlang.org/show_bug.cgi?id=3602 and * https://issues.dlang.org/show_bug.cgi?id=5230 */ - if (fd.needsFensure(fdv) && fdv.semanticRun != PASS.semantic3done) + if (needsFensure(fdv) && fdv.semanticRun != PASS.semantic3done) { assert(fdv._scope); Scope* sc = fdv._scope.push(); @@ -2735,3 +2889,176 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char) return false; } } + +/+ + + Checks the parameter and return types iff this is a `main` function. + + + + The following signatures are allowed for a `D main`: + + - Either no or a single parameter of type `string[]` + + - Return type is either `void`, `int` or `noreturn` + + + + The following signatures are standard C: + + - `int main()` + + - `int main(int, char**)` + + + + This function accepts the following non-standard extensions: + + - `char** envp` as a third parameter + + - `void` / `noreturn` as return type + + + + This function will issue errors for unexpected arguments / return types. + +/ +extern (D) void checkMain(FuncDeclaration fd) +{ + if (fd.ident != Id.main || fd.isMember() || fd.isNested()) + return; // Not a main function + + TypeFunction tf = fd.type.toTypeFunction(); + + Type retType = tf.nextOf(); + if (!retType) + { + // auto main(), check after semantic + assert(fd.inferRetType); + return; + } + + /// Checks whether `t` is equivalent to `char**` + /// Ignores qualifiers and treats enums according to their base type + static bool isCharPtrPtr(Type t) + { + auto tp = t.toBasetype().isTypePointer(); + if (!tp) + return false; + + tp = tp.next.toBasetype().isTypePointer(); + if (!tp) + return false; + + return tp.next.toBasetype().ty == Tchar; + } + + // Neither of these qualifiers is allowed because they affect the ABI + enum invalidSTC = STC.out_ | STC.ref_ | STC.lazy_; + + const nparams = tf.parameterList.length; + bool argerr; + + const linkage = fd.resolvedLinkage(); + if (linkage == LINK.d) + { + if (nparams == 1) + { + auto fparam0 = tf.parameterList[0]; + auto t = fparam0.type.toBasetype(); + if (t.ty != Tarray || + t.nextOf().ty != Tarray || + t.nextOf().nextOf().ty != Tchar || + fparam0.storageClass & invalidSTC) + { + argerr = true; + } + } + + if (tf.parameterList.varargs || nparams >= 2 || argerr) + .error(fd.loc, "%s `%s` parameter list must be empty or accept one parameter of type `string[]`", fd.kind, fd.toPrettyChars); + } + + else if (linkage == LINK.c) + { + if (nparams == 2 || nparams == 3) + { + // Argument count must be int + auto argCount = tf.parameterList[0]; + argerr |= !!(argCount.storageClass & invalidSTC); + argerr |= argCount.type.toBasetype().ty != Tint32; + + // Argument pointer must be char** + auto argPtr = tf.parameterList[1]; + argerr |= !!(argPtr.storageClass & invalidSTC); + argerr |= !isCharPtrPtr(argPtr.type); + + // `char** environ` is a common extension, see J.5.1 of the C standard + if (nparams == 3) + { + auto envPtr = tf.parameterList[2]; + argerr |= !!(envPtr.storageClass & invalidSTC); + argerr |= !isCharPtrPtr(envPtr.type); + } + } + else + argerr = nparams != 0; + + // Disallow variadic main() - except for K&R declarations in C files. + // E.g. int main(), int main(argc, argv) int argc, char** argc { ... } + if (tf.parameterList.varargs && (!fd.isCsymbol() || (!tf.parameterList.hasIdentifierList && nparams))) + argerr |= true; + + if (argerr) + { + .error(fd.loc, "%s `%s` parameters must match one of the following signatures", fd.kind, fd.toPrettyChars); + fd.loc.errorSupplemental("`main()`"); + fd.loc.errorSupplemental("`main(int argc, char** argv)`"); + fd.loc.errorSupplemental("`main(int argc, char** argv, char** environ)` [POSIX extension]"); + } + } + else + return; // Neither C nor D main, ignore (should probably be an error) + + // Allow enums with appropriate base types (same ABI) + retType = retType.toBasetype(); + + if (retType.ty != Tint32 && retType.ty != Tvoid && retType.ty != Tnoreturn) + .error(fd.loc, "%s `%s` must return `int`, `void` or `noreturn`, not `%s`", fd.kind, fd.toPrettyChars, tf.nextOf().toChars()); +} + +/*********************************************** + * Check all return statements for a function to verify that returning + * using NRVO is possible. + * + * Returns: + * `false` if the result cannot be returned by hidden reference. + */ +extern (D) bool checkNRVO(FuncDeclaration fd) +{ + if (!fd.isNRVO() || fd.returns is null) + return false; + + auto tf = fd.type.toTypeFunction(); + if (tf.isref) + return false; + + foreach (rs; *fd.returns) + { + if (auto ve = rs.exp.isVarExp()) + { + auto v = ve.var.isVarDeclaration(); + if (!v || v.isReference()) + return false; + else if (fd.nrvo_var is null) + { + // Variables in the data segment (e.g. globals, TLS or not), + // parameters and closure variables cannot be NRVOed. + if (v.isDataseg() || v.isParameter() || v.toParent2() != fd) + return false; + if (v.nestedrefs.length && fd.needsClosure()) + return false; + // don't know if the return storage is aligned + version (MARS) + { + if (fd.alignSectionVars && (*fd.alignSectionVars).contains(v)) + return false; + } + // The variable type needs to be equivalent to the return type. + if (!v.type.equivalent(tf.next)) + return false; + //printf("Setting nrvo to %s\n", v.toChars()); + fd.nrvo_var = v; + } + else if (fd.nrvo_var != v) + return false; + } + else //if (!exp.isLvalue()) // keep NRVO-ability + return false; + } + return true; +} diff --git a/gcc/d/dmd/gluelayer.d b/gcc/d/dmd/gluelayer.d index a3a3bd0..72e6c52 100644 --- a/gcc/d/dmd/gluelayer.d +++ b/gcc/d/dmd/gluelayer.d @@ -25,7 +25,7 @@ version (NoBackend) struct Symbol; struct code; struct block; - struct Blockx; + struct BlockState; struct elem; struct TYPE; alias type = TYPE; @@ -51,9 +51,9 @@ else version (IN_GCC) } else { - public import dmd.backend.cc : block, Blockx, Symbol; + public import dmd.backend.cc : block, BlockState, Symbol; public import dmd.backend.type : type; public import dmd.backend.el : elem; - public import dmd.backend.code_x86 : code; + public import dmd.backend.x86.code_x86 : code; public import dmd.objc_glue : ObjcGlue; } diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index 41da11d..1e72cf7 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -62,6 +62,7 @@ struct HdrGenState bool doFuncBodies; /// include function bodies in output bool vcg_ast; /// write out codegen-ast bool skipConstraints; // skip constraints when doing templates + bool showOneMember = true; bool fullQual; /// fully qualify types when printing int tpltMember; @@ -1974,7 +1975,7 @@ void toCharsMaybeConstraints(const TemplateDeclaration td, ref OutBuffer buf, re } buf.writeByte(')'); - if (td.onemember) + if (hgs.showOneMember && td.onemember) { if (const fd = td.onemember.isFuncDeclaration()) { diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 6dbc60b..dfaf8f5 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -102,6 +102,8 @@ immutable Msgtable[] msgtable = { "ctfe", "__ctfe" }, { "offset" }, { "offsetof" }, + { "bitoffsetof" }, + { "bitwidth" }, { "ModuleInfo" }, { "ClassInfo" }, { "classinfo" }, @@ -455,6 +457,7 @@ immutable Msgtable[] msgtable = { "isAbstractClass" }, { "isArithmetic" }, { "isAssociativeArray" }, + { "isBitfield" }, { "isFinalClass" }, { "isTemplate" }, { "isPOD" }, diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index dcfe183..a91a0a4 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -597,6 +597,14 @@ extern (C++) abstract class Type : ASTNode tsize_t = basic[isLP64 ? Tuns64 : Tuns32]; tptrdiff_t = basic[isLP64 ? Tint64 : Tint32]; thash_t = tsize_t; + + static if (__VERSION__ == 2081) + { + // Related issue: https://issues.dlang.org/show_bug.cgi?id=19134 + // D 2.081.x regressed initializing class objects at compile time. + // As a workaround initialize this global at run-time instead. + TypeTuple.empty = new TypeTuple(); + } } /** @@ -4405,7 +4413,10 @@ extern (C++) final class TypeClass : Type extern (C++) final class TypeTuple : Type { // 'logically immutable' cached global - don't modify! - __gshared TypeTuple empty = new TypeTuple(); + static if (__VERSION__ == 2081) + __gshared TypeTuple empty; // See comment in Type._init + else + __gshared TypeTuple empty = new TypeTuple(); Parameters* arguments; // types making up the tuple diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index d88face..963fa92 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -314,7 +314,7 @@ private extern(C++) final class Semantic3Visitor : Visitor fds.checkInContractOverrides(); // Remember whether we need to generate an 'out' contract. - immutable bool needEnsure = FuncDeclaration.needsFensure(funcdecl); + immutable bool needEnsure = funcdecl.needsFensure(); if (funcdecl.fbody || funcdecl.frequires || needEnsure) { diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index ae68d6a..d0e1b9a 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -3542,6 +3542,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ls2.statement = ls; sc = sc.push(); + sc.lastVar = sc.enclosing.lastVar; sc.scopesym = sc.enclosing.scopesym; sc.ctorflow.orCSX(CSX.label); @@ -3549,6 +3550,10 @@ Statement statementSemanticVisit(Statement s, Scope* sc) sc.slabel = ls; if (ls.statement) ls.statement = ls.statement.statementSemantic(sc); + + //issue 24534: lastVar may have been updated in the nested scope + sc.enclosing.lastVar = sc.lastVar; + sc.pop(); result = ls; diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d index 87826b5..dadf519 100644 --- a/gcc/d/dmd/target.d +++ b/gcc/d/dmd/target.d @@ -113,6 +113,7 @@ extern (C++) struct Target const(char)[] architectureName; CPU cpu; // CPU instruction set to target bool isX86_64; // generate 64 bit code for x86_64; true by default for 64 bit dmd + bool isX86; // generate 32 bit Intel x86 code bool isLP64; // pointers are 64 bits // Environmental @@ -120,7 +121,6 @@ extern (C++) struct Target const(char)[] lib_ext; /// extension for static library files const(char)[] dll_ext; /// extension for dynamic library files bool run_noext; /// allow -run sources without extensions - bool omfobj; // for Win32: write OMF object files instead of MsCoff /** * Values representing all properties for floating point types */ @@ -302,7 +302,6 @@ struct TargetC { Unspecified, Bionic, - DigitalMars, Glibc, Microsoft, Musl, @@ -314,7 +313,6 @@ struct TargetC enum BitFieldStyle : ubyte { Unspecified, - DM, /// Digital Mars 32 bit C compiler MS, /// Microsoft 32 and 64 bit C compilers /// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 /// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 @@ -347,7 +345,6 @@ struct TargetCPP { Unspecified, Clang, - DigitalMars, Gcc, Microsoft, Sun diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h index 6237cf14..a5caa74 100644 --- a/gcc/d/dmd/target.h +++ b/gcc/d/dmd/target.h @@ -50,7 +50,6 @@ struct TargetC { Unspecified, Bionic, - DigitalMars, Glibc, Microsoft, Musl, @@ -62,7 +61,6 @@ struct TargetC enum class BitFieldStyle : unsigned char { Unspecified, - DM, // Digital Mars 32 bit C compiler MS, // Microsoft 32 and 64 bit C compilers // https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 // https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 @@ -87,7 +85,6 @@ struct TargetCPP { Unspecified, Clang, - DigitalMars, Gcc, Microsoft, Sun @@ -157,6 +154,7 @@ struct Target DString architectureName; // name of the platform architecture (e.g. X86_64) CPU cpu; // CPU instruction set to target d_bool isX86_64; // generate 64 bit code for x86_64; true by default for 64 bit dmd + d_bool isX86; // generate 32 bit Intel x86 code d_bool isLP64; // pointers are 64 bits // Environmental @@ -164,7 +162,6 @@ struct Target DString lib_ext; /// extension for static library files DString dll_ext; /// extension for dynamic library files d_bool run_noext; /// allow -run sources without extensions - d_bool omfobj; /// for Win32: write OMF object files instead of COFF template <typename T> struct FPTypeProperties diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d index bd3cd89..d26e35d 100644 --- a/gcc/d/dmd/templatesem.d +++ b/gcc/d/dmd/templatesem.d @@ -56,6 +56,8 @@ import dmd.tokens; import dmd.typesem; import dmd.visitor; +alias funcLeastAsSpecialized = dmd.funcsem.leastAsSpecialized; + /************************************ * Perform semantic analysis on template. * Params: @@ -2021,8 +2023,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, * This is because f() is "more specialized." */ { - MATCH c1 = FuncDeclaration.leastAsSpecialized(fd, m.lastf, argumentList.names); - MATCH c2 = FuncDeclaration.leastAsSpecialized(m.lastf, fd, argumentList.names); + MATCH c1 = funcLeastAsSpecialized(fd, m.lastf, argumentList.names); + MATCH c2 = funcLeastAsSpecialized(m.lastf, fd, argumentList.names); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) return firstIsBetter(); if (c1 < c2) return 0; @@ -2301,8 +2303,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, } { // Disambiguate by picking the most specialized FunctionDeclaration - MATCH c1 = FuncDeclaration.leastAsSpecialized(fd, m.lastf, argumentList.names); - MATCH c2 = FuncDeclaration.leastAsSpecialized(m.lastf, fd, argumentList.names); + MATCH c1 = funcLeastAsSpecialized(fd, m.lastf, argumentList.names); + MATCH c2 = funcLeastAsSpecialized(m.lastf, fd, argumentList.names); //printf("3: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index 81d42e6..5ec3844 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -503,6 +503,17 @@ Expression semanticTraits(TraitsExp e, Scope* sc) sm => sm.isTemplateDeclaration() !is null) != 0; }); } + if (e.ident == Id.isBitfield) + { + if (dim != 1) + return dimError(1); + + return isDsymX((s) + { + s = s.toAlias(); + return s.isBitFieldDeclaration() !is null; + }); + } if (e.ident == Id.isPOD) { if (dim != 1) diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 195fdc7..31ebc4c 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -1282,6 +1282,23 @@ bool hasPointers(Type t) } } +/************************************** + * Returns an indirect type one step from t. + */ +Type getIndirection(Type t) +{ + t = t.baseElemOf(); + if (t.ty == Tarray || t.ty == Tpointer) + return t.nextOf().toBasetype(); + if (t.ty == Taarray || t.ty == Tclass) + return t; + if (t.ty == Tstruct) + return t.hasPointers() ? t : null; // TODO + + // should consider TypeDelegate? + return null; +} + /****************************************** * Perform semantic analysis on a type. * Params: @@ -4083,7 +4100,9 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag } if (v) { - if (ident == Id.offsetof) + if (ident == Id.offsetof || + ident == Id.bitoffsetof || + ident == Id.bitwidth) { v.dsymbolSemantic(null); if (v.isField()) @@ -4093,7 +4112,20 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag ad.size(e.loc); if (ad.sizeok != Sizeok.done) return ErrorExp.get(); - return new IntegerExp(e.loc, v.offset, Type.tsize_t); + uint value; + if (ident == Id.offsetof) + value = v.offset; + else // Id.bitoffsetof || Id.bitwidth + { + auto bf = v.isBitFieldDeclaration(); + if (bf) + { + value = ident == Id.bitoffsetof ? bf.bitOffset : bf.fieldWidth; + } + else + error(v.loc, "`%s` is not a bitfield, cannot apply `%s`", v.toChars(), ident.toChars()); + } + return new IntegerExp(e.loc, value, Type.tsize_t); } } else if (ident == Id._init) @@ -4512,6 +4544,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag ident != Id._mangleof && ident != Id.stringof && ident != Id.offsetof && + ident != Id.bitoffsetof && + ident != Id.bitwidth && // https://issues.dlang.org/show_bug.cgi?id=15045 // Don't forward special built-in member functions. ident != Id.ctor && @@ -6687,7 +6721,7 @@ Type substWildTo(Type type, uint mod) t = new TypeSArray(t, (cast(TypeSArray)type).dim.syntaxCopy()); else if (type.ty == Taarray) { - t = new TypeAArray(t, (cast(TypeAArray)type).index.syntaxCopy()); + t = new TypeAArray(t, (cast(TypeAArray)type).index.substWildTo(mod)); } else if (type.ty == Tdelegate) { |