]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Merge upstream dmd, druntime 855353a1d9
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 17 Mar 2024 11:00:57 +0000 (12:00 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sun, 17 Mar 2024 11:01:20 +0000 (12:01 +0100)
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.

29 files changed:
gcc/d/dmd/MERGE
gcc/d/dmd/VERSION
gcc/d/dmd/cxxfrontend.d
gcc/d/dmd/dcast.d
gcc/d/dmd/dinterpret.d
gcc/d/dmd/dsymbolsem.d
gcc/d/dmd/dtemplate.d
gcc/d/dmd/enum.h
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/hdrgen.d
gcc/d/dmd/lexer.d
gcc/d/dmd/mtype.d
gcc/d/dmd/mtype.h
gcc/d/dmd/root/filename.d
gcc/d/dmd/root/filename.h
gcc/d/dmd/template.h
gcc/d/dmd/templatesem.d
gcc/d/dmd/typesem.d
gcc/testsuite/gdc.test/compilable/named_arguments_auto_ref.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/named_arguments_ifti.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/hexstring.d
gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/literal.d
libphobos/libdruntime/MERGE
libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
libphobos/libdruntime/core/internal/gc/impl/proto/gc.d

index 4c0a0bc2aac4612afe55f049a0e1cd6e297b8421..a00872ef864d4b863620b01d78a832e64fedf29a 100644 (file)
@@ -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.
index 416807683f5aead32b7f8b219f8051c78e1bc2a6..8ca452f8912224655a8f902715a31d9417b313ae 100644 (file)
@@ -1 +1 @@
-v2.108.0-beta.1
+v2.108.0-rc.1
index 8c04634346861717a40d5cad7f63696983791e27..a0432d2e1b46c8e07e44c5a2baf297d3234b541a 100644 (file)
@@ -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*/;
@@ -213,6 +214,15 @@ void genCppHdrFiles(ref Modules ms)
     return dmd.dtoh.genCppHdrFiles(ms);
 }
 
+/***********************************************************
+ * enumsem.d
+ */
+Expression getDefaultValue(EnumDeclaration ed, const ref Loc loc)
+{
+    import dmd.enumsem;
+    return dmd.enumsem.getDefaultValue(ed, loc);
+}
+
 /***********************************************************
  * expression.d
  */
index a49bd575f4bb5a10f79e14bca9bc09de13c0c791..8a713f424d6475760fe8cb3301cf7ab03b96defc 100644 (file)
@@ -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)
         {
index c4924903f25a78d47454ac377bb7dbf1791b1059..5493fc188812bf1c1892dfec8877d23c848a304c 100644 (file)
@@ -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;
index bb0a1d6e2cc93ffd70c9e5bdf7df2e9716bbe9b2..b13f98aee73be4003becdfbb5037fca92d2d7658 100644 (file)
@@ -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;
         }
     }
 
index 165a010059f943da4179352c17875720858c10b3..d181facfc249b39aa644188aba9e0ef71f465086 100644 (file)
@@ -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
 {
index 650bf3e2c7cdac7319b21bd22a478037ca103fb1..4e6fbe2cacfbb970a8bb7967b858f85182f5f625 100644 (file)
@@ -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:
index 9cd73a965ba0d6bd58059fb98f9d8321fd41c6f4..2f6bb84acb9b2f98ff7f0728b53f0dcbb964b0ba 100644 (file)
@@ -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:
index db40ae01decf1cd6d833288ccdbf062d06516aef..7ae7f400d1661ba52c1e6af0d6f25a72466a5038 100644 (file)
@@ -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)
         {
index 8eef7992e2aee33c79c792b7c866dc9dae3c6b05..41da11dedbecea7c88a07b60b2bbb94171250222 100644 (file)
@@ -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);
index 937597cdf89d10a75a5b4c3a29d903a3758378dd..c9c506e9cf3c147a56302049f04312ce44ef4438 100644 (file)
@@ -1568,7 +1568,6 @@ class Lexer
                     stringbuffer.writeByte(v);
                 }
                 t.setString(stringbuffer);
-                t.postfix = 'h';
                 stringPostfix(t);
                 return TOK.hexadecimalString;
             default:
index 2c9e058bf325c465e597a3b35550ec1ffb9e6061..715ee12159cb927aa19e9aa12d21b98503247738 100644 (file)
@@ -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)
index 2f8bfa68d2212045e8bb519ed5516f6ed7e76443..ad64b120f400cf41ee6dbdbd77658664f66bda11 100644 (file)
@@ -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;
index 41c2050057d32932d2a55266e178f3b554845608..d9f1a04057dff00a03444fef1564dba339b32f05 100644 (file)
@@ -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;
     }
index 0e52b98232339d521b4420377454a4e82e076c5c..e8c8b11fffdd54b74f3c3d28f7ae2b22923143a2 100644 (file)
@@ -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);
index 0f96a1b3b0985e45d91523b7df54c32ef116afff..bccec1a68c128ff7222ef69677ff86735d7e7160 100644 (file)
@@ -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;
 
index 0a36838e167d2c64796e3ca5577e319353bba35f..bd3cd89588f7b902872bdf91fb95459ad41e0b7b 100644 (file)
@@ -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)
         {
index ad87ea0baebeab724d50197bb22d34a8ccd3c9d6..b2b9e38ead4d9a7979ea592452e24f8a8ac89f38 100644 (file)
@@ -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();
 }
diff --git a/gcc/testsuite/gdc.test/compilable/named_arguments_auto_ref.d b/gcc/testsuite/gdc.test/compilable/named_arguments_auto_ref.d
new file mode 100644 (file)
index 0000000..aa1ab71
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+TEST_OUTPUT:
+---
+Call 0
+(x: true, y: false)
+Call 1
+Call 2
+(x: false, y: false)
+Call 3
+(x: false, y: true)
+Call 4
+---
+
+As of writing this test, template function instances store the function arguments from the call site.
+When looking in cache for an existing template instantiation, matching template arguments isn't
+sufficient: `auto ref` parameters being ref or not also create different template instances.
+This test checks that the special logic for it still works with named arguments.
+*/
+
+void autoref()(auto ref int x, auto ref int y)
+{
+    pragma(msg, "(x: ", __traits(isRef, x), ", y: ", __traits(isRef, y), ")");
+}
+
+void main()
+{
+    int REF = 0;
+    enum NOT = 0;
+    pragma(msg, "Call 0");
+    autoref(y: NOT, x: REF); // new instance
+    pragma(msg, "Call 1");
+    autoref(x: REF, y: NOT); // existing instance
+    pragma(msg, "Call 2");
+    autoref(x: NOT, y: NOT); // new instance
+    pragma(msg, "Call 3");
+    autoref(x: NOT, y: REF); // new instance
+    pragma(msg, "Call 4");
+    autoref(y: REF, x: NOT); // existing instance
+}
diff --git a/gcc/testsuite/gdc.test/compilable/named_arguments_ifti.d b/gcc/testsuite/gdc.test/compilable/named_arguments_ifti.d
new file mode 100644 (file)
index 0000000..3a35d79
--- /dev/null
@@ -0,0 +1,27 @@
+// Basic out-of-order test
+int f0(T0, T1)(T0 t0, T1 t1)
+{
+    static assert(is(T0 == int));
+    static assert(is(T1 == string));
+    return t0;
+}
+
+static assert(f0(t1: "a", t0: 10) == 10);
+
+// Default argument at beginning instead of end
+int f1(T0, T1)(T0 t0 = 20, T1 t1) { return t0; }
+static assert(f1(t1: "a") == 20);
+
+// Two default arguments
+int f2(T0, T1)(T0 t0 = 20, T1 t1, T2 t2 = 30) { return t2; }
+
+// Selecting overload based on name
+string f3(T)(T x) { return "x"; }
+string f3(T)(T y) { return "y"; }
+static assert(f3(x: 0) == "x");
+static assert(f3(y: 0) == "y");
+
+// Variadic tuple cut short by named argument
+int f4(T...)(T x, int y, int z) { assert(y == 30); assert(z == 50); return T.length; }
+static assert(f4(10, 10, 10, y: 30, z: 50) == 3);
+static assert(f4(10, 10, 30, z: 50) == 2);
index 95b07e763fff615179f2555d3d5688b3232a3199..0f23f444389d901191fec1ac3759c11828f44c93 100644 (file)
@@ -12,11 +12,11 @@ fail_compilation/hexstring.d(38): Error: array cast from `string` to `immutable(
 fail_compilation/hexstring.d(39): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
 fail_compilation/hexstring.d(39):        perhaps remove postfix `c` from hex string
 fail_compilation/hexstring.d(40): Error: hex string with `dstring` type needs to be multiple of 4 bytes, not 5
-fail_compilation/hexstring.d(41): Error: cannot implicitly convert expression `x"44332211"d` of type `dstring` to `immutable(float[])`
+fail_compilation/hexstring.d(41): Error: cannot implicitly convert expression `x"11223344"d` of type `dstring` to `immutable(float[])`
+fail_compilation/hexstring.d(42): Error: cannot implicitly convert expression `x"1122"w` of type `wstring` to `immutable(ubyte[])`
 fail_compilation/hexstring.d(28): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]`
 ---
 */
-
 immutable ubyte[] s0 = x"123F";
 static assert(s0[0] == 0x12);
 static assert(s0[1] == 0x3F);
@@ -39,3 +39,4 @@ immutable ushort[] f10 = cast(immutable ushort[]) (x"1122" ~ "");
 immutable uint[] f11 = cast(immutable uint[]) x"AABBCCDD"c;
 immutable uint[] f12 = x"1122334455"d;
 immutable float[] f13 = x"11223344"d;
+immutable ubyte[] f14 = x"1122"w;
index b634a119564acfe32888a6f04872ce3b876b7536..125ebcc926e54dfd77331de08d2e18ec7e136b8b 100644 (file)
@@ -19,15 +19,15 @@ fail_compilation/named_arguments_error.d(33):        `named_arguments_error.g(in
 fail_compilation/named_arguments_error.d(43): Error: no named argument `element` allowed for array dimension
 fail_compilation/named_arguments_error.d(44): Error: no named argument `number` allowed for scalar
 fail_compilation/named_arguments_error.d(45): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string`
-fail_compilation/named_arguments_error.d(46): Error: named arguments with Implicit Function Template Instantiation are not supported yet
-fail_compilation/named_arguments_error.d(46): Error: template `tempfun` is not callable using argument types `!()(string, int)`
-fail_compilation/named_arguments_error.d(50):        Candidate is: `tempfun(T, U)(T t, U u)`
+fail_compilation/named_arguments_error.d(46): Error: template `tempfun` is not callable using argument types `!()(int, int)`
+fail_compilation/named_arguments_error.d(49):        Candidate is: `tempfun(T, U)(T t, U u)`
 ---
 */
 
 
 
 
+
 void f(int x, int y, int z);
 
 int g(int x, int y, int z = 3);
@@ -43,11 +43,10 @@ void main()
        auto g0 = new int[](element: 3);
        auto g1 = new int(number: 3);
        string s = g(x: 3, y: 4, z: 5);
-       enum x = tempfun(u: "u", t: 0);
+       enum x = tempfun(u: 0, 1);
 }
 
-// template arguments
 int tempfun(T, U)(T t, U u)
 {
-       return 3;
+    return 3;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
new file mode 100644 (file)
index 0000000..6d8a70a
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/named_arguments_ifti_error.d(17): Error: template `f` is not callable using argument types `!()(int, int)`
+fail_compilation/named_arguments_ifti_error.d(13):        Candidate is: `f(T, U)(T x, U y)`
+fail_compilation/named_arguments_ifti_error.d(18): Error: template `f` is not callable using argument types `!()(int, int)`
+fail_compilation/named_arguments_ifti_error.d(13):        Candidate is: `f(T, U)(T x, U y)`
+fail_compilation/named_arguments_ifti_error.d(19): Error: template `f` is not callable using argument types `!()(int)`
+fail_compilation/named_arguments_ifti_error.d(13):        Candidate is: `f(T, U)(T x, U y)`
+---
+*/
+
+void f(T, U)(T x, U y) {}
+
+void main()
+{
+       f(x: 3, x: 3); // double assignment of x
+       f(y: 3,    3); // overflow past last parameter
+       f(y: 3);       // skipping parameter x
+}
index 27b5543b6fce88f646863bc3c2e180ae9fbc7115..3cc7e51197bc8e91e460db829761fe8881ad6681 100644 (file)
@@ -243,23 +243,27 @@ void test12950()
 
 void testHexstring()
 {
-    static immutable uint[] x = cast(immutable uint[]) x"FFAADDEE";
+    static immutable uint[] x = cast(immutable uint[]) x"FFAADDEE"d;
     static assert(x[0] == 0xFFAADDEE);
     assert(x[0] == 0xFFAADDEE);
 
-    static immutable ulong[] y = cast(immutable ulong[]) x"1122334455667788AABBCCDDEEFF0099";
+    static immutable ulong[] y = x"1122334455667788AABBCCDDEEFF0099";
     static assert(y[0] == 0x1122334455667788);
     static assert(y[1] == 0xAABBCCDDEEFF0099);
     assert(y[0] == 0x1122334455667788);
     assert(y[1] == 0xAABBCCDDEEFF0099);
 
+    immutable long[] c = x"1122334455667788AABBCCDDEEFF0099";
+    assert(c[0] == 0x1122334455667788);
+    assert(c[1] == 0xAABBCCDDEEFF0099);
+
     // Test that mangling of StringExp with size 8 is the same as array literal mangling:
     void f(immutable ulong[] a)() {}
     static assert(f!y.mangleof == f!([0x1122334455667788, 0xAABBCCDDEEFF0099]).mangleof);
 
     // Test printing StringExp with size 8
     enum toStr(immutable ulong[] v) = v.stringof;
-    static assert(toStr!y == `x"88776655443322119900FFEEDDCCBBAA"`);
+    static assert(toStr!y == `x"1122334455667788AABBCCDDEEFF0099"`);
 
     // Hex string postfixes
     // https://issues.dlang.org/show_bug.cgi?id=24363
index 4c0a0bc2aac4612afe55f049a0e1cd6e297b8421..a00872ef864d4b863620b01d78a832e64fedf29a 100644 (file)
@@ -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.
index 56433b493022418d7eade815a53aaf4a361e20ff..cb8df47507fc1705ac48d139397b071f8c0c6fd3 100644 (file)
@@ -94,8 +94,8 @@ private
 
         // Declared as an extern instead of importing core.exception
         // to avoid inlining - see https://issues.dlang.org/show_bug.cgi?id=13725.
-        void onInvalidMemoryOperationError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc;
-        void onOutOfMemoryError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted nothrow @nogc;
+        noreturn onInvalidMemoryOperationError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc;
+        noreturn onOutOfMemoryError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc;
 
         version (COLLECT_FORK)
             version (OSX)
index 570781e2fdccc6c2ef814fcef08956f933f99325..b820adda1a2b42659cf6c7b338dd9c3798c115c3 100644 (file)
@@ -26,7 +26,7 @@ import core.internal.container.array;
 import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
 static import core.memory;
 
-extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
+extern (C) noreturn onOutOfMemoryError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
 
 // register GC in C constructor (_STI_)
 private pragma(crt_constructor) void gc_manual_ctor()
index ff044d9a9b2e89674643cf79df2060ba7d642bf6..2286d17d9ce74ce10c9456c761ab6c4d359edc6c 100644 (file)
@@ -8,7 +8,7 @@ import core.internal.container.array;
 import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
 static import core.memory;
 
-extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
+extern (C) noreturn onOutOfMemoryError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
 
 private
 {