diff mbox series

[committed] d: Merge upstream dmd, druntime 855353a1d9

Message ID 20240317111559.463023-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd, druntime 855353a1d9 | expand

Commit Message

Iain Buclaw March 17, 2024, 11:15 a.m. UTC
Hi,

This patch merges the D front-end and runtime library with upstream dmd
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.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, committed
to mainline.

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 855353a1d9.
	* dmd/VERSION:

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 855353a1d9.
---
 gcc/d/dmd/MERGE                               |  2 +-
 gcc/d/dmd/VERSION                             |  2 +-
 gcc/d/dmd/cxxfrontend.d                       | 10 +++
 gcc/d/dmd/dcast.d                             | 31 ++++---
 gcc/d/dmd/dinterpret.d                        |  2 +-
 gcc/d/dmd/dsymbolsem.d                        |  7 +-
 gcc/d/dmd/dtemplate.d                         | 48 +++++++++--
 gcc/d/dmd/enum.h                              |  6 ++
 gcc/d/dmd/expression.h                        | 15 ++++
 gcc/d/dmd/expressionsem.d                     |  9 +-
 gcc/d/dmd/hdrgen.d                            |  3 +-
 gcc/d/dmd/lexer.d                             |  1 -
 gcc/d/dmd/mtype.d                             | 17 ++--
 gcc/d/dmd/mtype.h                             |  5 +-
 gcc/d/dmd/root/filename.d                     |  2 +-
 gcc/d/dmd/root/filename.h                     |  2 +-
 gcc/d/dmd/template.h                          | 16 +---
 gcc/d/dmd/templatesem.d                       | 85 ++++++++++++-------
 gcc/d/dmd/typesem.d                           | 16 +++-
 .../compilable/named_arguments_auto_ref.d     | 39 +++++++++
 .../compilable/named_arguments_ifti.d         | 27 ++++++
 .../gdc.test/fail_compilation/hexstring.d     |  5 +-
 .../fail_compilation/named_arguments_error.d  | 11 ++-
 .../named_arguments_ifti_error.d              | 20 +++++
 gcc/testsuite/gdc.test/runnable/literal.d     | 10 ++-
 libphobos/libdruntime/MERGE                   |  2 +-
 .../core/internal/gc/impl/conservative/gc.d   |  4 +-
 .../core/internal/gc/impl/manual/gc.d         |  2 +-
 .../core/internal/gc/impl/proto/gc.d          |  2 +-
 29 files changed, 294 insertions(+), 107 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/named_arguments_auto_ref.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/named_arguments_ifti.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
diff mbox series

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 4c0a0bc2aac..a00872ef864 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 416807683f5..8ca452f8912 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 8c046343468..a0432d2e1b4 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*/;
@@ -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
  */
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index a49bd575f4b..8a713f424d6 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 c4924903f25..5493fc18881 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 bb0a1d6e2cc..b13f98aee73 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 165a010059f..d181facfc24 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 650bf3e2c7c..4e6fbe2cacf 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 9cd73a965ba..2f6bb84acb9 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 db40ae01dec..7ae7f400d16 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 8eef7992e2a..41da11dedbe 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 937597cdf89..c9c506e9cf3 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 2c9e058bf32..715ee12159c 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 2f8bfa68d22..ad64b120f40 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 41c2050057d..d9f1a04057d 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 0e52b982323..e8c8b11fffd 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 0f96a1b3b09..bccec1a68c1 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 0a36838e167..bd3cd89588f 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 ad87ea0baeb..b2b9e38ead4 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();
 }
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
index 00000000000..aa1ab7191c6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/named_arguments_auto_ref.d
@@ -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
index 00000000000..3a35d799e63
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/named_arguments_ifti.d
@@ -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);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/hexstring.d b/gcc/testsuite/gdc.test/fail_compilation/hexstring.d
index 95b07e763ff..0f23f444389 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/hexstring.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/hexstring.d
@@ -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;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
index b634a119564..125ebcc926e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
@@ -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
index 00000000000..6d8a70a2c46
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d
@@ -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
+}
diff --git a/gcc/testsuite/gdc.test/runnable/literal.d b/gcc/testsuite/gdc.test/runnable/literal.d
index 27b5543b6fc..3cc7e51197b 100644
--- a/gcc/testsuite/gdc.test/runnable/literal.d
+++ b/gcc/testsuite/gdc.test/runnable/literal.d
@@ -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
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 4c0a0bc2aac..a00872ef864 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/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/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index 56433b49302..cb8df47507f 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -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)
diff --git a/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d b/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
index 570781e2fdc..b820adda1a2 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
@@ -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()
diff --git a/libphobos/libdruntime/core/internal/gc/impl/proto/gc.d b/libphobos/libdruntime/core/internal/gc/impl/proto/gc.d
index ff044d9a9b2..2286d17d9ce 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/proto/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/proto/gc.d
@@ -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
 {