aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2024-03-17 12:00:57 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2024-03-17 12:01:20 +0100
commit2d454f982914c481a268f1c63e431b2682cc3be0 (patch)
treef8a0d79787e5b6f11835d55260c135f2aa2c7ecf /gcc/d
parentb5490afe3a480fb20eae7b93f8da203aa7f843b4 (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/cxxfrontend.d10
-rw-r--r--gcc/d/dmd/dcast.d31
-rw-r--r--gcc/d/dmd/dinterpret.d2
-rw-r--r--gcc/d/dmd/dsymbolsem.d7
-rw-r--r--gcc/d/dmd/dtemplate.d48
-rw-r--r--gcc/d/dmd/enum.h6
-rw-r--r--gcc/d/dmd/expression.h15
-rw-r--r--gcc/d/dmd/expressionsem.d9
-rw-r--r--gcc/d/dmd/hdrgen.d3
-rw-r--r--gcc/d/dmd/lexer.d1
-rw-r--r--gcc/d/dmd/mtype.d17
-rw-r--r--gcc/d/dmd/mtype.h5
-rw-r--r--gcc/d/dmd/root/filename.d2
-rw-r--r--gcc/d/dmd/root/filename.h2
-rw-r--r--gcc/d/dmd/template.h16
-rw-r--r--gcc/d/dmd/templatesem.d85
-rw-r--r--gcc/d/dmd/typesem.d16
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();
}