* [committed] d: Merge upstream dmd, druntime 855353a1d9
@ 2024-03-17 11:15 Iain Buclaw
0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2024-03-17 11:15 UTC (permalink / raw)
To: gcc-patches; +Cc: Iain Buclaw
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 --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
{
--
2.40.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2024-03-17 11:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-17 11:15 [committed] d: Merge upstream dmd, druntime 855353a1d9 Iain Buclaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).