diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2024-03-17 12:00:57 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2024-03-17 12:01:20 +0100 |
commit | 2d454f982914c481a268f1c63e431b2682cc3be0 (patch) | |
tree | f8a0d79787e5b6f11835d55260c135f2aa2c7ecf /gcc/d | |
parent | b5490afe3a480fb20eae7b93f8da203aa7f843b4 (diff) | |
download | gcc-2d454f982914c481a268f1c63e431b2682cc3be0.zip gcc-2d454f982914c481a268f1c63e431b2682cc3be0.tar.gz gcc-2d454f982914c481a268f1c63e431b2682cc3be0.tar.bz2 |
d: Merge upstream dmd, druntime 855353a1d9
D front-end changes:
- Import dmd v2.108.0-rc.1.
- Add support for Named Arguments for functions.
- Hex strings now convert to integer arrays.
D runtime changes:
- Import druntime v2.108.0-rc.1.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 855353a1d9.
* dmd/VERSION:
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 855353a1d9.
Diffstat (limited to 'gcc/d')
-rw-r--r-- | gcc/d/dmd/MERGE | 2 | ||||
-rw-r--r-- | gcc/d/dmd/VERSION | 2 | ||||
-rw-r--r-- | gcc/d/dmd/cxxfrontend.d | 10 | ||||
-rw-r--r-- | gcc/d/dmd/dcast.d | 31 | ||||
-rw-r--r-- | gcc/d/dmd/dinterpret.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/dsymbolsem.d | 7 | ||||
-rw-r--r-- | gcc/d/dmd/dtemplate.d | 48 | ||||
-rw-r--r-- | gcc/d/dmd/enum.h | 6 | ||||
-rw-r--r-- | gcc/d/dmd/expression.h | 15 | ||||
-rw-r--r-- | gcc/d/dmd/expressionsem.d | 9 | ||||
-rw-r--r-- | gcc/d/dmd/hdrgen.d | 3 | ||||
-rw-r--r-- | gcc/d/dmd/lexer.d | 1 | ||||
-rw-r--r-- | gcc/d/dmd/mtype.d | 17 | ||||
-rw-r--r-- | gcc/d/dmd/mtype.h | 5 | ||||
-rw-r--r-- | gcc/d/dmd/root/filename.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/root/filename.h | 2 | ||||
-rw-r--r-- | gcc/d/dmd/template.h | 16 | ||||
-rw-r--r-- | gcc/d/dmd/templatesem.d | 85 | ||||
-rw-r--r-- | gcc/d/dmd/typesem.d | 16 |
19 files changed, 188 insertions, 91 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 4c0a0bc..a00872e 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -f8bae0455851a1dfc8113d69323415f6de549e39 +855353a1d9e16d43e85b6cf2b03aef388619bd16 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/VERSION b/gcc/d/dmd/VERSION index 4168076..8ca452f 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.108.0-beta.1 +v2.108.0-rc.1 diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d index 8c04634..a0432d2 100644 --- a/gcc/d/dmd/cxxfrontend.d +++ b/gcc/d/dmd/cxxfrontend.d @@ -14,6 +14,7 @@ import dmd.aggregate : AggregateDeclaration; import dmd.arraytypes; import dmd.astenums; import dmd.common.outbuffer : OutBuffer; +import dmd.denum : EnumDeclaration; import dmd.dmodule /*: Module*/; import dmd.dscope : Scope; import dmd.dstruct /*: StructDeclaration*/; @@ -214,6 +215,15 @@ void genCppHdrFiles(ref Modules ms) } /*********************************************************** + * enumsem.d + */ +Expression getDefaultValue(EnumDeclaration ed, const ref Loc loc) +{ + import dmd.enumsem; + return dmd.enumsem.getDefaultValue(ed, loc); +} + +/*********************************************************** * expression.d */ void expandTuples(Expressions* exps, Identifiers* names = null) diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index a49bd57..8a713f4 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -629,7 +629,7 @@ MATCH implicitConvTo(Expression e, Type t) TY tyn = e.type.nextOf().ty; - if (!tyn.isSomeChar) + if (!tyn.isSomeChar && !e.hexString) return visit(e); switch (t.ty) @@ -703,6 +703,11 @@ MATCH implicitConvTo(Expression e, Type t) return MATCH.nomatch; m = MATCH.constant; } + if (e.hexString && tn.isintegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0))) + { + m = MATCH.convert; + return m; + } if (!e.committed) { switch (tn.ty) @@ -719,9 +724,6 @@ MATCH implicitConvTo(Expression e, Type t) if (e.postfix != 'd') m = MATCH.convert; return m; - case Tint8: - case Tuns8: - break; case Tenum: if (tn.isTypeEnum().sym.isSpecial()) { @@ -735,14 +737,6 @@ MATCH implicitConvTo(Expression e, Type t) break; } } - if (e.hexString) - { - if (tn.isintegral && tn.size == e.sz) - { - m = MATCH.convert; - return m; - } - } break; default: @@ -1884,6 +1878,19 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) Type tb = t.toBasetype(); Type typeb = e.type.toBasetype(); + if (e.hexString && !e.committed) + { + const szx = cast(ubyte) tb.nextOf().size(); + if (szx != se.sz && (e.len % szx) == 0) + { + import dmd.utils: arrayCastBigEndian; + const data = e.peekData(); + se.setData(arrayCastBigEndian(data, szx).ptr, data.length / szx, szx); + se.type = t; + return se; + } + } + //printf("\ttype = %s\n", e.type.toChars()); if (tb.ty == Tdelegate && typeb.ty != Tdelegate) { diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index c492490..5493fc1 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -6118,7 +6118,7 @@ public: return; } - auto str = arrayCastBigEndian((cast(const ubyte[]) se.peekString()), sz); + auto str = arrayCastBigEndian(se.peekData(), sz); emplaceExp!(StringExp)(pue, e1.loc, str, se.len / sz, cast(ubyte) sz); result = pue.exp(); result.type = e.to; diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index bb0a1d6..b13f98a 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -4621,12 +4621,11 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList return aliasInstanceSemantic(tempinst, sc, tempdecl); } - Expressions* fargs = argumentList.arguments; // TODO: resolve named args /* See if there is an existing TemplateInstantiation that already * implements the typeargs. If so, just refer to that one instead. */ - tempinst.inst = tempdecl.findExistingInstance(tempinst, fargs); + tempinst.inst = tempdecl.findExistingInstance(tempinst, argumentList); TemplateInstance errinst = null; if (!tempinst.inst) { @@ -4874,7 +4873,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList /* If function template declaration */ - if (fargs && tempinst.aliasdecl) + if (argumentList.length > 0 && tempinst.aliasdecl) { if (auto fd = tempinst.aliasdecl.isFuncDeclaration()) { @@ -4883,7 +4882,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList */ if (fd.type) if (auto tf = fd.type.isTypeFunction()) - tf.fargs = fargs; + tf.inferenceArguments = argumentList; } } diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 165a010..d181fac 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -828,16 +828,24 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol } /**************************************************** - * Given a new instance tithis of this TemplateDeclaration, + * Given a new instance `tithis` of this TemplateDeclaration, * see if there already exists an instance. - * If so, return that existing instance. + * + * Params: + * tithis = template instance to check + * argumentList = For function templates, needed because different + * `auto ref` resolutions create different instances, + * even when template parameters are identical + * + * Returns: that existing instance, or `null` when it doesn't exist */ - extern (D) TemplateInstance findExistingInstance(TemplateInstance tithis, Expressions* fargs) + extern (D) TemplateInstance findExistingInstance(TemplateInstance tithis, ArgumentList argumentList) { //printf("findExistingInstance() %s\n", tithis.toChars()); - tithis.fargs = fargs; + tithis.fargs = argumentList.arguments; + tithis.fnames = argumentList.names; auto tibox = TemplateInstanceBox(tithis); - auto p = tibox in instances; + auto p = tibox in this.instances; debug (FindExistingInstance) ++(p ? nFound : nNotFound); //if (p) printf("\tfound %p\n", *p); else printf("\tnot found\n"); return p ? *p : null; @@ -3674,7 +3682,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol TemplateInstance inst; // refer to existing instance ScopeDsymbol argsym; // argument symbol table size_t hash; // cached result of toHash() - Expressions* fargs; // for function template, these are the function arguments + + /// For function template, these are the function names and arguments + /// Relevant because different resolutions of `auto ref` parameters + /// create different template instances even with the same template arguments + Expressions* fargs; + Identifiers* fnames; TemplateInstances* deferred; @@ -3974,6 +3987,19 @@ extern (C++) class TemplateInstance : ScopeDsymbol { if (!fd.errors) { + auto resolvedArgs = fd.type.isTypeFunction().resolveNamedArgs( + ArgumentList(this.fargs, this.fnames), null); + + // resolvedArgs can be null when there's an error: fail_compilation/fail14669.d + // In that case, equalsx returns true to prevent endless template instantiations + // However, it can also mean the function was explicitly instantiated + // without function arguments: fail_compilation/fail14669 + // Hence the following check: + if (this.fargs && !resolvedArgs) + return true; + + Expression[] args = resolvedArgs ? (*resolvedArgs)[] : []; + auto fparameters = fd.getParameterList(); size_t nfparams = fparameters.length; // Num function parameters for (size_t j = 0; j < nfparams; j++) @@ -3981,7 +4007,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol Parameter fparam = fparameters[j]; if (fparam.storageClass & STC.autoref) // if "auto ref" { - Expression farg = fargs && j < fargs.length ? (*fargs)[j] : fparam.defaultArg; + Expression farg = (j < args.length) ? args[j] : fparam.defaultArg; + // resolveNamedArgs strips trailing nulls / default params + // when it doesn't anymore, the ternary can be replaced with: + // assert(j < resolvedArgs.length); + if (!farg) + farg = fparam.defaultArg; if (!farg) goto Lnotequals; if (farg.isLvalue()) @@ -5723,8 +5754,7 @@ extern (C++) final class TemplateMixin : TemplateInstance /************************************ * This struct is needed for TemplateInstance to be the key in an associative array. - * Fixing https://issues.dlang.org/show_bug.cgi?id=15812 and - * https://issues.dlang.org/show_bug.cgi?id=15813 would make it unnecessary. + * Fixing https://issues.dlang.org/show_bug.cgi?id=15813 would make it unnecessary. */ struct TemplateInstanceBox { diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h index 650bf3e..4e6fbe2 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -17,6 +17,12 @@ class Identifier; class Type; class Expression; +namespace dmd +{ + // in enumsem.d + Expression *getDefaultValue(EnumDeclaration *ed, const Loc &loc); +} + class EnumDeclaration final : public ScopeDsymbol { public: diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 9cd73a9..2f6bb84 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -800,6 +800,21 @@ public: void accept(Visitor *v) override { v->visit(this); } }; +struct ArgumentList final +{ + Expressions* arguments; + Identifiers* names; + ArgumentList() : + arguments(), + names() + { + } + ArgumentList(Expressions* arguments, Identifiers* names = nullptr) : + arguments(arguments), + names(names) + {} +}; + class CallExp final : public UnaExp { public: diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index db40ae0..7ae7f40 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -2984,6 +2984,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, foreach (u; 0 .. elements.length) { Expression a = (*arguments)[i + u]; + assert(a); if (tret && a.implicitConvTo(tret)) { // p is a lazy array of delegates, tret is return type of the delegates @@ -4245,18 +4246,21 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (e.hexString) { - const data = cast(const ubyte[]) e.peekString(); switch (e.postfix) { case 'd': + e.committed = true; e.sz = 4; e.type = Type.tdstring; break; case 'w': + e.committed = true; e.sz = 2; e.type = Type.twstring; break; case 'c': + e.committed = true; + goto default; default: e.type = Type.tstring; e.sz = 1; @@ -4266,8 +4270,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor error(e.loc, "hex string with `%s` type needs to be multiple of %d bytes, not %d", e.type.toChars(), e.sz, cast(int) e.len); - e.setData(arrayCastBigEndian(data, e.sz).ptr, e.len / e.sz, e.sz); - e.committed = true; + e.setData(arrayCastBigEndian(e.peekData(), e.sz).ptr, e.len / e.sz, e.sz); } else switch (e.postfix) { diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index 8eef799..41da11d 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -2281,7 +2281,8 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt { buf.writeByte('x'); buf.writeByte('"'); - buf.writeHexString(e.peekData, true); + foreach (i; 0 .. e.len) + buf.printf("%0*llX", e.sz, e.getIndex(i)); buf.writeByte('"'); if (e.postfix) buf.writeByte(e.postfix); diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 937597c..c9c506e 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -1568,7 +1568,6 @@ class Lexer stringbuffer.writeByte(v); } t.setString(stringbuffer); - t.postfix = 'h'; stringPostfix(t); return TOK.hexadecimalString; default: diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 2c9e058..715ee12 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -3073,7 +3073,7 @@ extern (C++) final class TypeFunction : TypeNext TRUST trust; // level of trust PURE purity = PURE.impure; byte inuse; - Expressions* fargs; // function arguments + ArgumentList inferenceArguments; // function arguments to determine `auto ref` in type semantic extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0) @safe { @@ -3146,7 +3146,7 @@ extern (C++) final class TypeFunction : TypeNext t.isInOutParam = isInOutParam; t.isInOutQual = isInOutQual; t.trust = trust; - t.fargs = fargs; + t.inferenceArguments = inferenceArguments; t.isctor = isctor; return t; } @@ -3197,10 +3197,12 @@ extern (C++) final class TypeFunction : TypeNext { Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null; Identifier[] names = argumentList.names ? (*argumentList.names)[] : null; - auto newArgs = new Expressions(parameterList.length); + const nParams = parameterList.length(); // cached because O(n) + auto newArgs = new Expressions(nParams); newArgs.zero(); size_t ci = 0; bool hasNamedArgs = false; + const bool isVariadic = parameterList.varargs != VarArg.none; foreach (i, arg; args) { if (!arg) @@ -3223,7 +3225,7 @@ extern (C++) final class TypeFunction : TypeNext } if (ci >= newArgs.length) { - if (!parameterList.varargs) + if (!isVariadic) { // Without named args, let the caller diagnose argument overflow if (hasNamedArgs && pMessage) @@ -3247,7 +3249,12 @@ extern (C++) final class TypeFunction : TypeNext if (arg || parameterList[i].defaultArg) continue; - if (parameterList.varargs != VarArg.none && i + 1 == newArgs.length) + if (isVariadic && i + 1 == newArgs.length) + continue; + + // dtemplate sets `defaultArg=null` to avoid semantic on default arguments, + // don't complain about missing arguments in that case + if (this.incomplete) continue; if (pMessage) diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 2f8bfa6..ad64b12 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -14,6 +14,7 @@ #include "arraytypes.h" #include "ast_node.h" +#include "expression.h" #include "globals.h" #include "visitor.h" @@ -254,8 +255,6 @@ public: bool isSharedWild() const { return (mod & (MODshared | MODwild)) == (MODshared | MODwild); } bool isNaked() const { return mod == 0; } Type *nullAttributes() const; - Type *arrayOf(); - Type *sarrayOf(dinteger_t dim); bool hasDeprecatedAliasThis(); virtual Type *makeConst(); virtual Type *makeImmutable(); @@ -567,7 +566,7 @@ public: TRUST trust; // level of trust PURE purity; // PURExxxx char inuse; - Expressions *fargs; // function arguments + ArgumentList inferenceArguments; // function arguments static TypeFunction *create(Parameters *parameters, Type *treturn, VarArg varargs, LINK linkage, StorageClass stc = 0); const char *kind() override; diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d index 41c2050..d9f1a04 100644 --- a/gcc/d/dmd/root/filename.d +++ b/gcc/d/dmd/root/filename.d @@ -665,7 +665,7 @@ nothrow: * Returns: * if found, filename combined with path, otherwise null */ - extern (C++) static const(char)* searchPath(const ref Strings path, const char* name, bool cwd) + extern (C++) static const(char)* searchPath(const ref Strings path, const(char)* name, bool cwd) { return searchPath(path[], name.toDString, cwd).ptr; } diff --git a/gcc/d/dmd/root/filename.h b/gcc/d/dmd/root/filename.h index 0e52b98..e8c8b11 100644 --- a/gcc/d/dmd/root/filename.h +++ b/gcc/d/dmd/root/filename.h @@ -38,7 +38,7 @@ public: bool equalsExt(const char *ext); - static const char *searchPath(Strings& path, const char *name, bool cwd); + static const char *searchPath(const Strings &path, const char *name, bool cwd); static int exists(const char *name); static bool ensurePathExists(const char *path); static const char *canonicalName(const char *name); diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h index 0f96a1b..bccec1a 100644 --- a/gcc/d/dmd/template.h +++ b/gcc/d/dmd/template.h @@ -12,6 +12,7 @@ #include "arraytypes.h" #include "dsymbol.h" +#include "expression.h" class Identifier; class TemplateInstance; @@ -46,20 +47,6 @@ struct TemplatePrevious Objects *dedargs; }; -struct ArgumentList final -{ - Expressions* arguments; - Identifiers* names; - ArgumentList() : - arguments(), - names() - { - } - ArgumentList(Expressions* arguments, Identifiers* names = nullptr) : - arguments(arguments), - names(names) - {} -}; class TemplateDeclaration final : public ScopeDsymbol { @@ -271,6 +258,7 @@ public: ScopeDsymbol *argsym; // argument symbol table hash_t hash; // cached result of toHash() Expressions *fargs; // for function template, these are the function arguments + Identifiers *fnames; // for function template, argument names TemplateInstances* deferred; diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d index 0a36838..bd3cd89 100644 --- a/gcc/d/dmd/templatesem.d +++ b/gcc/d/dmd/templatesem.d @@ -250,7 +250,7 @@ MATCH matchWithInstance(Scope* sc, TemplateDeclaration td, TemplateInstance ti, return MATCH.nomatch; size_t parameters_dim = td.parameters.length; - int variadic = td.isVariadic() !is null; + const bool variadic = td.isVariadic() !is null; // If more arguments than parameters, no match if (ti.tiargs.length > parameters_dim && !variadic) @@ -338,12 +338,6 @@ MATCH matchWithInstance(Scope* sc, TemplateDeclaration td, TemplateInstance ti, if (fd) { TypeFunction tf = fd.type.isTypeFunction().syntaxCopy(); - if (argumentList.hasNames) - return nomatch(); - Expressions* fargs = argumentList.arguments; - // TODO: Expressions* fargs = tf.resolveNamedArgs(argumentList, null); - // if (!fargs) - // return nomatch(); fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf); fd.parent = ti; @@ -357,7 +351,7 @@ MATCH matchWithInstance(Scope* sc, TemplateDeclaration td, TemplateInstance ti, tf.incomplete = true; // Resolve parameter types and 'auto ref's. - tf.fargs = fargs; + tf.inferenceArguments = argumentList; uint olderrors = global.startGagging(); fd.type = tf.typeSemantic(td.loc, paramscope); global.endGagging(olderrors); @@ -762,7 +756,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat } size_t ntargs = 0; // array size of tiargs - size_t inferStart = 0; // index of first parameter to infer + size_t inferStart = 0; // index of first template parameter to infer from function argument const Loc instLoc = ti.loc; MATCH matchTiargs = MATCH.exact; @@ -834,9 +828,6 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat ParameterList fparameters = fd.getParameterList(); // function parameter list const nfparams = fparameters.length; // number of function parameters - if (argumentList.hasNames) - return matcherror(); // TODO: resolve named args - Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null; /* Check for match of function arguments with variadic template * parameter, such as: @@ -950,9 +941,14 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat { //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.length : 0); //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL); - size_t argi = 0; - size_t nfargs2 = fargs.length; // nfargs + supplied defaultArgs + enum DEFAULT_ARGI = size_t.max - 10; // pseudo index signifying the parameter is expected to be assigned its default argument + size_t argi = 0; // current argument index + size_t argsConsumed = 0; // to ensure no excess arguments + size_t nfargs2 = argumentList.length; // total number of arguments including applied defaultArgs uint inoutMatch = 0; // for debugging only + Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null; + Identifier[] fnames = argumentList.names ? (*argumentList.names)[] : null; + for (size_t parami = 0; parami < nfparams; parami++) { Parameter fparam = fparameters[parami]; @@ -961,11 +957,28 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat Type prmtype = fparam.type.addStorageClass(fparam.storageClass); Expression farg; + Identifier fname = argi < fnames.length ? fnames[argi] : null; + bool foundName = false; + if (fparam.ident) + { + foreach (i; 0 .. fnames.length) + { + if (fparam.ident == fnames[i]) + { + argi = i; + foundName = true; + } + } + } + if (fname && !foundName) + { + argi = DEFAULT_ARGI; + } /* See function parameters which wound up * as part of a template tuple parameter. */ - if (fptupindex != IDX_NOTFOUND && parami == fptupindex) + if (fptupindex != IDX_NOTFOUND && parami == fptupindex && argi != DEFAULT_ARGI) { TypeIdentifier tid = prmtype.isTypeIdentifier(); assert(tid); @@ -986,7 +999,12 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat Parameter p = fparameters[j]; if (p.defaultArg) { - break; + break; + } + foreach(name; fnames) + { + if (p.ident == name) + break; } if (!reliesOnTemplateParameters(p.type, (*td.parameters)[inferStart .. td.parameters.length])) { @@ -1055,6 +1073,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat } assert(declaredTuple); argi += declaredTuple.objects.length; + argsConsumed += declaredTuple.objects.length; continue; } @@ -1068,7 +1087,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat if (TypeTuple tt = prmtype.isTypeTuple()) { const tt_dim = tt.arguments.length; - for (size_t j = 0; j < tt_dim; j++, ++argi) + for (size_t j = 0; j < tt_dim; j++, ++argi, ++argsConsumed) { Parameter p = (*tt.arguments)[j]; if (j == tt_dim - 1 && fparameters.varargs == VarArg.typesafe && @@ -1171,7 +1190,9 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat } } } - nfargs2 = argi + 1; + + if (argi != DEFAULT_ARGI) + nfargs2 = argi + 1; /* If prmtype does not depend on any template parameters: * @@ -1189,7 +1210,11 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat */ if (prmtype.deco || prmtype.syntaxCopy().trySemantic(td.loc, paramscope)) { - ++argi; + if (argi != DEFAULT_ARGI) + { + ++argi; + ++argsConsumed; + } continue; } @@ -1203,6 +1228,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat farg = fargs[argi]; } { + assert(farg); // Check invalid arguments to detect errors early. if (farg.op == EXP.error || farg.type.ty == Terror) return nomatch(); @@ -1350,7 +1376,11 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat { if (m < match) match = m; // pick worst match - argi++; + if (argi != DEFAULT_ARGI) + { + argi++; + argsConsumed++; + } continue; } } @@ -1490,8 +1520,8 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat } assert(0); } - //printf(". argi = %d, nfargs = %d, nfargs2 = %d\n", argi, nfargs, nfargs2); - if (argi != nfargs2 && fparameters.varargs == VarArg.none) + // printf(". argi = %d, nfargs = %d, nfargs2 = %d, argsConsumed = %d\n", cast(int) argi, cast(int) nfargs, cast(int) nfargs2, cast(int) argsConsumed); + if (argsConsumed != nfargs2 && fparameters.varargs == VarArg.none) return nomatch(); } @@ -1618,7 +1648,7 @@ Lmatch: sc2.minst = sc.minst; sc2.stc |= fd.storage_class & STC.deprecated_; - fd = doHeaderInstantiation(td, ti, sc2, fd, tthis, argumentList.arguments); + fd = doHeaderInstantiation(td, ti, sc2, fd, tthis, argumentList); sc2 = sc2.pop(); sc2 = sc2.pop(); @@ -1650,7 +1680,7 @@ Lmatch: * Limited function template instantiation for using fd.leastAsSpecialized() */ private -FuncDeclaration doHeaderInstantiation(TemplateDeclaration td, TemplateInstance ti, Scope* sc2, FuncDeclaration fd, Type tthis, Expressions* fargs) +FuncDeclaration doHeaderInstantiation(TemplateDeclaration td, TemplateInstance ti, Scope* sc2, FuncDeclaration fd, Type tthis, ArgumentList inferenceArguments) { assert(fd); version (none) @@ -1667,7 +1697,7 @@ FuncDeclaration doHeaderInstantiation(TemplateDeclaration td, TemplateInstance t assert(fd.type.ty == Tfunction); auto tf = fd.type.isTypeFunction(); - tf.fargs = fargs; + tf.inferenceArguments = inferenceArguments; if (tthis) { @@ -2084,11 +2114,6 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, } //printf("td = %s\n", td.toChars()); - if (argumentList.hasNames) - { - .error(loc, "named arguments with Implicit Function Template Instantiation are not supported yet"); - goto Lerror; - } auto f = td.onemember ? td.onemember.isFuncDeclaration() : null; if (!f) { diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index ad87ea0..b2b9e38 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -2187,6 +2187,12 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc) } } + Expressions* fargs = mtype.inferenceArguments.arguments; + + // mtype.argumentList only provided for Implicit Function Template Instantiation + if (mtype.inferenceArguments.length > 0) + fargs = tf.resolveNamedArgs(mtype.inferenceArguments, null); + // Now that we completed semantic for the argument types, // run semantic on their default values, // bearing in mind tuples have been expanded. @@ -2236,8 +2242,10 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc) */ if (eparam.storageClass & STC.auto_) { - Expression farg = mtype.fargs && eidx < mtype.fargs.length ? - (*mtype.fargs)[eidx] : eparam.defaultArg; + Expression farg = (fargs && eidx < fargs.length) ? (*fargs)[eidx] : null; + if (!farg) + farg = eparam.defaultArg; + if (farg && (eparam.storageClass & STC.ref_)) { if (!farg.isLvalue()) @@ -5681,7 +5689,7 @@ Type addStorageClass(Type type, StorageClass stc) // Klunky to change these auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, 0); tf.mod = t.mod; - tf.fargs = tf_src.fargs; + tf.inferenceArguments = tf_src.inferenceArguments; tf.purity = t.purity; tf.isnothrow = t.isnothrow; tf.isnogc = t.isnogc; @@ -6775,7 +6783,7 @@ Type substWildTo(Type type, uint mod) t.isInOutParam = false; t.isInOutQual = false; t.trust = tf.trust; - t.fargs = tf.fargs; + t.inferenceArguments = tf.inferenceArguments; t.isctor = tf.isctor; return t.merge(); } |