aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2024-01-18 02:39:20 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2024-02-03 00:49:46 +0100
commitf204359931866b917856fc959c70dbf55f28c14d (patch)
treeba1c671045e384fa49a6381f79abf7c1b84a55ea /gcc/d/dmd
parent5470a9b176c2b3030ff3891c7e9403db2b0685b8 (diff)
downloadgcc-f204359931866b917856fc959c70dbf55f28c14d.zip
gcc-f204359931866b917856fc959c70dbf55f28c14d.tar.gz
gcc-f204359931866b917856fc959c70dbf55f28c14d.tar.bz2
d: Merge dmd, druntime bce5c1f7b5, phobos e4d0dd513.
D front-end changes: - Import latest changes from dmd v2.107.0-beta.1. - Keywords like `__FILE__' are now always evaluated at the callsite. D runtime changes: - Import latest changes from druntime v2.107.0-beta.1. - Added `nameSig' field to TypeInfo_Class in object.d. Phobos changes: - Import latest changes from phobos v2.107.0-beta.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd bce5c1f7b5. * d-attribs.cc (build_attributes): Update for new front-end interface. * d-lang.cc (d_parse_file): Likewise. * decl.cc (DeclVisitor::visit (VarDeclaration *)): Likewise. * expr.cc (build_lambda_tree): New function. (ExprVisitor::visit (FuncExp *)): Use build_lambda_tree. (ExprVisitor::visit (SymOffExp *)): Likewise. (ExprVisitor::visit (VarExp *)): Likewise. * typeinfo.cc (create_tinfo_types): Add two ulong fields to internal TypeInfo representation. (TypeInfoVisitor::visit (TypeInfoClassDeclaration *)): Emit stub data for TypeInfo_Class.nameSig. (TypeInfoVisitor::visit (TypeInfoStructDeclaration *)): Update for new front-end interface. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime bce5c1f7b5. * src/MERGE: Merge upstream phobos e4d0dd513.
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/astenums.d6
-rw-r--r--gcc/d/dmd/constfold.d1
-rw-r--r--gcc/d/dmd/declaration.d29
-rw-r--r--gcc/d/dmd/dinterpret.d132
-rw-r--r--gcc/d/dmd/dmodule.d18
-rw-r--r--gcc/d/dmd/doc.d1
-rw-r--r--gcc/d/dmd/dscope.d1
-rw-r--r--gcc/d/dmd/dsymbolsem.d6
-rw-r--r--gcc/d/dmd/dtemplate.d964
-rw-r--r--gcc/d/dmd/dtoh.d11
-rw-r--r--gcc/d/dmd/escape.d1
-rw-r--r--gcc/d/dmd/expression.d33
-rw-r--r--gcc/d/dmd/expressionsem.d243
-rw-r--r--gcc/d/dmd/file_manager.d30
-rw-r--r--gcc/d/dmd/func.d33
-rw-r--r--gcc/d/dmd/globals.d4
-rw-r--r--gcc/d/dmd/globals.h2
-rw-r--r--gcc/d/dmd/mtype.d573
-rw-r--r--gcc/d/dmd/mtype.h35
-rw-r--r--gcc/d/dmd/mustuse.d1
-rw-r--r--gcc/d/dmd/ob.d1
-rw-r--r--gcc/d/dmd/parse.d61
-rw-r--r--gcc/d/dmd/safe.d1
-rw-r--r--gcc/d/dmd/scope.h1
-rw-r--r--gcc/d/dmd/semantic3.d6
-rw-r--r--gcc/d/dmd/sideeffect.d1
-rw-r--r--gcc/d/dmd/statementsem.d5
-rw-r--r--gcc/d/dmd/template.h2
-rw-r--r--gcc/d/dmd/typesem.d564
30 files changed, 1445 insertions, 1323 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 2b4400f..138b0b6 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-d8e3976a58d6aef7c2c9371028a2ca4460b5b2ce
+bce5c1f7b521d22dcf1ea4e2bc3f76d9d28274fa
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/astenums.d b/gcc/d/dmd/astenums.d
index f19edb9..77940b8 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -459,3 +459,9 @@ extern (C++) struct structalign_t
bool isPack() const { return pack; }
void setPack(bool pack) { this.pack = pack; }
}
+
+/// Use to return D arrays from C++ functions
+extern (C++) struct DArray(T)
+{
+ T[] data;
+}
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 7bd9691..cee1f63 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -1038,6 +1038,7 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
else if (tb.ty == Tstruct && e1.op == EXP.int64)
{
// Struct = 0;
+ import dmd.typesem : toDsymbol;
StructDeclaration sd = tb.toDsymbol(null).isStructDeclaration();
assert(sd);
auto elements = new Expressions();
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 5869a22..93ef63f 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -1749,6 +1749,35 @@ extern (C++) final class SymbolDeclaration : Declaration
/***********************************************************
*/
+private Identifier getTypeInfoIdent(Type t)
+{
+ import dmd.dmangle;
+ import core.stdc.stdlib;
+ import dmd.root.rmem;
+ // _init_10TypeInfo_%s
+ OutBuffer buf;
+ buf.reserve(32);
+ mangleToBuffer(t, buf);
+
+ const slice = buf[];
+
+ // Allocate buffer on stack, fail over to using malloc()
+ char[128] namebuf;
+ const namelen = 19 + size_t.sizeof * 3 + slice.length + 1;
+ auto name = namelen <= namebuf.length ? namebuf.ptr : cast(char*)Mem.check(malloc(namelen));
+
+ const length = snprintf(name, namelen, "_D%lluTypeInfo_%.*s6__initZ",
+ cast(ulong)(9 + slice.length), cast(int)slice.length, slice.ptr);
+ //printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name);
+ assert(0 < length && length < namelen); // don't overflow the buffer
+
+ auto id = Identifier.idPool(name[0 .. length]);
+
+ if (name != namebuf.ptr)
+ free(name);
+ return id;
+}
+
extern (C++) class TypeInfoDeclaration : VarDeclaration
{
Type tinfo;
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index eda91d1..a3b38d9 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -1416,6 +1416,7 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate)
foreach (ca; *s.catches)
{
Type catype = ca.type;
+ import dmd.typesem : isBaseOf;
if (!catype.equals(extype) && !catype.isBaseOf(extype, null))
continue;
@@ -6237,6 +6238,11 @@ public:
{
if (soe.offset == 0 && soe.var.isFuncDeclaration())
return;
+ if (soe.offset == 0 && soe.var.isVarDeclaration() && soe.var.isImmutable())
+ {
+ result = getVarExp(e.loc, istate, soe.var, CTFEGoal.RValue);
+ return;
+ }
error(e.loc, "cannot dereference pointer to static variable `%s` at compile time", soe.var.toChars());
result = CTFEExp.cantexp;
return;
@@ -6359,6 +6365,7 @@ public:
{
if (auto t = isType(ex.isTypeidExp().obj))
{
+ import dmd.typesem : toDsymbol;
auto sym = t.toDsymbol(null);
if (auto ident = (sym ? sym.ident : null))
{
@@ -6643,6 +6650,7 @@ Expressions* copyArrayOnWrite(Expressions* exps, Expressions* original)
private
bool stopPointersEscaping(const ref Loc loc, Expression e)
{
+ import dmd.typesem : hasPointers;
if (!e.type.hasPointers())
return true;
if (isPointer(e.type))
@@ -6706,7 +6714,7 @@ Statement findGotoTarget(InterState* istate, Identifier ident)
Statement target = null;
if (ident)
{
- LabelDsymbol label = istate.fd.searchLabel(ident);
+ LabelDsymbol label = istate.fd.searchLabel(ident, Loc.initial);
assert(label && label.statement);
LabelStatement ls = label.statement;
target = ls.gotoTarget ? ls.gotoTarget : ls.statement;
@@ -7263,6 +7271,33 @@ private Expression interpret_aaApply(UnionExp* pue, InterState* istate, Expressi
return eresult;
}
+/// Returns: equivalent `StringExp` from `ArrayLiteralExp ale` containing only `IntegerExp` elements
+StringExp arrayLiteralToString(ArrayLiteralExp ale)
+{
+ const len = ale.elements ? ale.elements.length : 0;
+ const size = ale.type.nextOf().size();
+
+ StringExp impl(T)()
+ {
+ T[] result = new T[len];
+ foreach (i; 0 .. len)
+ result[i] = cast(T) (*ale.elements)[i].isIntegerExp().getInteger();
+ return new StringExp(ale.loc, result[], len, cast(ubyte) size);
+ }
+
+ switch (size)
+ {
+ case 1:
+ return impl!char();
+ case 2:
+ return impl!wchar();
+ case 4:
+ return impl!dchar();
+ default:
+ assert(0);
+ }
+}
+
/* Decoding UTF strings for foreach loops. Duplicates the functionality of
* the twelve _aApplyXXn functions in aApply.d in the runtime.
*/
@@ -7299,8 +7334,10 @@ private Expression foreachApplyUtf(UnionExp* pue, InterState* istate, Expression
str = resolveSlice(str, &strTmp);
auto se = str.isStringExp();
- auto ale = str.isArrayLiteralExp();
- if (!se && !ale)
+ if (auto ale = str.isArrayLiteralExp())
+ se = arrayLiteralToString(ale);
+
+ if (!se)
{
error(str.loc, "CTFE internal error: cannot foreach `%s`", str.toChars());
return CTFEExp.cantexp;
@@ -7309,7 +7346,7 @@ private Expression foreachApplyUtf(UnionExp* pue, InterState* istate, Expression
Expression eresult = null; // ded-store to prevent spurious warning
- // Buffers for encoding; also used for decoding array literals
+ // Buffers for encoding
char[4] utf8buf = void;
wchar[2] utf16buf = void;
@@ -7323,90 +7360,11 @@ private Expression foreachApplyUtf(UnionExp* pue, InterState* istate, Expression
dchar rawvalue; // Holds the decoded dchar
size_t currentIndex = indx; // The index of the decoded character
- if (ale)
- {
- // If it is an array literal, copy the code points into the buffer
- size_t buflen = 1; // #code points in the buffer
- size_t n = 1; // #code points in this char
- size_t sz = cast(size_t)ale.type.nextOf().size();
+ // String literals
+ size_t saveindx; // used for reverse iteration
- switch (sz)
- {
- case 1:
- if (rvs)
- {
- // find the start of the string
- --indx;
- buflen = 1;
- while (indx > 0 && buflen < 4)
- {
- Expression r = (*ale.elements)[indx];
- char x = cast(char)r.isIntegerExp().getInteger();
- if ((x & 0xC0) != 0x80)
- break;
- --indx;
- ++buflen;
- }
- }
- else
- buflen = (indx + 4 > len) ? len - indx : 4;
- for (size_t i = 0; i < buflen; ++i)
- {
- Expression r = (*ale.elements)[indx + i];
- utf8buf[i] = cast(char)r.isIntegerExp().getInteger();
- }
- n = 0;
- errmsg = utf_decodeChar(utf8buf[0 .. buflen], n, rawvalue);
- break;
-
- case 2:
- if (rvs)
- {
- // find the start of the string
- --indx;
- buflen = 1;
- Expression r = (*ale.elements)[indx];
- ushort x = cast(ushort)r.isIntegerExp().getInteger();
- if (indx > 0 && x >= 0xDC00 && x <= 0xDFFF)
- {
- --indx;
- ++buflen;
- }
- }
- else
- buflen = (indx + 2 > len) ? len - indx : 2;
- for (size_t i = 0; i < buflen; ++i)
- {
- Expression r = (*ale.elements)[indx + i];
- utf16buf[i] = cast(ushort)r.isIntegerExp().getInteger();
- }
- n = 0;
- errmsg = utf_decodeWchar(utf16buf[0 .. buflen], n, rawvalue);
- break;
-
- case 4:
- {
- if (rvs)
- --indx;
- Expression r = (*ale.elements)[indx];
- rawvalue = cast(dchar)r.isIntegerExp().getInteger();
- n = 1;
- }
- break;
-
- default:
- assert(0);
- }
- if (!rvs)
- indx += n;
- }
- else
+ switch (se.sz)
{
- // String literals
- size_t saveindx; // used for reverse iteration
-
- switch (se.sz)
- {
case 1:
{
if (rvs)
@@ -7450,8 +7408,8 @@ private Expression foreachApplyUtf(UnionExp* pue, InterState* istate, Expression
default:
assert(0);
- }
}
+
if (errmsg)
{
error(deleg.loc, "`%.*s`", cast(int)errmsg.length, errmsg.ptr);
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 022231c..59d4065 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -679,23 +679,23 @@ extern (C++) final class Module : Package
/* Preprocess the file if it's a .c file
*/
FileName filename = srcfile;
- bool ifile = false; // did we generate a .i file
- scope (exit)
- {
- if (ifile)
- File.remove(filename.toChars()); // remove generated file
- }
+ const(ubyte)[] srctext;
if (global.preprocess &&
FileName.equalsExt(srcfile.toString(), c_ext) &&
FileName.exists(srcfile.toString()))
{
- filename = global.preprocess(srcfile, loc, ifile, &defines); // run C preprocessor
+ /* Apply C preprocessor to the .c file, returning the contents
+ * after preprocessing
+ */
+ srctext = global.preprocess(srcfile, loc, defines).data;
}
+ else
+ srctext = global.fileManager.getFileContents(filename);
+ this.src = srctext;
- if (auto result = global.fileManager.lookup(filename))
+ if (srctext)
{
- this.src = result;
if (global.params.makeDeps.doOutput)
global.params.makeDeps.files.push(srcfile.toChars());
return true;
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index 810642f..ec3cc91 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -1355,6 +1355,7 @@ void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc)
{
if (type.ty == Tclass || type.ty == Tstruct || type.ty == Tenum)
{
+ import dmd.typesem : toDsymbol;
if (Dsymbol s = type.toDsymbol(null)) // elaborate type
prettyPrintDsymbol(s, ad.parent);
else
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 7e9499f..e02ba9a 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -97,6 +97,7 @@ extern (C++) struct Scope
Dsymbol inunion; /// != null if processing members of a union
bool nofree; /// true if shouldn't free it
bool inLoop; /// true if inside a loop (where constructor calls aren't allowed)
+ bool inDefaultArg; /// true if inside a default argument (where __FILE__, etc are evaluated at the call site)
int intypeof; /// in typeof(exp)
VarDeclaration lastVar; /// Previous symbol used to prevent goto-skips-init
ErrorSink eSink; /// sink for error messages
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 23f0bc5..e9cdb94 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -6553,7 +6553,8 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration();
assert(tempdecl);
- TemplateStats.incInstance(tempdecl, tempinst);
+ if (global.params.v.templates)
+ TemplateStats.incInstance(tempdecl, tempinst, global.params.v.templatesListInstances);
tempdecl.checkDeprecated(tempinst.loc, sc);
@@ -6746,7 +6747,8 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
tempinst.parent = tempinst.enclosing ? tempinst.enclosing : tempdecl.parent;
//printf("parent = '%s'\n", parent.kind());
- TemplateStats.incUnique(tempdecl, tempinst);
+ if (global.params.v.templates)
+ TemplateStats.incUnique(tempdecl, tempinst);
TemplateInstance tempdecl_instance_idx = tempdecl.addInstance(tempinst);
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 1d84ccd..13cc32f 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -56,6 +56,7 @@ import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
+import dmd.errorsink;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
@@ -150,7 +151,7 @@ extern (C++) bool isError(const RootObject o)
if (const e = isExpression(o))
return (e.op == EXP.error || !e.type || e.type.ty == Terror);
if (const v = isTuple(o))
- return arrayObjectIsError(&v.objects);
+ return arrayObjectIsError(v.objects);
const s = isDsymbol(o);
assert(s);
if (s.errors)
@@ -161,9 +162,9 @@ extern (C++) bool isError(const RootObject o)
/**************************************
* Are any of the Objects an error?
*/
-bool arrayObjectIsError(const Objects* args)
+bool arrayObjectIsError(const ref Objects args)
{
- foreach (const o; *args)
+ foreach (const o; args)
{
if (isError(o))
return true;
@@ -187,6 +188,13 @@ inout(Type) getType(inout RootObject o)
}
+/***********************************
+ * If oarg represents a Dsymbol, return that Dsymbol
+ * Params:
+ * oarg = argument to check
+ * Returns:
+ * Dsymbol if a symbol, null if not
+ */
Dsymbol getDsymbol(RootObject oarg)
{
//printf("getDsymbol()\n");
@@ -256,8 +264,11 @@ private Expression getExpression(RootObject o)
}
/******************************
- * If o1 matches o2, return true.
- * Else, return false.
+ * See if two objects match
+ * Params:
+ * o1 = first object
+ * o2 = second object
+ * Returns: true if they match
*/
private bool match(RootObject o1, RootObject o2)
{
@@ -343,7 +354,7 @@ private bool match(RootObject o1, RootObject o2)
printf("\tu1 = %s\n", u1.toChars());
printf("\tu2 = %s\n", u2.toChars());
}
- if (!arrayObjectMatch(&u1.objects, &u2.objects))
+ if (!arrayObjectMatch(u1.objects, u2.objects))
goto Lnomatch;
goto Lmatch;
@@ -362,15 +373,15 @@ Lnomatch:
/************************************
* Match an array of them.
*/
-private bool arrayObjectMatch(Objects* oa1, Objects* oa2)
+private bool arrayObjectMatch(ref Objects oa1, ref Objects oa2)
{
- if (oa1 == oa2)
+ if (&oa1 == &oa2)
return true;
if (oa1.length != oa2.length)
return false;
immutable oa1dim = oa1.length;
- auto oa1d = (*oa1)[].ptr;
- auto oa2d = (*oa2)[].ptr;
+ auto oa1d = oa1[].ptr;
+ auto oa2d = oa2[].ptr;
foreach (j; 0 .. oa1dim)
{
RootObject o1 = oa1d[j];
@@ -386,12 +397,12 @@ private bool arrayObjectMatch(Objects* oa1, Objects* oa2)
/************************************
* Return hash of Objects.
*/
-private size_t arrayObjectHash(Objects* oa1)
+private size_t arrayObjectHash(ref Objects oa1)
{
import dmd.root.hash : mixHash;
size_t hash = 0;
- foreach (o1; *oa1)
+ foreach (o1; oa1)
{
/* Must follow the logic of match()
*/
@@ -407,7 +418,7 @@ private size_t arrayObjectHash(Objects* oa1)
hash = mixHash(hash, mixHash(cast(size_t)cast(void*)s1.getIdent(), cast(size_t)cast(void*)s1.parent));
}
else if (auto u1 = isTuple(o1))
- hash = mixHash(hash, arrayObjectHash(&u1.objects));
+ hash = mixHash(hash, arrayObjectHash(u1.objects));
}
return hash;
}
@@ -672,7 +683,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
/**********************************
* Overload existing TemplateDeclaration 'this' with the new one 's'.
- * Return true if successful; i.e. no conflict.
+ * Params:
+ * s = symbol to be inserted
+ * Return: true if successful; i.e. no conflict.
*/
override bool overloadInsert(Dsymbol s)
{
@@ -741,6 +754,8 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
return toCharsMaybeConstraints(false);
}
+ // Note: this function is not actually `const`, because iterating the
+ // function parameter list may run dsymbolsemantic on enum types
const(char)* toCharsMaybeConstraints(bool includeConstraints) const
{
OutBuffer buf;
@@ -758,15 +773,17 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
if (onemember)
{
- const FuncDeclaration fd = onemember.isFuncDeclaration();
- if (fd && fd.type)
+ if (const fd = onemember.isFuncDeclaration())
{
- TypeFunction tf = cast(TypeFunction)fd.type;
- buf.writestring(parametersTypeToChars(tf.parameterList));
- if (tf.mod)
+ if (TypeFunction tf = cast(TypeFunction)fd.type.isTypeFunction())
{
- buf.writeByte(' ');
- buf.MODtoBuffer(tf.mod);
+ // !! Casted away const
+ buf.writestring(parametersTypeToChars(tf.parameterList));
+ if (tf.mod)
+ {
+ buf.writeByte(' ');
+ buf.MODtoBuffer(tf.mod);
+ }
}
}
}
@@ -790,7 +807,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
/****************************
* Check to see if constraint is satisfied.
*/
- extern (D) bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
+ private bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
{
/* Detect recursive attempts to instantiate this template declaration,
* https://issues.dlang.org/show_bug.cgi?id=4072
@@ -807,7 +824,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
for (TemplatePrevious* p = previous; p; p = p.prev)
{
- if (!arrayObjectMatch(p.dedargs, dedargs))
+ if (!arrayObjectMatch(*p.dedargs, *dedargs))
continue;
//printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
/* It must be a subscope of p.sc, other scope chains are not recursive
@@ -1055,7 +1072,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
* dedtypes deduced arguments
* Return match level.
*/
- extern (D) MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, ArgumentList argumentList, int flag)
+ private MATCH matchWithInstance(Scope* sc, TemplateInstance ti, ref Objects dedtypes, ArgumentList argumentList, int flag)
{
enum LOGM = 0;
static if (LOGM)
@@ -1151,7 +1168,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
/* Any parameter left without a type gets the type of
* its corresponding arg
*/
- foreach (i, ref dedtype; *dedtypes)
+ foreach (i, ref dedtype; dedtypes)
{
if (!dedtype)
{
@@ -1202,7 +1219,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
// TODO: dedtypes => ti.tiargs ?
- if (!evaluateConstraint(ti, sc, paramscope, dedtypes, fd))
+ if (!evaluateConstraint(ti, sc, paramscope, &dedtypes, fd))
return nomatch();
}
@@ -1283,7 +1300,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
Objects dedtypes = Objects(td2.parameters.length);
// Attempt a type deduction
- MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, argumentList, 1);
+ MATCH m = td2.matchWithInstance(sc, ti, dedtypes, argumentList, 1);
if (m > MATCH.nomatch)
{
/* A non-variadic template is more specialized than a
@@ -1425,7 +1442,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
{
assert(i < parameters.length);
Declaration sparam = null;
- MATCH m = (*parameters)[i].matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, &sparam);
+ MATCH m = (*parameters)[i].matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, &sparam);
//printf("\tdeduceType m = %d\n", m);
if (m == MATCH.nomatch)
return nomatch();
@@ -1458,10 +1475,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
ParameterList fparameters = fd.getParameterList(); // function parameter list
const nfparams = fparameters.length; // number of function parameters
- const nfargs = argumentList.length; // number of function arguments
if (argumentList.hasNames)
return matcherror(); // TODO: resolve named args
- Expressions* fargs = argumentList.arguments; // TODO: resolve named args
+ Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null;
/* Check for match of function arguments with variadic template
* parameter, such as:
@@ -1475,7 +1491,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
// TemplateTupleParameter always makes most lesser matching.
matchTiargs = MATCH.convert;
- if (nfparams == 0 && nfargs != 0) // if no function parameters
+ if (nfparams == 0 && argumentList.length != 0) // if no function parameters
{
if (!declaredTuple)
{
@@ -1498,7 +1514,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
auto fparam = (*fparameters.parameters)[fptupindex]; // fparameters[fptupindex] ?
if (fparam.type.ty != Tident)
continue;
- TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
+ TypeIdentifier tid = fparam.type.isTypeIdentifier();
if (!tp.ident.equals(tid.ident) || tid.idents.length)
continue;
@@ -1527,7 +1543,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
hasttp = true;
Type t = new TypeIdentifier(Loc.initial, ttp.ident);
- MATCH m = deduceType(tthis, paramscope, t, parameters, dedtypes);
+ MATCH m = deduceType(tthis, paramscope, t, *parameters, *dedtypes);
if (m == MATCH.nomatch)
return nomatch();
if (m < match)
@@ -1576,7 +1592,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
//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 = nfargs; // nfargs + supplied defaultArgs
+ size_t nfargs2 = fargs.length; // nfargs + supplied defaultArgs
uint inoutMatch = 0; // for debugging only
for (size_t parami = 0; parami < nfparams; parami++)
{
@@ -1592,8 +1608,8 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
*/
if (fptupindex != IDX_NOTFOUND && parami == fptupindex)
{
- assert(prmtype.ty == Tident);
- TypeIdentifier tid = cast(TypeIdentifier)prmtype;
+ TypeIdentifier tid = prmtype.isTypeIdentifier();
+ assert(tid);
if (!declaredTuple)
{
/* The types of the function arguments
@@ -1606,7 +1622,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
* void foo(U, T...)(int y, T, U, double, int bar = 0) {} // rem == 2 (U, double)
*/
size_t rem = 0;
- for (size_t j = parami + 1; j < nfparams; j++)
+ foreach (j; parami + 1 .. nfparams)
{
Parameter p = fparameters[j];
if (p.defaultArg)
@@ -1616,7 +1632,10 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
if (!reliesOnTemplateParameters(p.type, (*parameters)[inferStart .. parameters.length]))
{
Type pt = p.type.syntaxCopy().typeSemantic(fd.loc, paramscope);
- rem += pt.ty == Ttuple ? (cast(TypeTuple)pt).arguments.length : 1;
+ if (auto ptt = pt.isTypeTuple())
+ rem += ptt.arguments.length;
+ else
+ rem += 1;
}
else
{
@@ -1627,9 +1646,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
if (nfargs2 - argi < rem)
return nomatch();
declaredTuple.objects.setDim(nfargs2 - argi - rem);
- for (size_t i = 0; i < declaredTuple.objects.length; i++)
+ foreach (i; 0 .. declaredTuple.objects.length)
{
- farg = (*fargs)[argi + i];
+ farg = fargs[argi + i];
// Check invalid arguments to detect errors early.
if (farg.op == EXP.error || farg.type.ty == Terror)
@@ -1647,7 +1666,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
else
{
- m = deduceTypeHelper(farg.type, &tt, tid);
+ m = deduceTypeHelper(farg.type, tt, tid);
}
if (m == MATCH.nomatch)
return nomatch();
@@ -1687,20 +1706,19 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
// should copy prmtype to avoid affecting semantic result
prmtype = prmtype.syntaxCopy().typeSemantic(fd.loc, paramscope);
- if (prmtype.ty == Ttuple)
+ if (TypeTuple tt = prmtype.isTypeTuple())
{
- TypeTuple tt = cast(TypeTuple)prmtype;
- size_t tt_dim = tt.arguments.length;
+ const tt_dim = tt.arguments.length;
for (size_t j = 0; j < tt_dim; j++, ++argi)
{
Parameter p = (*tt.arguments)[j];
if (j == tt_dim - 1 && fparameters.varargs == VarArg.typesafe &&
- parami + 1 == nfparams && argi < nfargs)
+ parami + 1 == nfparams && argi < fargs.length)
{
prmtype = p.type;
goto Lvarargs;
}
- if (argi >= nfargs)
+ if (argi >= fargs.length)
{
if (p.defaultArg)
continue;
@@ -1711,7 +1729,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
return nomatch();
}
- farg = (*fargs)[argi];
+ farg = fargs[argi];
if (!farg.implicitConvTo(p.type))
return nomatch();
}
@@ -1719,7 +1737,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
}
- if (argi >= nfargs) // if not enough arguments
+ if (argi >= fargs.length) // if not enough arguments
{
if (!fparam.defaultArg)
goto Lvarargs;
@@ -1741,7 +1759,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
* // at fparam `N start = 0`, N should be 'size_t' before
* // the deduction result from fparam.defaultArg.
*/
- if (argi == nfargs)
+ if (argi == fargs.length)
{
foreach (ref dedtype; *dedtypes)
{
@@ -1769,7 +1787,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
* the oded == oarg
*/
(*dedargs)[i] = oded;
- MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
+ MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, null);
//printf("m2 = %d\n", m2);
if (m2 == MATCH.nomatch)
return nomatch();
@@ -1822,7 +1840,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
else
{
- farg = (*fargs)[argi];
+ farg = fargs[argi];
}
{
// Check invalid arguments to detect errors early.
@@ -1851,8 +1869,15 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
{
/* Allow expressions that have CT-known boundaries and type [] to match with [dim]
*/
- Type taai;
- if (argtype.ty == Tarray && (prmtype.ty == Tsarray || prmtype.ty == Taarray && (taai = (cast(TypeAArray)prmtype).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
+ bool inferIndexType = (argtype.ty == Tarray) && (prmtype.ty == Tsarray || prmtype.ty == Taarray);
+ if (auto aaType = prmtype.isTypeAArray())
+ {
+ if (auto indexType = aaType.index.isTypeIdentifier())
+ {
+ inferIndexType = indexType.idents.length == 0;
+ }
+ }
+ if (inferIndexType)
{
if (StringExp se = farg.isStringExp())
{
@@ -1871,7 +1896,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
oarg = argtype;
}
- else if ((fparam.storageClass & STC.out_) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && (cast(TypeIdentifier)prmtype).idents.length == 0)
+ else if ((fparam.storageClass & STC.out_) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && prmtype.isTypeIdentifier().idents.length == 0)
{
/* The farg passing to the prmtype always make a copy. Therefore,
* we can shrink the set of the deduced type arguments for prmtype
@@ -1892,11 +1917,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
}
- if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < nfargs)
+ if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < fargs.length)
goto Lvarargs;
uint im = 0;
- MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &im, inferStart);
+ MATCH m = deduceType(oarg, paramscope, prmtype, *parameters, *dedtypes, &im, inferStart);
//printf("\tL%d deduceType m = %d, im = x%x, inoutMatch = x%x\n", __LINE__, m, im, inoutMatch);
inoutMatch |= im;
@@ -1984,17 +2009,15 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
case Taarray:
{
// Perhaps we can do better with this, see TypeFunction.callMatch()
- if (tb.ty == Tsarray)
+ if (TypeSArray tsa = tb.isTypeSArray())
{
- TypeSArray tsa = cast(TypeSArray)tb;
dinteger_t sz = tsa.dim.toInteger();
- if (sz != nfargs - argi)
+ if (sz != fargs.length - argi)
return nomatch();
}
- else if (tb.ty == Taarray)
+ else if (TypeAArray taa = tb.isTypeAArray())
{
- TypeAArray taa = cast(TypeAArray)tb;
- Expression dim = new IntegerExp(instLoc, nfargs - argi, Type.tsize_t);
+ Expression dim = new IntegerExp(instLoc, fargs.length - argi, Type.tsize_t);
size_t i = templateParameterLookup(taa.index, parameters);
if (i == IDX_NOTFOUND)
@@ -2057,9 +2080,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
{
TypeArray ta = cast(TypeArray)tb;
Type tret = fparam.isLazyArray();
- for (; argi < nfargs; argi++)
+ for (; argi < fargs.length; argi++)
{
- Expression arg = (*fargs)[argi];
+ Expression arg = fargs[argi];
assert(arg);
MATCH m;
@@ -2085,7 +2108,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
else
{
uint wm = 0;
- m = deduceType(arg, paramscope, ta.next, parameters, dedtypes, &wm, inferStart);
+ m = deduceType(arg, paramscope, ta.next, *parameters, *dedtypes, &wm, inferStart);
inoutMatch |= wm;
}
if (m == MATCH.nomatch)
@@ -2112,8 +2135,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
Lmatch:
foreach (ref dedtype; *dedtypes)
{
- Type at = isType(dedtype);
- if (at)
+ if (Type at = isType(dedtype))
{
if (at.ty == Tnone)
{
@@ -2147,7 +2169,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
* the oded == oarg
*/
(*dedargs)[i] = oded;
- MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
+ MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, null);
//printf("m2 = %d\n", m2);
if (m2 == MATCH.nomatch)
return nomatch();
@@ -2194,7 +2216,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
if (tparam.specialization())
{
(*dedargs)[i] = oded;
- MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
+ MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, null);
//printf("m2 = %d\n", m2);
if (m2 == MATCH.nomatch)
return nomatch();
@@ -2233,7 +2255,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
sc2.minst = sc.minst;
sc2.stc |= fd.storage_class & STC.deprecated_;
- fd = doHeaderInstantiation(ti, sc2, fd, tthis, fargs);
+ fd = doHeaderInstantiation(ti, sc2, fd, tthis, argumentList.arguments);
sc2 = sc2.pop();
sc2 = sc2.pop();
@@ -2396,7 +2418,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
if (hasttp)
{
- tf = cast(TypeFunction)tf.addSTC(ModToStc(tthis.mod));
+ tf = tf.addSTC(ModToStc(tthis.mod)).isTypeFunction();
assert(!tf.deco);
}
}
@@ -2602,10 +2624,10 @@ extern (C++) final class TypeDeduced : Type
* tiargs = initial list of template arguments
* tthis = if !NULL, the 'this' pointer argument
* argumentList= arguments to function
- * pMessage = address to store error message, or null
+ * errorHelper = delegate to send error message to if not null
*/
void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs,
- Type tthis, ArgumentList argumentList, const(char)** pMessage = null)
+ Type tthis, ArgumentList argumentList, void delegate(const(char)*) scope errorHelper = null)
{
version (none)
{
@@ -2662,7 +2684,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
return 1;
}
//printf("fd = %s %s, fargs = %s\n", fd.toChars(), fd.type.toChars(), fargs.toChars());
- auto tf = cast(TypeFunction)fd.type;
+ auto tf = fd.type.isTypeFunction();
int prop = tf.isproperty ? 1 : 2;
if (property == 0)
@@ -2711,8 +2733,12 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
else if (shared_this && !shared_dtor && tthis_fd !is null)
tf.mod = tthis_fd.mod;
}
- MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, pMessage, sc);
+ const(char)* failMessage;
+ const(char)** pMessage = errorHelper ? &failMessage : null;
+ MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, errorHelper, sc);
//printf("test1: mfa = %d\n", mfa);
+ if (failMessage)
+ errorHelper(failMessage);
if (mfa == MATCH.nomatch)
return 0;
@@ -2850,7 +2876,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
auto ti = new TemplateInstance(loc, td, tiargs);
Objects dedtypes = Objects(td.parameters.length);
assert(td.semanticRun != PASS.initial);
- MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, argumentList, 0);
+ MATCH mta = td.matchWithInstance(sc, ti, dedtypes, argumentList, 0);
//printf("matchWithInstance = %d\n", mta);
if (mta == MATCH.nomatch || mta < ta_last) // no match or less match
return 0;
@@ -2869,7 +2895,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
// Check for recursive instantiation of tdx.
for (TemplatePrevious* p = tdx.previous; p; p = p.prev)
{
- if (arrayObjectMatch(p.dedargs, &dedtypesX))
+ if (arrayObjectMatch(*p.dedargs, dedtypesX))
{
//printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
/* It must be a subscope of p.sc, other scope chains are not recursive
@@ -2918,7 +2944,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null;
- auto tf = cast(TypeFunction)fd.type;
+ auto tf = fd.type.isTypeFunction();
MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, null, sc);
if (mfa < m.last)
return 0;
@@ -2979,7 +3005,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
if (isCtorCall)
{
// Constructor call requires additional check.
- auto tf = cast(TypeFunction)fd.type;
+ auto tf = fd.type.isTypeFunction();
assert(tf.next);
if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
tf.isWild() && tf.isShared() == tthis_fd.isShared() ||
@@ -3175,9 +3201,8 @@ private size_t templateIdentifierLookup(Identifier id, TemplateParameters* param
private size_t templateParameterLookup(Type tparam, TemplateParameters* parameters)
{
- if (tparam.ty == Tident)
+ if (TypeIdentifier tident = tparam.isTypeIdentifier())
{
- TypeIdentifier tident = cast(TypeIdentifier)tparam;
//printf("\ttident = '%s'\n", tident.toChars());
return templateIdentifierLookup(tident.ident, parameters);
}
@@ -3267,7 +3292,7 @@ private Type rawTypeMerge(Type t1, Type t2)
return null;
}
-private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
+private MATCH deduceTypeHelper(Type t, out Type at, Type tparam)
{
// 9*9 == 81 cases
@@ -3297,7 +3322,7 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
// foo(U) shared(inout(const(T))) => shared(inout(const(T)))
// foo(U) immutable(T) => immutable(T)
{
- *at = t;
+ at = t;
return MATCH.exact;
}
case X(MODFlags.const_, MODFlags.const_):
@@ -3317,7 +3342,7 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
// foo(shared(inout(const(U)))) shared(inout(const(T))) => T
// foo(immutable(U)) immutable(T) => T
{
- *at = t.mutableOf().unSharedOf();
+ at = t.mutableOf().unSharedOf();
return MATCH.exact;
}
case X(MODFlags.const_, MODFlags.shared_ | MODFlags.const_):
@@ -3327,7 +3352,7 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
// foo(inout(U)) shared(inout(T)) => shared(T)
// foo(inout(const(U))) shared(inout(const(T))) => shared(T)
{
- *at = t.mutableOf();
+ at = t.mutableOf();
return MATCH.exact;
}
case X(MODFlags.const_, 0):
@@ -3345,13 +3370,13 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
// foo(const(U)) immutable(T) => T
// foo(shared(const(U))) immutable(T) => T
{
- *at = t.mutableOf();
+ at = t.mutableOf();
return MATCH.constant;
}
case X(MODFlags.const_, MODFlags.shared_):
// foo(const(U)) shared(T) => shared(T)
{
- *at = t;
+ at = t;
return MATCH.constant;
}
case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.const_):
@@ -3361,13 +3386,13 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
// foo(shared(U)) shared(inout(T)) => inout(T)
// foo(shared(U)) shared(inout(const(T))) => inout(const(T))
{
- *at = t.unSharedOf();
+ at = t.unSharedOf();
return MATCH.exact;
}
case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_):
// foo(shared(const(U))) shared(T) => T
{
- *at = t.unSharedOf();
+ at = t.unSharedOf();
return MATCH.constant;
}
case X(MODFlags.wildconst, MODFlags.immutable_):
@@ -3379,13 +3404,13 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
// foo(shared(inout(const(U)))) immutable(T) => T
// foo(shared(inout(const(U)))) shared(inout(T)) => T
{
- *at = t.unSharedOf().mutableOf();
+ at = t.unSharedOf().mutableOf();
return MATCH.constant;
}
case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.wild):
// foo(shared(const(U))) shared(inout(T)) => T
{
- *at = t.unSharedOf().mutableOf();
+ at = t.unSharedOf().mutableOf();
return MATCH.constant;
}
case X(MODFlags.wild, 0):
@@ -3499,30 +3524,16 @@ __gshared Expression emptyArrayElement = null;
* Output:
* dedtypes = [ int ] // Array of Expression/Type's
*/
-MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm = null, size_t inferStart = 0, bool ignoreAliasThis = false)
+MATCH deduceType(RootObject o, Scope* sc, Type tparam, ref TemplateParameters parameters, ref Objects dedtypes, uint* wm = null, size_t inferStart = 0, bool ignoreAliasThis = false)
{
extern (C++) final class DeduceType : Visitor
{
alias visit = Visitor.visit;
public:
- Scope* sc;
- Type tparam;
- TemplateParameters* parameters;
- Objects* dedtypes;
- uint* wm;
- size_t inferStart;
- bool ignoreAliasThis;
MATCH result;
- extern (D) this(Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm, size_t inferStart, bool ignoreAliasThis) @safe
+ extern (D) this() @safe
{
- this.sc = sc;
- this.tparam = tparam;
- this.parameters = parameters;
- this.dedtypes = dedtypes;
- this.wm = wm;
- this.inferStart = inferStart;
- this.ignoreAliasThis = ignoreAliasThis;
result = MATCH.nomatch;
}
@@ -3537,7 +3548,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
if (tparam.ty == Tident)
{
// Determine which parameter tparam is
- size_t i = templateParameterLookup(tparam, parameters);
+ size_t i = templateParameterLookup(tparam, &parameters);
if (i == IDX_NOTFOUND)
{
if (!sc)
@@ -3548,7 +3559,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
Loc loc;
if (parameters.length)
{
- TemplateParameter tp = (*parameters)[0];
+ TemplateParameter tp = parameters[0];
loc = tp.loc;
}
@@ -3561,9 +3572,9 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
return;
}
- TemplateParameter tp = (*parameters)[i];
+ TemplateParameter tp = parameters[i];
- TypeIdentifier tident = cast(TypeIdentifier)tparam;
+ TypeIdentifier tident = tparam.isTypeIdentifier();
if (tident.idents.length > 0)
{
//printf("matching %s to %s\n", tparam.toChars(), t.toChars());
@@ -3601,21 +3612,21 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
Type tt = s.getType();
if (!tt)
goto Lnomatch;
- Type at = cast(Type)(*dedtypes)[i];
+ Type at = cast(Type)dedtypes[i];
if (at && at.ty == Tnone)
at = (cast(TypeDeduced)at).tded;
if (!at || tt.equals(at))
{
- (*dedtypes)[i] = tt;
+ dedtypes[i] = tt;
goto Lexact;
}
}
if (tp.isTemplateAliasParameter())
{
- Dsymbol s2 = cast(Dsymbol)(*dedtypes)[i];
+ Dsymbol s2 = cast(Dsymbol)dedtypes[i];
if (!s2 || s == s2)
{
- (*dedtypes)[i] = s;
+ dedtypes[i] = s;
goto Lexact;
}
}
@@ -3637,7 +3648,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
+/
if (auto ta = tp.isTemplateAliasParameter())
{
- (*dedtypes)[i] = t;
+ dedtypes[i] = t;
goto Lexact;
}
// (23578) - ensure previous behaviour for non-alias template params
@@ -3646,14 +3657,14 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
goto Lnomatch;
}
- Type at = cast(Type)(*dedtypes)[i];
+ Type at = cast(Type)dedtypes[i];
Type tt;
if (ubyte wx = wm ? deduceWildHelper(t, &tt, tparam) : 0)
{
// type vs (none)
if (!at)
{
- (*dedtypes)[i] = tt;
+ dedtypes[i] = tt;
*wm |= wx;
result = MATCH.constant;
return;
@@ -3662,11 +3673,11 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// type vs expressions
if (at.ty == Tnone)
{
- TypeDeduced xt = cast(TypeDeduced)at;
+ auto xt = cast(TypeDeduced)at;
result = xt.matchAll(tt);
if (result > MATCH.nomatch)
{
- (*dedtypes)[i] = tt;
+ dedtypes[i] = tt;
if (result > MATCH.constant)
result = MATCH.constant; // limit level for inout matches
}
@@ -3676,29 +3687,29 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// type vs type
if (tt.equals(at))
{
- (*dedtypes)[i] = tt; // Prefer current type match
+ dedtypes[i] = tt; // Prefer current type match
goto Lconst;
}
if (tt.implicitConvTo(at.constOf()))
{
- (*dedtypes)[i] = at.constOf().mutableOf();
+ dedtypes[i] = at.constOf().mutableOf();
*wm |= MODFlags.const_;
goto Lconst;
}
if (at.implicitConvTo(tt.constOf()))
{
- (*dedtypes)[i] = tt.constOf().mutableOf();
+ dedtypes[i] = tt.constOf().mutableOf();
*wm |= MODFlags.const_;
goto Lconst;
}
goto Lnomatch;
}
- else if (MATCH m = deduceTypeHelper(t, &tt, tparam))
+ else if (MATCH m = deduceTypeHelper(t, tt, tparam))
{
// type vs (none)
if (!at)
{
- (*dedtypes)[i] = tt;
+ dedtypes[i] = tt;
result = m;
return;
}
@@ -3706,11 +3717,11 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// type vs expressions
if (at.ty == Tnone)
{
- TypeDeduced xt = cast(TypeDeduced)at;
+ auto xt = cast(TypeDeduced)at;
result = xt.matchAll(tt);
if (result > MATCH.nomatch)
{
- (*dedtypes)[i] = tt;
+ dedtypes[i] = tt;
}
return;
}
@@ -3740,7 +3751,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
Loc loc;
if (parameters.length)
{
- TemplateParameter tp = (*parameters)[0];
+ TemplateParameter tp = parameters[0];
loc = tp.loc;
}
@@ -3757,9 +3768,8 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
MATCH m = t.implicitConvTo(tparam);
if (m == MATCH.nomatch && !ignoreAliasThis)
{
- if (t.ty == Tclass)
+ if (auto tc = t.isTypeClass())
{
- TypeClass tc = cast(TypeClass)t;
if (tc.sym.aliasthis && !(tc.att & AliasThisRec.tracingDT))
{
if (auto ato = t.aliasthisOf())
@@ -3770,9 +3780,8 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
}
}
}
- else if (t.ty == Tstruct)
+ else if (auto ts = t.isTypeStruct())
{
- TypeStruct ts = cast(TypeStruct)t;
if (ts.sym.aliasthis && !(ts.att & AliasThisRec.tracingDT))
{
if (auto ato = t.aliasthisOf())
@@ -3822,9 +3831,8 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
override void visit(TypeVector t)
{
- if (tparam.ty == Tvector)
+ if (auto tp = tparam.isTypeVector())
{
- TypeVector tp = cast(TypeVector)tparam;
result = deduceType(t.basetype, sc, tp.basetype, parameters, dedtypes, wm);
return;
}
@@ -3851,25 +3859,23 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
TemplateParameter tp = null;
Expression edim = null;
size_t i;
- if (tparam.ty == Tsarray)
+ if (auto tsa = tparam.isTypeSArray())
{
- TypeSArray tsa = cast(TypeSArray)tparam;
if (tsa.dim.isVarExp() && tsa.dim.isVarExp().var.storage_class & STC.templateparameter)
{
Identifier id = tsa.dim.isVarExp().var.ident;
- i = templateIdentifierLookup(id, parameters);
+ i = templateIdentifierLookup(id, &parameters);
assert(i != IDX_NOTFOUND);
- tp = (*parameters)[i];
+ tp = parameters[i];
}
else
edim = tsa.dim;
}
- else if (tparam.ty == Taarray)
+ else if (auto taa = tparam.isTypeAArray())
{
- TypeAArray taa = cast(TypeAArray)tparam;
- i = templateParameterLookup(taa.index, parameters);
+ i = templateParameterLookup(taa.index, &parameters);
if (i != IDX_NOTFOUND)
- tp = (*parameters)[i];
+ tp = parameters[i];
else
{
Loc loc;
@@ -3878,7 +3884,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// so we use that for the resolution (better error message).
if (inferStart < parameters.length)
{
- TemplateParameter loctp = (*parameters)[inferStart];
+ TemplateParameter loctp = parameters[inferStart];
loc = loctp.loc;
}
@@ -3889,7 +3895,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
edim = s ? getValue(s) : getValue(e);
}
}
- if (tp && tp.matchArg(sc, t.dim, i, parameters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
+ if (tp && tp.matchArg(sc, t.dim, i, &parameters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
{
result = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
return;
@@ -3903,7 +3909,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Extra check that index type must match
if (tparam && tparam.ty == Taarray)
{
- TypeAArray tp = cast(TypeAArray)tparam;
+ TypeAArray tp = tparam.isTypeAArray();
if (!deduceType(t.index, sc, tp.index, parameters, dedtypes))
{
result = MATCH.nomatch;
@@ -3936,7 +3942,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// https://issues.dlang.org/show_bug.cgi?id=15243
// Resolve parameter type if it's not related with template parameters
- if (!reliesOnTemplateParameters(fparam.type, (*parameters)[inferStart .. parameters.length]))
+ if (!reliesOnTemplateParameters(fparam.type, parameters[inferStart .. parameters.length]))
{
auto tx = fparam.type.typeSemantic(Loc.initial, sc);
if (tx.ty == Terror)
@@ -3948,7 +3954,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
}
}
- size_t nfargs = t.parameterList.length;
+ const size_t nfargs = t.parameterList.length;
size_t nfparams = tp.parameterList.length;
/* See if tuple match
@@ -3963,7 +3969,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
assert(fparam.type);
if (fparam.type.ty != Tident)
goto L1;
- TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
+ TypeIdentifier tid = fparam.type.isTypeIdentifier();
if (tid.idents.length)
goto L1;
@@ -3974,7 +3980,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
{
if (tupi == parameters.length)
goto L1;
- TemplateParameter tx = (*parameters)[tupi];
+ TemplateParameter tx = parameters[tupi];
TemplateTupleParameter tup = tx.isTemplateTupleParameter();
if (tup && tup.ident.equals(tid.ident))
break;
@@ -3987,7 +3993,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
/* See if existing tuple, and whether it matches or not
*/
- RootObject o = (*dedtypes)[tupi];
+ RootObject o = dedtypes[tupi];
if (o)
{
// Existing deduced argument must be a tuple, and must match
@@ -4016,7 +4022,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
Parameter arg = t.parameterList[nfparams - 1 + i];
tup.objects[i] = arg.type;
}
- (*dedtypes)[tupi] = tup;
+ dedtypes[tupi] = tup;
}
nfparams--; // don't consider the last parameter for type deduction
goto L2;
@@ -4053,7 +4059,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Extra check
if (tparam && tparam.ty == Tident)
{
- TypeIdentifier tp = cast(TypeIdentifier)tparam;
+ TypeIdentifier tp = tparam.isTypeIdentifier();
for (size_t i = 0; i < t.idents.length; i++)
{
RootObject id1 = t.idents[i];
@@ -4076,7 +4082,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
TemplateDeclaration tempdecl = t.tempinst.tempdecl.isTemplateDeclaration();
assert(tempdecl);
- TypeInstance tp = cast(TypeInstance)tparam;
+ TypeInstance tp = tparam.isTypeInstance();
//printf("tempinst.tempdecl = %p\n", tempdecl);
//printf("tp.tempinst.tempdecl = %p\n", tp.tempinst.tempdecl);
@@ -4087,7 +4093,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
/* Handle case of:
* template Foo(T : sa!(T), alias sa)
*/
- size_t i = templateIdentifierLookup(tp.tempinst.name, parameters);
+ size_t i = templateIdentifierLookup(tp.tempinst.name, &parameters);
if (i == IDX_NOTFOUND)
{
/* Didn't find it as a parameter identifier. Try looking
@@ -4132,15 +4138,15 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
goto Lnomatch;
}
- TemplateParameter tpx = (*parameters)[i];
- if (!tpx.matchArg(sc, tempdecl, i, parameters, dedtypes, null))
+ TemplateParameter tpx = parameters[i];
+ if (!tpx.matchArg(sc, tempdecl, i, &parameters, dedtypes, null))
goto Lnomatch;
}
else if (tempdecl != tp.tempinst.tempdecl)
goto Lnomatch;
L2:
- if (!resolveTemplateInstantiation(t.tempinst.tiargs, &t.tempinst.tdtypes, tempdecl, tp, dedtypes))
+ if (!resolveTemplateInstantiation(sc, &parameters, t.tempinst.tiargs, &t.tempinst.tdtypes, tempdecl, tp, &dedtypes))
goto Lnomatch;
}
visit(cast(Type)t);
@@ -4151,198 +4157,6 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
result = MATCH.nomatch;
}
- /********************
- * Match template `parameters` to the target template instance.
- * Example:
- * struct Temp(U, int Z) {}
- * void foo(T)(Temp!(T, 3));
- * foo(Temp!(int, 3)());
- * Input:
- * this.parameters = template params of foo -> [T]
- * tiargs = <Temp!(int, 3)>.tiargs -> [int, 3]
- * tdtypes = <Temp!(int, 3)>.tdtypes -> [int, 3]
- * tempdecl = <struct Temp!(T, int Z)> -> [T, Z]
- * tp = <Temp!(T, 3)>
- * Output:
- * dedtypes = deduced params of `foo(Temp!(int, 3)())` -> [int]
- */
- private bool resolveTemplateInstantiation(Objects* tiargs, Objects* tdtypes, TemplateDeclaration tempdecl, TypeInstance tp, Objects* dedtypes)
- {
- for (size_t i = 0; 1; i++)
- {
- //printf("\ttest: tempinst.tiargs[%zu]\n", i);
- RootObject o1 = null;
- if (i < tiargs.length)
- o1 = (*tiargs)[i];
- else if (i < tdtypes.length && i < tp.tempinst.tiargs.length)
- {
- // Pick up default arg
- o1 = (*tdtypes)[i];
- }
- else if (i >= tp.tempinst.tiargs.length)
- break;
- //printf("\ttest: o1 = %s\n", o1.toChars());
- if (i >= tp.tempinst.tiargs.length)
- {
- size_t dim = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
- while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
- {
- i++;
- }
- if (i >= dim)
- break; // match if all remained parameters are dependent
- return false;
- }
-
- RootObject o2 = (*tp.tempinst.tiargs)[i];
- Type t2 = isType(o2);
- //printf("\ttest: o2 = %s\n", o2.toChars());
- size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.length - 1)
- ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
- if (j != IDX_NOTFOUND && j == parameters.length - 1 &&
- (*parameters)[j].isTemplateTupleParameter())
- {
- /* Given:
- * struct A(B...) {}
- * alias A!(int, float) X;
- * static if (is(X Y == A!(Z), Z...)) {}
- * deduce that Z is a tuple(int, float)
- */
-
- /* Create tuple from remaining args
- */
- size_t vtdim = (tempdecl.isVariadic() ? tiargs.length : tdtypes.length) - i;
- auto vt = new Tuple(vtdim);
- for (size_t k = 0; k < vtdim; k++)
- {
- RootObject o;
- if (k < tiargs.length)
- o = (*tiargs)[i + k];
- else // Pick up default arg
- o = (*tdtypes)[i + k];
- vt.objects[k] = o;
- }
-
- Tuple v = cast(Tuple)(*dedtypes)[j];
- if (v)
- {
- if (!match(v, vt))
- return false;
- }
- else
- (*dedtypes)[j] = vt;
- break;
- }
- else if (!o1)
- break;
-
- Type t1 = isType(o1);
- Dsymbol s1 = isDsymbol(o1);
- Dsymbol s2 = isDsymbol(o2);
- Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
- Expression e2 = isExpression(o2);
- version (none)
- {
- Tuple v1 = isTuple(o1);
- Tuple v2 = isTuple(o2);
- if (t1)
- printf("t1 = %s\n", t1.toChars());
- if (t2)
- printf("t2 = %s\n", t2.toChars());
- if (e1)
- printf("e1 = %s\n", e1.toChars());
- if (e2)
- printf("e2 = %s\n", e2.toChars());
- if (s1)
- printf("s1 = %s\n", s1.toChars());
- if (s2)
- printf("s2 = %s\n", s2.toChars());
- if (v1)
- printf("v1 = %s\n", v1.toChars());
- if (v2)
- printf("v2 = %s\n", v2.toChars());
- }
-
- if (t1 && t2)
- {
- if (!deduceType(t1, sc, t2, parameters, dedtypes))
- return false;
- }
- else if (e1 && e2)
- {
- Le:
- e1 = e1.ctfeInterpret();
-
- /* If it is one of the template parameters for this template,
- * we should not attempt to interpret it. It already has a value.
- */
- if (e2.op == EXP.variable && (e2.isVarExp().var.storage_class & STC.templateparameter))
- {
- /*
- * (T:Number!(e2), int e2)
- */
- j = templateIdentifierLookup(e2.isVarExp().var.ident, parameters);
- if (j != IDX_NOTFOUND)
- goto L1;
- // The template parameter was not from this template
- // (it may be from a parent template, for example)
- }
-
- e2 = e2.expressionSemantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
- e2 = e2.ctfeInterpret();
-
- //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
- //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
- if (!e1.equals(e2))
- {
- if (!e2.implicitConvTo(e1.type))
- return false;
-
- e2 = e2.implicitCastTo(sc, e1.type);
- e2 = e2.ctfeInterpret();
- if (!e1.equals(e2))
- return false;
- }
- }
- else if (e1 && t2 && t2.ty == Tident)
- {
- j = templateParameterLookup(t2, parameters);
- L1:
- if (j == IDX_NOTFOUND)
- {
- t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
- if (e2)
- goto Le;
- return false;
- }
- if (!(*parameters)[j].matchArg(sc, e1, j, parameters, dedtypes, null))
- return false;
- }
- else if (s1 && s2)
- {
- Ls:
- if (!s1.equals(s2))
- return false;
- }
- else if (s1 && t2 && t2.ty == Tident)
- {
- j = templateParameterLookup(t2, parameters);
- if (j == IDX_NOTFOUND)
- {
- t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
- if (s2)
- goto Ls;
- return false;
- }
- if (!(*parameters)[j].matchArg(sc, s1, j, parameters, dedtypes, null))
- return false;
- }
- else
- return false;
- }
- return true;
- }
-
override void visit(TypeStruct t)
{
/* If this struct is a template struct, and we're matching
@@ -4368,7 +4182,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
/* Match things like:
* S!(T).foo
*/
- TypeInstance tpi = cast(TypeInstance)tparam;
+ TypeInstance tpi = tparam.isTypeInstance();
if (tpi.idents.length)
{
RootObject id = tpi.idents[tpi.idents.length - 1];
@@ -4391,7 +4205,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Extra check
if (tparam && tparam.ty == Tstruct)
{
- TypeStruct tp = cast(TypeStruct)tparam;
+ TypeStruct tp = tparam.isTypeStruct();
//printf("\t%d\n", cast(MATCH) t.implicitConvTo(tp));
if (wm && t.deduceWild(tparam, false))
@@ -4410,7 +4224,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Extra check
if (tparam && tparam.ty == Tenum)
{
- TypeEnum tp = cast(TypeEnum)tparam;
+ TypeEnum tp = tparam.isTypeEnum();
if (t.sym == tp.sym)
visit(cast(Type)t);
else
@@ -4428,59 +4242,6 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
visit(cast(Type)t);
}
- /* Helper for TypeClass.deduceType().
- * Classes can match with implicit conversion to a base class or interface.
- * This is complicated, because there may be more than one base class which
- * matches. In such cases, one or more parameters remain ambiguous.
- * For example,
- *
- * interface I(X, Y) {}
- * class C : I(uint, double), I(char, double) {}
- * C x;
- * foo(T, U)( I!(T, U) x)
- *
- * deduces that U is double, but T remains ambiguous (could be char or uint).
- *
- * Given a baseclass b, and initial deduced types 'dedtypes', this function
- * tries to match tparam with b, and also tries all base interfaces of b.
- * If a match occurs, numBaseClassMatches is incremented, and the new deduced
- * types are ANDed with the current 'best' estimate for dedtypes.
- */
- static void deduceBaseClassParameters(ref BaseClass b, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, Objects* best, ref int numBaseClassMatches)
- {
- TemplateInstance parti = b.sym ? b.sym.parent.isTemplateInstance() : null;
- if (parti)
- {
- // Make a temporary copy of dedtypes so we don't destroy it
- auto tmpdedtypes = new Objects(dedtypes.length);
- memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.length * (void*).sizeof);
-
- auto t = new TypeInstance(Loc.initial, parti);
- MATCH m = deduceType(t, sc, tparam, parameters, tmpdedtypes);
- if (m > MATCH.nomatch)
- {
- // If this is the first ever match, it becomes our best estimate
- if (numBaseClassMatches == 0)
- memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.length * (void*).sizeof);
- else
- for (size_t k = 0; k < tmpdedtypes.length; ++k)
- {
- // If we've found more than one possible type for a parameter,
- // mark it as unknown.
- if ((*tmpdedtypes)[k] != (*best)[k])
- (*best)[k] = (*dedtypes)[k];
- }
- ++numBaseClassMatches;
- }
- }
-
- // Now recursively test the inherited interfaces
- foreach (ref bi; b.baseInterfaces)
- {
- deduceBaseClassParameters(bi, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
- }
- }
-
override void visit(TypeClass t)
{
//printf("TypeClass.deduceType(this = %s)\n", t.toChars());
@@ -4509,7 +4270,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
/* Match things like:
* S!(T).foo
*/
- TypeInstance tpi = cast(TypeInstance)tparam;
+ TypeInstance tpi = tparam.isTypeInstance();
if (tpi.idents.length)
{
RootObject id = tpi.idents[tpi.idents.length - 1];
@@ -4547,12 +4308,12 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
while (s && s.baseclasses.length > 0)
{
// Test the base class
- deduceBaseClassParameters(*(*s.baseclasses)[0], sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
+ deduceBaseClassParameters(*(*s.baseclasses)[0], sc, tparam, parameters, dedtypes, *best, numBaseClassMatches);
// Test the interfaces inherited by the base class
foreach (b; s.interfaces)
{
- deduceBaseClassParameters(*b, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
+ deduceBaseClassParameters(*b, sc, tparam, parameters, dedtypes, *best, numBaseClassMatches);
}
s = (*s.baseclasses)[0].sym;
}
@@ -4572,7 +4333,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Extra check
if (tparam && tparam.ty == Tclass)
{
- TypeClass tp = cast(TypeClass)tparam;
+ TypeClass tp = tparam.isTypeClass();
//printf("\t%d\n", cast(MATCH) t.implicitConvTo(tp));
if (wm && t.deduceWild(tparam, false))
@@ -4589,8 +4350,8 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
override void visit(Expression e)
{
//printf("Expression.deduceType(e = %s)\n", e.toChars());
- size_t i = templateParameterLookup(tparam, parameters);
- if (i == IDX_NOTFOUND || (cast(TypeIdentifier)tparam).idents.length > 0)
+ size_t i = templateParameterLookup(tparam, &parameters);
+ if (i == IDX_NOTFOUND || tparam.isTypeIdentifier().idents.length > 0)
{
if (e == emptyArrayElement && tparam.ty == Tarray)
{
@@ -4602,13 +4363,13 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
return;
}
- TemplateTypeParameter tp = (*parameters)[i].isTemplateTypeParameter();
+ TemplateTypeParameter tp = parameters[i].isTemplateTypeParameter();
if (!tp)
return; // nomatch
if (e == emptyArrayElement)
{
- if ((*dedtypes)[i])
+ if (dedtypes[i])
{
result = MATCH.exact;
return;
@@ -4630,14 +4391,14 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
tb.ty == Tstruct && tb.hasPointers();
}
- Type at = cast(Type)(*dedtypes)[i];
+ Type at = cast(Type)dedtypes[i];
Type tt;
if (ubyte wx = deduceWildHelper(e.type, &tt, tparam))
{
*wm |= wx;
result = MATCH.constant;
}
- else if (MATCH m = deduceTypeHelper(e.type, &tt, tparam))
+ else if (MATCH m = deduceTypeHelper(e.type, tt, tparam))
{
result = m;
}
@@ -4658,7 +4419,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// expression vs (none)
if (!at)
{
- (*dedtypes)[i] = new TypeDeduced(tt, e, tparam);
+ dedtypes[i] = new TypeDeduced(tt, e, tparam);
return;
}
@@ -4716,7 +4477,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
if (xt)
xt.update(tt, e, tparam);
else
- (*dedtypes)[i] = tt;
+ dedtypes[i] = tt;
result = match1;
return;
}
@@ -4736,7 +4497,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
if (xt)
xt.update(t, e, tparam);
else
- (*dedtypes)[i] = t;
+ dedtypes[i] = t;
pt = tt.addMod(tparam.mod);
if (*wm)
@@ -4870,7 +4631,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Parameter types inference from 'tof'
assert(e.td._scope);
- TypeFunction tf = cast(TypeFunction)e.fd.type;
+ TypeFunction tf = e.fd.type.isTypeFunction();
//printf("\ttof = %s\n", tof.toChars());
//printf("\ttf = %s\n", tf.toChars());
const dim = tf.parameterList.length;
@@ -4895,7 +4656,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
if (!pto)
break;
Type t = pto.type.syntaxCopy(); // https://issues.dlang.org/show_bug.cgi?id=11774
- if (reliesOnTemplateParameters(t, (*parameters)[inferStart .. parameters.length]))
+ if (reliesOnTemplateParameters(t, parameters[inferStart .. parameters.length]))
return;
t = t.typeSemantic(e.loc, sc);
if (t.ty == Terror)
@@ -4929,7 +4690,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Allow conversion from implicit function pointer to delegate
if (e.tok == TOK.reserved && t.ty == Tpointer && tparam.ty == Tdelegate)
{
- TypeFunction tf = cast(TypeFunction)t.nextOf();
+ TypeFunction tf = t.nextOf().isTypeFunction();
t = (new TypeDelegate(tf)).merge();
}
//printf("tparam = %s <= e.type = %s, t = %s\n", tparam.toChars(), e.type.toChars(), t.toChars());
@@ -4959,7 +4720,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
}
}
- scope DeduceType v = new DeduceType(sc, tparam, parameters, dedtypes, wm, inferStart, ignoreAliasThis);
+ scope DeduceType v = new DeduceType();
if (Type t = isType(o))
t.accept(v);
else if (Expression e = isExpression(o))
@@ -4972,6 +4733,254 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
return v.result;
}
+
+/* Helper for TypeClass.deduceType().
+ * Classes can match with implicit conversion to a base class or interface.
+ * This is complicated, because there may be more than one base class which
+ * matches. In such cases, one or more parameters remain ambiguous.
+ * For example,
+ *
+ * interface I(X, Y) {}
+ * class C : I(uint, double), I(char, double) {}
+ * C x;
+ * foo(T, U)( I!(T, U) x)
+ *
+ * deduces that U is double, but T remains ambiguous (could be char or uint).
+ *
+ * Given a baseclass b, and initial deduced types 'dedtypes', this function
+ * tries to match tparam with b, and also tries all base interfaces of b.
+ * If a match occurs, numBaseClassMatches is incremented, and the new deduced
+ * types are ANDed with the current 'best' estimate for dedtypes.
+ */
+private void deduceBaseClassParameters(ref BaseClass b, Scope* sc, Type tparam, ref TemplateParameters parameters, ref Objects dedtypes, ref Objects best, ref int numBaseClassMatches)
+{
+ TemplateInstance parti = b.sym ? b.sym.parent.isTemplateInstance() : null;
+ if (parti)
+ {
+ // Make a temporary copy of dedtypes so we don't destroy it
+ auto tmpdedtypes = new Objects(dedtypes.length);
+ memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.length * (void*).sizeof);
+
+ auto t = new TypeInstance(Loc.initial, parti);
+ MATCH m = deduceType(t, sc, tparam, parameters, *tmpdedtypes);
+ if (m > MATCH.nomatch)
+ {
+ // If this is the first ever match, it becomes our best estimate
+ if (numBaseClassMatches == 0)
+ memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.length * (void*).sizeof);
+ else
+ for (size_t k = 0; k < tmpdedtypes.length; ++k)
+ {
+ // If we've found more than one possible type for a parameter,
+ // mark it as unknown.
+ if ((*tmpdedtypes)[k] != best[k])
+ best[k] = dedtypes[k];
+ }
+ ++numBaseClassMatches;
+ }
+ }
+
+ // Now recursively test the inherited interfaces
+ foreach (ref bi; b.baseInterfaces)
+ {
+ deduceBaseClassParameters(bi, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
+ }
+}
+
+/********************
+ * Match template `parameters` to the target template instance.
+ * Example:
+ * struct Temp(U, int Z) {}
+ * void foo(T)(Temp!(T, 3));
+ * foo(Temp!(int, 3)());
+ * Input:
+ * sc = context
+ * parameters = template params of foo -> [T]
+ * tiargs = <Temp!(int, 3)>.tiargs -> [int, 3]
+ * tdtypes = <Temp!(int, 3)>.tdtypes -> [int, 3]
+ * tempdecl = <struct Temp!(T, int Z)> -> [T, Z]
+ * tp = <Temp!(T, 3)>
+ * Output:
+ * dedtypes = deduced params of `foo(Temp!(int, 3)())` -> [int]
+ */
+private bool resolveTemplateInstantiation(Scope* sc, TemplateParameters* parameters, Objects* tiargs, Objects* tdtypes, TemplateDeclaration tempdecl, TypeInstance tp, Objects* dedtypes)
+{
+ for (size_t i = 0; 1; i++)
+ {
+ //printf("\ttest: tempinst.tiargs[%zu]\n", i);
+ RootObject o1 = null;
+ if (i < tiargs.length)
+ o1 = (*tiargs)[i];
+ else if (i < tdtypes.length && i < tp.tempinst.tiargs.length)
+ {
+ // Pick up default arg
+ o1 = (*tdtypes)[i];
+ }
+ else if (i >= tp.tempinst.tiargs.length)
+ break;
+ //printf("\ttest: o1 = %s\n", o1.toChars());
+ if (i >= tp.tempinst.tiargs.length)
+ {
+ size_t dim = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
+ while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
+ {
+ i++;
+ }
+ if (i >= dim)
+ break; // match if all remained parameters are dependent
+ return false;
+ }
+
+ RootObject o2 = (*tp.tempinst.tiargs)[i];
+ Type t2 = isType(o2);
+ //printf("\ttest: o2 = %s\n", o2.toChars());
+ size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.length - 1)
+ ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
+ if (j != IDX_NOTFOUND && j == parameters.length - 1 &&
+ (*parameters)[j].isTemplateTupleParameter())
+ {
+ /* Given:
+ * struct A(B...) {}
+ * alias A!(int, float) X;
+ * static if (is(X Y == A!(Z), Z...)) {}
+ * deduce that Z is a tuple(int, float)
+ */
+
+ /* Create tuple from remaining args
+ */
+ size_t vtdim = (tempdecl.isVariadic() ? tiargs.length : tdtypes.length) - i;
+ auto vt = new Tuple(vtdim);
+ for (size_t k = 0; k < vtdim; k++)
+ {
+ RootObject o;
+ if (k < tiargs.length)
+ o = (*tiargs)[i + k];
+ else // Pick up default arg
+ o = (*tdtypes)[i + k];
+ vt.objects[k] = o;
+ }
+
+ Tuple v = cast(Tuple)(*dedtypes)[j];
+ if (v)
+ {
+ if (!match(v, vt))
+ return false;
+ }
+ else
+ (*dedtypes)[j] = vt;
+ break;
+ }
+ else if (!o1)
+ break;
+
+ Type t1 = isType(o1);
+ Dsymbol s1 = isDsymbol(o1);
+ Dsymbol s2 = isDsymbol(o2);
+ Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
+ Expression e2 = isExpression(o2);
+ version (none)
+ {
+ Tuple v1 = isTuple(o1);
+ Tuple v2 = isTuple(o2);
+ if (t1)
+ printf("t1 = %s\n", t1.toChars());
+ if (t2)
+ printf("t2 = %s\n", t2.toChars());
+ if (e1)
+ printf("e1 = %s\n", e1.toChars());
+ if (e2)
+ printf("e2 = %s\n", e2.toChars());
+ if (s1)
+ printf("s1 = %s\n", s1.toChars());
+ if (s2)
+ printf("s2 = %s\n", s2.toChars());
+ if (v1)
+ printf("v1 = %s\n", v1.toChars());
+ if (v2)
+ printf("v2 = %s\n", v2.toChars());
+ }
+
+ if (t1 && t2)
+ {
+ if (!deduceType(t1, sc, t2, *parameters, *dedtypes))
+ return false;
+ }
+ else if (e1 && e2)
+ {
+ Le:
+ e1 = e1.ctfeInterpret();
+
+ /* If it is one of the template parameters for this template,
+ * we should not attempt to interpret it. It already has a value.
+ */
+ if (e2.op == EXP.variable && (e2.isVarExp().var.storage_class & STC.templateparameter))
+ {
+ /*
+ * (T:Number!(e2), int e2)
+ */
+ j = templateIdentifierLookup(e2.isVarExp().var.ident, parameters);
+ if (j != IDX_NOTFOUND)
+ goto L1;
+ // The template parameter was not from this template
+ // (it may be from a parent template, for example)
+ }
+
+ e2 = e2.expressionSemantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
+ e2 = e2.ctfeInterpret();
+
+ //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
+ //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
+ if (!e1.equals(e2))
+ {
+ if (!e2.implicitConvTo(e1.type))
+ return false;
+
+ e2 = e2.implicitCastTo(sc, e1.type);
+ e2 = e2.ctfeInterpret();
+ if (!e1.equals(e2))
+ return false;
+ }
+ }
+ else if (e1 && t2 && t2.ty == Tident)
+ {
+ j = templateParameterLookup(t2, parameters);
+ L1:
+ if (j == IDX_NOTFOUND)
+ {
+ t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
+ if (e2)
+ goto Le;
+ return false;
+ }
+ if (!(*parameters)[j].matchArg(sc, e1, j, parameters, *dedtypes, null))
+ return false;
+ }
+ else if (s1 && s2)
+ {
+ Ls:
+ if (!s1.equals(s2))
+ return false;
+ }
+ else if (s1 && t2 && t2.ty == Tident)
+ {
+ j = templateParameterLookup(t2, parameters);
+ if (j == IDX_NOTFOUND)
+ {
+ t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
+ if (s2)
+ goto Ls;
+ return false;
+ }
+ if (!(*parameters)[j].matchArg(sc, s1, j, parameters, *dedtypes, null))
+ return false;
+ }
+ else
+ return false;
+ }
+ return true;
+}
+
+
/***********************************************************
* Check whether the type t representation relies on one or more the template parameters.
* Params:
@@ -5625,7 +5634,11 @@ extern (C++) final class TemplateValueParameter : TemplateParameter
if (e)
{
e = e.syntaxCopy();
- if ((e = e.expressionSemantic(sc)) is null)
+ Scope* sc2 = sc.push();
+ sc2.inDefaultArg = true;
+ e = e.expressionSemantic(sc2);
+ sc2.pop();
+ if (e is null)
return null;
if (auto te = e.isTemplateExp())
{
@@ -6176,7 +6189,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
}
//printf("parent = %s, ti.parent = %s\n", parent.toPrettyChars(), ti.parent.toPrettyChars());
- if (!arrayObjectMatch(&tdtypes, &ti.tdtypes))
+ if (!arrayObjectMatch(tdtypes, ti.tdtypes))
goto Lnotequals;
/* Template functions may have different instantiations based on
@@ -6221,7 +6234,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
if (!hash)
{
hash = cast(size_t)cast(void*)enclosing;
- hash += arrayObjectHash(&tdtypes);
+ hash += arrayObjectHash(tdtypes);
hash += hash == 0;
}
return hash;
@@ -6691,6 +6704,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol
if (!tiargs)
return true;
bool err = false;
+
+ // The arguments are not treated as part of a default argument,
+ // because they are evaluated at compile time.
+ sc = sc.push();
+ sc.inDefaultArg = false;
+
for (size_t j = 0; j < tiargs.length; j++)
{
RootObject o = (*tiargs)[j];
@@ -6716,10 +6735,9 @@ extern (C++) class TemplateInstance : ScopeDsymbol
}
Ltype:
- if (ta.ty == Ttuple)
+ if (TypeTuple tt = ta.isTypeTuple())
{
// Expand tuple
- TypeTuple tt = cast(TypeTuple)ta;
size_t dim = tt.arguments.length;
tiargs.remove(j);
if (dim)
@@ -6923,6 +6941,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
}
//printf("1: (*tiargs)[%d] = %p\n", j, (*tiargs)[j]);
}
+ sc.pop();
version (none)
{
printf("-TemplateInstance.semanticTiargs()\n");
@@ -6982,7 +7001,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
assert(tempdecl._scope);
// Deduce tdtypes
tdtypes.setDim(tempdecl.parameters.length);
- if (!tempdecl.matchWithInstance(sc, this, &tdtypes, argumentList, 2))
+ if (!tempdecl.matchWithInstance(sc, this, tdtypes, argumentList, 2))
{
.error(loc, "%s `%s` incompatible arguments for template instantiation", kind, toPrettyChars);
return false;
@@ -7032,7 +7051,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
dedtypes.zero();
assert(td.semanticRun != PASS.initial);
- MATCH m = td.matchWithInstance(sc, this, &dedtypes, argumentList, 0);
+ MATCH m = td.matchWithInstance(sc, this, dedtypes, argumentList, 0);
//printf("matchWithInstance = %d\n", m);
if (m == MATCH.nomatch) // no match at all
return 0;
@@ -7158,7 +7177,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
// print additional information, e.g. `foo` is not a type
foreach (i, param; *tdecl.parameters)
{
- MATCH match = param.matchArg(loc, sc, tiargs, i, tdecl.parameters, &dedtypes, null);
+ MATCH match = param.matchArg(loc, sc, tiargs, i, tdecl.parameters, dedtypes, null);
auto arg = (*tiargs)[i];
auto sym = arg.isDsymbol;
auto exp = arg.isExpression;
@@ -7262,7 +7281,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
* to instantiate the template.
*/
//printf("tp = %p, td.parameters.length = %d, tiargs.length = %d\n", tp, td.parameters.length, tiargs.length);
- auto tf = cast(TypeFunction)fd.type;
+ auto tf = fd.type.isTypeFunction();
if (tf.parameterList.length)
{
auto tp = td.isVariadic();
@@ -7308,7 +7327,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
return 1;
}
}
- MATCH m = td.matchWithInstance(sc, this, &dedtypes, ArgumentList(), 0);
+ MATCH m = td.matchWithInstance(sc, this, dedtypes, ArgumentList(), 0);
if (m == MATCH.nomatch)
return 0;
}
@@ -7992,7 +8011,7 @@ struct TemplateInstanceBox
* dedtypes[] deduced arguments to template instance
* *psparam set to symbol declared and initialized to dedtypes[i]
*/
-MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
+MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, ref Objects dedtypes, Declaration* psparam)
{
MATCH matchArgNoMatch()
{
@@ -8015,7 +8034,7 @@ MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, si
{
assert(i < dedtypes.length);
// It might have already been deduced
- oarg = (*dedtypes)[i];
+ oarg = dedtypes[i];
if (!oarg)
return matchArgNoMatch();
}
@@ -8031,7 +8050,7 @@ MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, si
assert(i + 1 == dedtypes.length); // must be the last one
Tuple ovar;
- if (Tuple u = isTuple((*dedtypes)[i]))
+ if (Tuple u = isTuple(dedtypes[i]))
{
// It has already been deduced
ovar = u;
@@ -8059,7 +8078,7 @@ MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, si
return matchArgParameter();
}
-MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
+MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, ref Objects dedtypes, Declaration* psparam)
{
MATCH matchArgNoMatch()
{
@@ -8087,7 +8106,7 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
return matchArgNoMatch();
//printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta.toChars(), ttp.specType.toChars());
- MATCH m2 = deduceType(ta, sc, ttp.specType, parameters, dedtypes);
+ MATCH m2 = deduceType(ta, sc, ttp.specType, *parameters, dedtypes);
if (m2 == MATCH.nomatch)
{
//printf("\tfailed deduceType\n");
@@ -8096,9 +8115,9 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
if (m2 < m)
m = m2;
- if ((*dedtypes)[i])
+ if (dedtypes[i])
{
- Type t = cast(Type)(*dedtypes)[i];
+ Type t = cast(Type)dedtypes[i];
if (ttp.dependent && !t.equals(ta)) // https://issues.dlang.org/show_bug.cgi?id=14357
return matchArgNoMatch();
@@ -8113,10 +8132,10 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
}
else
{
- if ((*dedtypes)[i])
+ if (dedtypes[i])
{
// Must match already deduced type
- Type t = cast(Type)(*dedtypes)[i];
+ Type t = cast(Type)dedtypes[i];
if (!t.equals(ta))
{
@@ -8130,7 +8149,7 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
m = MATCH.convert;
}
}
- (*dedtypes)[i] = ta;
+ dedtypes[i] = ta;
if (psparam)
*psparam = new AliasDeclaration(ttp.loc, ttp.ident, ta);
@@ -8235,15 +8254,15 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
}
else
{
- if ((*dedtypes)[i])
+ if (dedtypes[i])
{
// Must match already deduced value
- Expression e = cast(Expression)(*dedtypes)[i];
+ Expression e = cast(Expression)dedtypes[i];
if (!ei || !ei.equals(e))
return matchArgNoMatch();
}
}
- (*dedtypes)[i] = ei;
+ dedtypes[i] = ei;
if (psparam)
{
@@ -8354,7 +8373,7 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
return matchArgNoMatch();
Type t = new TypeInstance(Loc.initial, ti);
- MATCH m2 = deduceType(t, sc, talias, parameters, dedtypes);
+ MATCH m2 = deduceType(t, sc, talias, *parameters, dedtypes);
if (m2 == MATCH.nomatch)
return matchArgNoMatch();
}
@@ -8375,14 +8394,14 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
}
}
}
- else if ((*dedtypes)[i])
+ else if (dedtypes[i])
{
// Must match already deduced symbol
- RootObject si = (*dedtypes)[i];
+ RootObject si = dedtypes[i];
if (!sa || si != sa)
return matchArgNoMatch();
}
- (*dedtypes)[i] = sa;
+ dedtypes[i] = sa;
if (psparam)
{
@@ -8415,15 +8434,15 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
Tuple ovar = isTuple(oarg);
if (!ovar)
return MATCH.nomatch;
- if ((*dedtypes)[i])
+ if (dedtypes[i])
{
- Tuple tup = isTuple((*dedtypes)[i]);
+ Tuple tup = isTuple(dedtypes[i]);
if (!tup)
return MATCH.nomatch;
if (!match(tup, ovar))
return MATCH.nomatch;
}
- (*dedtypes)[i] = ovar;
+ dedtypes[i] = ovar;
if (psparam)
*psparam = new TupleDeclaration(ttp.loc, ttp.ident, &ovar.objects);
@@ -8457,21 +8476,24 @@ struct TemplateStats
/*******************************
* Add this instance
+ * Params:
+ * td = template declaration
+ * ti = instance of td
+ * listInstances = keep track of instances of templates
*/
static void incInstance(const TemplateDeclaration td,
- const TemplateInstance ti)
+ const TemplateInstance ti,
+ bool listInstances)
{
void log(ref TemplateStats ts)
{
if (ts.allInstances is null)
ts.allInstances = new TemplateInstances();
- if (global.params.v.templatesListInstances)
+ if (listInstances)
ts.allInstances.push(cast() ti);
}
- // message(ti.loc, "incInstance %p %p", td, ti);
- if (!global.params.v.templates)
- return;
+ // message(ti.loc, "incInstance %p %p", td, ti);
if (!td)
return;
assert(ti);
@@ -8494,8 +8516,6 @@ struct TemplateStats
const TemplateInstance ti)
{
// message(ti.loc, "incUnique %p %p", td, ti);
- if (!global.params.v.templates)
- return;
if (!td)
return;
assert(ti);
@@ -8506,7 +8526,13 @@ struct TemplateStats
}
}
-extern (C++) void printTemplateStats()
+/********************************
+ * Print informational statistics on template instantiations.
+ * Params:
+ * listInstances = list instances of templates
+ * eSink = where the print is sent
+ */
+extern (C++) void printTemplateStats(bool listInstances, ErrorSink eSink)
{
static struct TemplateDeclarationStats
{
@@ -8523,11 +8549,12 @@ extern (C++) void printTemplateStats()
}
}
- if (!global.params.v.templates)
- return;
+ const stats_length = TemplateStats.stats.length;
+ if (!stats_length)
+ return; // nothing to report
Array!(TemplateDeclarationStats) sortedStats;
- sortedStats.reserve(TemplateStats.stats.length);
+ sortedStats.reserve(stats_length);
foreach (td_, ref ts; TemplateStats.stats)
{
sortedStats.push(TemplateDeclarationStats(cast(TemplateDeclaration) td_, ts));
@@ -8537,10 +8564,9 @@ extern (C++) void printTemplateStats()
foreach (const ref ss; sortedStats[])
{
- if (global.params.v.templatesListInstances &&
- ss.ts.allInstances)
+ if (listInstances && ss.ts.allInstances)
{
- message(ss.td.loc,
+ eSink.message(ss.td.loc,
"vtemplate: %u (%u distinct) instantiation(s) of template `%s` found, they are:",
ss.ts.numInstantiations,
ss.ts.uniqueInstantiations,
@@ -8548,14 +8574,14 @@ extern (C++) void printTemplateStats()
foreach (const ti; (*ss.ts.allInstances)[])
{
if (ti.tinst) // if has enclosing instance
- message(ti.loc, "vtemplate: implicit instance `%s`", ti.toChars());
+ eSink.message(ti.loc, "vtemplate: implicit instance `%s`", ti.toChars());
else
- message(ti.loc, "vtemplate: explicit instance `%s`", ti.toChars());
+ eSink.message(ti.loc, "vtemplate: explicit instance `%s`", ti.toChars());
}
}
else
{
- message(ss.td.loc,
+ eSink.message(ss.td.loc,
"vtemplate: %u (%u distinct) instantiation(s) of template `%s` found",
ss.ts.numInstantiations,
ss.ts.uniqueInstantiations,
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 30991c9..2bfa96c 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -779,6 +779,17 @@ public:
}
}
+ if (tf && tf.next)
+ {
+ // Ensure return type is declared before a function that returns that is declared.
+ if (auto sty = tf.next.isTypeStruct())
+ ensureDeclared(sty.sym);
+ //else if (auto cty = tf.next.isTypeClass())
+ // includeSymbol(cty.sym); // classes are returned by pointer only need to forward declare
+ //else if (auto ety = tf.next.isTypeEnum())
+ // ensureDeclared(ety.sym);
+ }
+
writeProtection(fd.visibility.kind);
if (tf && tf.linkage == LINK.c)
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 433907a..3e17ff4 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -34,6 +34,7 @@ import dmd.mtype;
import dmd.printast;
import dmd.rootobject;
import dmd.tokens;
+import dmd.typesem : hasPointers, parameterStorageClass;
import dmd.visitor;
import dmd.arraytypes;
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 41eeff9..cbf0118 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -190,39 +190,6 @@ extern (C++) void expandTuples(Expressions* exps, Identifiers* names = null)
}
/****************************************
- * Expand alias this tuples.
- */
-TupleDeclaration isAliasThisTuple(Expression e)
-{
- if (!e.type)
- return null;
-
- Type t = e.type.toBasetype();
- while (true)
- {
- if (Dsymbol s = t.toDsymbol(null))
- {
- if (auto ad = s.isAggregateDeclaration())
- {
- s = ad.aliasthis ? ad.aliasthis.sym : null;
- if (s && s.isVarDeclaration())
- {
- TupleDeclaration td = s.isVarDeclaration().toAlias().isTupleDeclaration();
- if (td && td.isexp)
- return td;
- }
- if (Type att = t.aliasthisOf())
- {
- t = att;
- continue;
- }
- }
- }
- return null;
- }
-}
-
-/****************************************
* If `s` is a function template, i.e. the only member of a template
* and that member is a function, return that template.
* Params:
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 9ce6f4d..d464574 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -384,7 +384,6 @@ private Expression reorderSettingAAElem(BinExp exp, Scope* sc)
return Expression.combine(e0, be);
}
-
private Expression checkOpAssignTypes(BinExp binExp, Scope* sc)
{
auto e1 = binExp.e1;
@@ -563,6 +562,39 @@ private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
return e0;
}
+/****************************************
+ * Expand alias this tuples.
+ */
+TupleDeclaration isAliasThisTuple(Expression e)
+{
+ if (!e.type)
+ return null;
+
+ Type t = e.type.toBasetype();
+ while (true)
+ {
+ if (Dsymbol s = t.toDsymbol(null))
+ {
+ if (auto ad = s.isAggregateDeclaration())
+ {
+ s = ad.aliasthis ? ad.aliasthis.sym : null;
+ if (s && s.isVarDeclaration())
+ {
+ TupleDeclaration td = s.isVarDeclaration().toAlias().isTupleDeclaration();
+ if (td && td.isexp)
+ return td;
+ }
+ if (Type att = t.aliasthisOf())
+ {
+ t = att;
+ continue;
+ }
+ }
+ }
+ return null;
+ }
+}
+
/**************************************
* Runs semantic on ae.arguments. Declares temporary variables
* if '$' was used.
@@ -5115,7 +5147,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
tb = tb.isTypeDArray().next.toBasetype();
}
- if (global.params.betterC || !sc.needsCodegen())
+ if (!global.params.useGC && sc.needsCodegen())
+ {
+ version(IN_GCC)
+ error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-fno-rtti`", exp.toChars());
+ else
+ error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-betterC`", exp.toChars());
+ return setError();
+ }
+
+ if (!sc.needsCodegen())
goto LskipNewArrayLowering;
/* Class types may inherit base classes that have errors.
@@ -6432,8 +6473,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- const(char)* failMessage;
- if (!tf.callMatch(null, exp.argumentList, 0, &failMessage, sc))
+ void errorHelper(const(char)* failMessage) scope
{
OutBuffer buf;
buf.writeByte('(');
@@ -6447,8 +6487,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
if (failMessage)
errorSupplemental(exp.loc, "%s", failMessage);
- return setError();
}
+
+ if (tf.callMatch(null, exp.argumentList, 0, &errorHelper, sc) == MATCH.nomatch)
+ return setError();
+
// Purity and safety check should run after testing arguments matching
if (exp.f)
{
@@ -6505,8 +6548,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
exp.f = exp.f.toAliasFunc();
TypeFunction tf = cast(TypeFunction)exp.f.type;
- const(char)* failMessage;
- if (!tf.callMatch(null, exp.argumentList, 0, &failMessage, sc))
+
+ void errorHelper2(const(char)* failMessage) scope
{
OutBuffer buf;
buf.writeByte('(');
@@ -6527,6 +6570,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
errorSupplemental(exp.loc, "%s", failMessage);
exp.f = null;
}
+
+ if (tf.callMatch(null, exp.argumentList, 0, &errorHelper2, sc) == MATCH.nomatch)
+ exp.f = null;
}
if (!exp.f || exp.f.errors)
return setError();
@@ -7041,7 +7087,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sc2.tinst = null;
sc2.minst = null;
sc2.flags |= SCOPE.fullinst;
- Type t = e.targ.trySemantic(e.loc, sc2);
+ Type t = dmd.typesem.trySemantic(e.targ, e.loc, sc2);
sc2.pop();
if (!t) // errors, so condition is false
return no();
@@ -7271,7 +7317,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Objects dedtypes = Objects(e.parameters.length);
dedtypes.zero();
- MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
+ MATCH m = deduceType(e.targ, sc, e.tspec, *e.parameters, dedtypes, null, 0, e.tok == TOK.equal);
if (m == MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
{
@@ -7292,7 +7338,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
TemplateParameter tp = (*e.parameters)[i];
Declaration s = null;
- m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
+ m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, dedtypes, &s);
if (m == MATCH.nomatch)
return no();
s.dsymbolSemantic(sc);
@@ -7437,7 +7483,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = (cast(BinExp)e).reorderSettingAAElem(sc);
}
- private Expression compileIt(MixinExp exp)
+ private Expression compileIt(MixinExp exp, Scope *sc)
{
OutBuffer buf;
if (expressionsToString(buf, sc, exp.exps))
@@ -7478,7 +7524,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
printf("MixinExp::semantic('%s')\n", exp.toChars());
}
- auto e = compileIt(exp);
+ // The expression is not treated as part of a default argument,
+ // because it is evaluated at compile time.
+ Scope* sc2 = sc.push();
+ sc2.inDefaultArg = false;
+
+ auto e = compileIt(exp, sc2);
+ sc2.pop();
if (!e)
return setError();
result = e.expressionSemantic(sc);
@@ -7575,7 +7627,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
auto fileName = FileName(resolvedNamez);
- if (auto fmResult = global.fileManager.lookup(fileName))
+ if (auto fmResult = global.fileManager.getFileContents(fileName))
{
se = new StringExp(e.loc, fmResult);
}
@@ -7721,7 +7773,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// if the assert condition is a mixin expression, try to compile it
if (auto ce = exp.e1.isMixinExp())
{
- if (auto e1 = compileIt(ce))
+ if (auto e1 = compileIt(ce, sc))
exp.e1 = e1;
}
@@ -13924,45 +13976,34 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
//printf("FileInitExp::semantic()\n");
e.type = Type.tstring;
- result = e;
+ result = e.resolveLoc(e.loc, sc);
}
override void visit(LineInitExp e)
{
e.type = Type.tint32;
- result = e;
+ result = e.resolveLoc(e.loc, sc);
}
override void visit(ModuleInitExp e)
{
//printf("ModuleInitExp::semantic()\n");
e.type = Type.tstring;
- result = e;
+ result = e.resolveLoc(e.loc, sc);
}
override void visit(FuncInitExp e)
{
//printf("FuncInitExp::semantic()\n");
e.type = Type.tstring;
- if (sc.func)
- {
- result = e.resolveLoc(Loc.initial, sc);
- return;
- }
- result = e;
+ result = e.resolveLoc(e.loc, sc);
}
override void visit(PrettyFuncInitExp e)
{
//printf("PrettyFuncInitExp::semantic()\n");
e.type = Type.tstring;
- if (sc.func)
- {
- result = e.resolveLoc(Loc.initial, sc);
- return;
- }
-
- result = e;
+ result = e.resolveLoc(e.loc, sc);
}
}
@@ -15047,10 +15088,21 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
*/
Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
{
+ // Don't replace the special keywords, while we are inside a default
+ // argument. They are replaced later when copied to the call site.
+ if (sc.inDefaultArg)
+ return exp;
+
exp.loc = loc;
Expression visit(Expression exp)
{
+ if (auto binExp = exp.isBinExp())
+ {
+ binExp.e1 = binExp.e1.resolveLoc(loc, sc);
+ binExp.e2 = binExp.e2.resolveLoc(loc, sc);
+ return binExp;
+ }
if (auto unaExp = exp.isUnaExp())
{
unaExp.e1 = unaExp.e1.resolveLoc(loc, sc);
@@ -15059,10 +15111,121 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
return exp;
}
+ Expression visitCond(CondExp exp)
+ {
+ exp.e1 = exp.e1.resolveLoc(loc, sc);
+ exp.e2 = exp.e2.resolveLoc(loc, sc);
+ exp.econd = exp.econd.resolveLoc(loc, sc);
+ return exp;
+ }
+
Expression visitCat(CatExp exp)
{
exp.e1 = exp.e1.resolveLoc(loc, sc);
exp.e2 = exp.e2.resolveLoc(loc, sc);
+ if (exp.lowering)
+ exp.lowering = exp.lowering.resolveLoc(loc, sc);
+ return exp;
+ }
+
+ Expression visitStructLiteral(StructLiteralExp exp)
+ {
+ foreach (ref element; *exp.elements)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
+ return exp;
+ }
+
+ Expression visitNew(NewExp exp)
+ {
+ if (exp.thisexp)
+ exp.thisexp = exp.thisexp.resolveLoc(loc, sc);
+ if (exp.argprefix)
+ exp.argprefix = exp.argprefix.resolveLoc(loc, sc);
+ if (exp.lowering)
+ exp.lowering = exp.lowering.resolveLoc(loc, sc);
+
+ foreach (ref element; *exp.arguments)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
+ return exp;
+ }
+
+ Expression visitCall(CallExp exp)
+ {
+ foreach (ref element; *exp.arguments)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
+ return exp;
+ }
+
+ Expression visitArray(ArrayExp exp)
+ {
+ exp.e1 = exp.e1.resolveLoc(loc, sc);
+
+ foreach (ref element; *exp.arguments)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
+ return exp;
+ }
+
+ Expression visitSlice(SliceExp exp)
+ {
+ exp.e1 = exp.e1.resolveLoc(loc, sc);
+ exp.lwr = exp.lwr.resolveLoc(loc, sc);
+ exp.upr = exp.upr.resolveLoc(loc, sc);
+
+ return exp;
+ }
+
+ Expression visitInterval(IntervalExp exp)
+ {
+ exp.lwr = exp.lwr.resolveLoc(loc, sc);
+ exp.upr = exp.upr.resolveLoc(loc, sc);
+
+ return exp;
+ }
+
+ Expression visitArrayLiteral(ArrayLiteralExp exp)
+ {
+ if (exp.basis)
+ exp.basis = exp.basis.resolveLoc(loc, sc);
+
+ foreach (ref element; *exp.elements)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
+ return exp;
+ }
+
+ Expression visitAssocArrayLiteral(AssocArrayLiteralExp exp)
+ {
+ foreach (ref element; *exp.keys)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
+ foreach (ref element; *exp.values)
+ {
+ if (element)
+ element = element.resolveLoc(loc, sc);
+ }
+
return exp;
}
@@ -15079,20 +15242,20 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
return e.expressionSemantic(sc);
}
- Expression visitLineInit(LineInitExp _)
+ Expression visitLineInit(LineInitExp exp)
{
Expression e = new IntegerExp(loc, loc.linnum, Type.tint32);
return e.expressionSemantic(sc);
}
- Expression visitModuleInit(ModuleInitExp _)
+ Expression visitModuleInit(ModuleInitExp exp)
{
const auto s = (sc.callsc ? sc.callsc : sc)._module.toPrettyChars().toDString();
Expression e = new StringExp(loc, s);
return e.expressionSemantic(sc);
}
- Expression visitFuncInit(FuncInitExp _)
+ Expression visitFuncInit(FuncInitExp exp)
{
const(char)* s;
if (sc.callsc && sc.callsc.func)
@@ -15105,7 +15268,7 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
return e.expressionSemantic(sc);
}
- Expression visitPrettyFunc(PrettyFuncInitExp _)
+ Expression visitPrettyFunc(PrettyFuncInitExp exp)
{
FuncDeclaration fd = (sc.callsc && sc.callsc.func)
? sc.callsc.func
@@ -15133,7 +15296,16 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
switch(exp.op)
{
default: return visit(exp);
+ case EXP.structLiteral: return visitStructLiteral(exp.isStructLiteralExp());
+ case EXP.new_: return visitNew(exp.isNewExp());
case EXP.concatenate: return visitCat(exp.isCatExp());
+ case EXP.call: return visitCall(exp.isCallExp());
+ case EXP.question: return visitCond(exp.isCondExp());
+ case EXP.array: return visitArray(exp.isArrayExp());
+ case EXP.slice: return visitSlice(exp.isSliceExp());
+ case EXP.interval: return visitInterval(exp.isIntervalExp());
+ case EXP.arrayLiteral: return visitArrayLiteral(exp.isArrayLiteralExp());
+ case EXP.assocArrayLiteral: return visitAssocArrayLiteral(exp.isAssocArrayLiteralExp());
case EXP.file:
case EXP.fileFullPath: return visitFileInit(exp.isFileInitExp());
case EXP.line: return visitLineInit(exp.isLineInitExp);
@@ -16193,7 +16365,10 @@ Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
em.checkDisabled(loc, sc);
if (em.depdecl && !em.depdecl._scope)
+ {
em.depdecl._scope = sc;
+ em.depdecl._scope.setNoFree();
+ }
em.checkDeprecated(loc, sc);
if (em.errors)
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index eaef8d5..c696a5c 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -72,7 +72,7 @@ private struct PathStack
final class FileManager
{
- private StringTable!(const(ubyte)[]) files;
+ private StringTable!(const(ubyte)[]) files; // contents of files indexed by file name
private StringTable!(bool) packageStatus;
// check if the package path of the given path exists. The input path is
@@ -247,35 +247,37 @@ nothrow:
}
/**
- * Looks up the given filename from the internal file buffer table.
- * If the file does not already exist within the table, it will be read from the filesystem.
- * If it has been read before,
- *
- * Returns: the loaded source file if it was found in memory,
- * otherwise `null`
+ * Retrieve the cached contents of the file given by `filename`.
+ * If the file has not been read before, read it and add the contents
+ * to the file cache.
+ * Params:
+ * filename = the name of the file
+ * Returns:
+ * the contents of the file, or `null` if it could not be read or was empty
*/
- const(ubyte)[] lookup(FileName filename)
+ const(ubyte)[] getFileContents(FileName filename)
{
const name = filename.toString;
- if (auto val = files.lookup(name))
- return val.value;
+ if (auto val = files.lookup(name)) // if `name` is cached
+ return val.value; // return its contents
- if (name == "__stdin.d")
+ if (name == "__stdin.d") // special name for reading from stdin
{
- auto buffer = readFromStdin().extractSlice();
+ const ubyte[] buffer = readFromStdin().extractSlice();
if (this.files.insert(name, buffer) is null)
+ // this.files already contains the name
assert(0, "stdin: Insert after lookup failure should never return `null`");
return buffer;
}
- if (FileName.exists(name) != 1)
+ if (FileName.exists(name) != 1) // if not an ordinary file
return null;
auto readResult = File.read(name);
if (!readResult.success)
return null;
- auto fb = readResult.extractSlice();
+ const ubyte[] fb = readResult.extractSlice();
if (files.insert(name, fb) is null)
assert(0, "Insert after lookup failure should never return `null`");
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 242b4dc..370da6f 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -1195,7 +1195,7 @@ extern (C++) class FuncDeclaration : Declaration
*
* Returns: the `LabelDsymbol` for `ident`
*/
- final LabelDsymbol searchLabel(Identifier ident, const ref Loc loc = Loc.initial)
+ final LabelDsymbol searchLabel(Identifier ident, const ref Loc loc)
{
Dsymbol s;
if (!labtab)
@@ -1471,6 +1471,9 @@ extern (C++) class FuncDeclaration : Declaration
final PURE isPure()
{
//printf("FuncDeclaration::isPure() '%s'\n", toChars());
+
+ import dmd.typesem : purityLevel;
+
TypeFunction tf = type.toTypeFunction();
if (purityInprocess)
setImpure();
@@ -1782,6 +1785,7 @@ extern (C++) class FuncDeclaration : Declaration
case Tstruct:
/* Drill down and check the struct's fields
*/
+ import dmd.typesem : toDsymbol;
auto sym = t.toDsymbol(null).isStructDeclaration();
const tName = t.toChars.toDString;
const entry = parentTypes.insert(tName, t);
@@ -1863,6 +1867,7 @@ extern (C++) class FuncDeclaration : Declaration
case Tstruct:
/* Drill down and check the struct's fields
*/
+ import dmd.typesem : toDsymbol;
auto sym = tp.toDsymbol(null).isStructDeclaration();
foreach (v; sym.fields)
{
@@ -2727,6 +2732,7 @@ extern (C++) class FuncDeclaration : Declaration
{
Type t1 = fdv.type.nextOf().toBasetype();
Type t2 = this.type.nextOf().toBasetype();
+ import dmd.typesem : isBaseOf;
if (t1.isBaseOf(t2, null))
{
/* Making temporary reference variable is necessary
@@ -3294,7 +3300,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
}
- if (tiargs && arrayObjectIsError(tiargs))
+ if (tiargs && arrayObjectIsError(*tiargs))
return null;
if (fargs !is null)
foreach (arg; *fargs)
@@ -3441,17 +3447,20 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
return null;
}
- const(char)* failMessage;
- functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &failMessage);
- if (failMessage)
+ bool calledHelper;
+ void errorHelper(const(char)* failMessage) scope
{
.error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
tf.modToChars(), fargsBuf.peekChars());
errorSupplemental(loc, failMessage);
- return null;
+ calledHelper = true;
}
+ functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper);
+ if (calledHelper)
+ return null;
+
if (fd.isCtorDeclaration())
.error(loc, "%s%s `%s` cannot construct a %sobject",
funcBuf.peekChars(), fd.kind(), fd.toPrettyChars(), thisBuf.peekChars());
@@ -3505,10 +3514,13 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
}
}
}
- const(char)* failMessage;
- functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &failMessage);
- if (failMessage)
+
+ void errorHelper2(const(char)* failMessage) scope
+ {
errorSupplemental(loc, failMessage);
+ }
+
+ functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper2);
}
return null;
}
@@ -3624,6 +3636,7 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
*/
Type getIndirection(Type t)
{
+ import dmd.typesem : hasPointers;
t = t.baseElemOf();
if (t.ty == Tarray || t.ty == Tpointer)
return t.nextOf().toBasetype();
@@ -3670,6 +3683,7 @@ private bool traverseIndirections(Type ta, Type tb)
static bool traverse(Type ta, Type tb, ref scope AssocArray!(const(char)*, bool) table, bool reversePass)
{
+ import dmd.typesem : hasPointers;
//printf("traverse(%s, %s)\n", ta.toChars(), tb.toChars());
ta = ta.baseElemOf();
tb = tb.baseElemOf();
@@ -3706,6 +3720,7 @@ private bool traverseIndirections(Type ta, Type tb)
else
*found = true;
+ import dmd.typesem : toDsymbol;
AggregateDeclaration sym = tb.toDsymbol(null).isAggregateDeclaration();
foreach (v; sym.fields)
{
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index b60a3f8..e9e73e8 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -15,7 +15,9 @@ import core.stdc.stdio;
import core.stdc.stdint;
import core.stdc.string;
+import dmd.astenums;
import dmd.root.array;
+import dmd.root.file;
import dmd.root.filename;
import dmd.common.outbuffer;
import dmd.errorsink;
@@ -308,7 +310,7 @@ extern (C++) struct Global
ErrorSink errorSink; /// where the error messages go
ErrorSink errorSinkNull; /// where the error messages are ignored
- extern (C++) FileName function(FileName, ref const Loc, out bool, OutBuffer*) preprocess;
+ extern (C++) DArray!ubyte function(FileName, ref const Loc, ref OutBuffer) preprocess;
nothrow:
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index c71d2f0..93e7c64 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -307,7 +307,7 @@ struct Global
ErrorSink* errorSink; // where the error messages go
ErrorSink* errorSinkNull; // where the error messages disappear
- FileName (*preprocess)(FileName, const Loc&, bool&, OutBuffer&);
+ DArray<unsigned char> (*preprocess)(FileName, const Loc&, OutBuffer&);
/* Start gagging. Return the current number of gagged errors
*/
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 4c741cd..3d88a1d 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -21,16 +21,11 @@ import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
import dmd.ast_node;
-import dmd.gluelayer;
import dmd.dclass;
-import dmd.dcast;
import dmd.declaration;
import dmd.denum;
-import dmd.dmangle;
-import dmd.dscope;
import dmd.dstruct;
import dmd.dsymbol;
-import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
@@ -39,9 +34,7 @@ import dmd.globals;
import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
-import dmd.init;
import dmd.location;
-import dmd.opover;
import dmd.root.ctfloat;
import dmd.common.outbuffer;
import dmd.root.rmem;
@@ -256,57 +249,6 @@ bool isSomeChar(TY ty) pure nothrow @nogc @safe
return ty == Tchar || ty == Twchar || ty == Tdchar;
}
-/************************************
- * Determine mutability of indirections in (ref) t.
- *
- * Returns: When the type has any mutable indirections, returns 0.
- * When all indirections are immutable, returns 2.
- * Otherwise, when the type has const/inout indirections, returns 1.
- *
- * Params:
- * isref = if true, check `ref t`; otherwise, check just `t`
- * t = the type that is being checked
- */
-int mutabilityOfType(bool isref, Type t)
-{
- if (isref)
- {
- if (t.mod & MODFlags.immutable_)
- return 2;
- if (t.mod & (MODFlags.const_ | MODFlags.wild))
- return 1;
- return 0;
- }
-
- t = t.baseElemOf();
-
- if (!t.hasPointers() || t.mod & MODFlags.immutable_)
- return 2;
-
- /* Accept immutable(T)[] and immutable(T)* as being strongly pure
- */
- if (t.ty == Tarray || t.ty == Tpointer)
- {
- Type tn = t.nextOf().toBasetype();
- if (tn.mod & MODFlags.immutable_)
- return 2;
- if (tn.mod & (MODFlags.const_ | MODFlags.wild))
- return 1;
- }
-
- /* The rest of this is too strict; fix later.
- * For example, the only pointer members of a struct may be immutable,
- * which would maintain strong purity.
- * (Just like for dynamic arrays and pointers above.)
- */
- if (t.mod & (MODFlags.const_ | MODFlags.wild))
- return 1;
-
- /* Should catch delegates and function pointers, and fold in their purity
- */
- return 0;
-}
-
/****************
* dotExp() bit flags
*/
@@ -363,7 +305,7 @@ extern (C++) abstract class Type : ASTNode
TypeInfoDeclaration vtinfo; // TypeInfo object for this Type
- type* ctype; // for back end
+ void* ctype; // for back end
extern (C++) __gshared Type tvoid;
extern (C++) __gshared Type tint8;
@@ -659,31 +601,6 @@ extern (C++) abstract class Type : ASTNode
return cast(uint)size(Loc.initial);
}
- final Type trySemantic(const ref Loc loc, Scope* sc)
- {
- //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
-
- // Needed to display any deprecations that were gagged
- auto tcopy = this.syntaxCopy();
-
- const errors = global.startGagging();
- Type t = typeSemantic(this, loc, sc);
- if (global.endGagging(errors) || t.ty == Terror) // if any errors happened
- {
- t = null;
- }
- else
- {
- // If `typeSemantic` succeeded, there may have been deprecations that
- // were gagged due the `startGagging` above. Run again to display
- // those deprecations. https://issues.dlang.org/show_bug.cgi?id=19107
- if (global.gaggedWarnings > 0)
- typeSemantic(tcopy, loc, sc);
- }
- //printf("-trySemantic(%s) %d\n", toChars(), global.errors);
- return t;
- }
-
/*************************************
* This version does a merge even if the deco is already computed.
* Necessary for types that have a deco, but are not merged.
@@ -1907,11 +1824,6 @@ extern (C++) abstract class Type : ASTNode
return t;
}
- Dsymbol toDsymbol(Scope* sc)
- {
- return null;
- }
-
/*******************************
* If this is a shell around another type,
* get that other type.
@@ -1925,11 +1837,6 @@ extern (C++) abstract class Type : ASTNode
return ((te = isTypeEnum()) !is null) ? te.toBasetype2() : this;
}
- bool isBaseOf(Type t, int* poffset)
- {
- return 0; // assume not
- }
-
/********************************
* Determine if 'this' can be implicitly converted
* to type 'to'.
@@ -2155,32 +2062,6 @@ extern (C++) abstract class Type : ASTNode
return false; // assume not
}
- final Identifier getTypeInfoIdent()
- {
- // _init_10TypeInfo_%s
- OutBuffer buf;
- buf.reserve(32);
- mangleToBuffer(this, buf);
-
- const slice = buf[];
-
- // Allocate buffer on stack, fail over to using malloc()
- char[128] namebuf;
- const namelen = 19 + size_t.sizeof * 3 + slice.length + 1;
- auto name = namelen <= namebuf.length ? namebuf.ptr : cast(char*)Mem.check(malloc(namelen));
-
- const length = snprintf(name, namelen, "_D%lluTypeInfo_%.*s6__initZ",
- cast(ulong)(9 + slice.length), cast(int)slice.length, slice.ptr);
- //printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name);
- assert(0 < length && length < namelen); // don't overflow the buffer
-
- auto id = Identifier.idPool(name[0 .. length]);
-
- if (name != namebuf.ptr)
- free(name);
- return id;
- }
-
/***************************************
* Return !=0 if the type or any of its subtypes is wild.
*/
@@ -2189,16 +2070,6 @@ extern (C++) abstract class Type : ASTNode
return mod & MODFlags.wild;
}
- /***************************************
- * Return !=0 if type has pointers that need to
- * be scanned by the GC during a collection cycle.
- */
- bool hasPointers()
- {
- //printf("Type::hasPointers() %s, %d\n", toChars(), ty);
- return false;
- }
-
/*************************************
* Detect if type has pointer fields that are initialized to void.
* Local stack variables with such void fields can remain uninitialized,
@@ -2340,76 +2211,6 @@ extern (C++) abstract class Type : ASTNode
return false;
}
- /*************************************
- * https://issues.dlang.org/show_bug.cgi?id=14488
- * Check if the inner most base type is complex or imaginary.
- * Should only give alerts when set to emit transitional messages.
- * Params:
- * loc = The source location.
- * sc = scope of the type
- */
- extern (D) final bool checkComplexTransition(const ref Loc loc, Scope* sc)
- {
- if (sc.isDeprecated())
- return false;
- // Don't complain if we're inside a template constraint
- // https://issues.dlang.org/show_bug.cgi?id=21831
- if (sc.flags & SCOPE.constraint)
- return false;
-
- Type t = baseElemOf();
- while (t.ty == Tpointer || t.ty == Tarray)
- t = t.nextOf().baseElemOf();
-
- // Basetype is an opaque enum, nothing to check.
- if (t.ty == Tenum && !(cast(TypeEnum)t).sym.memtype)
- return false;
-
- if (t.isimaginary() || t.iscomplex())
- {
- if (sc.flags & SCOPE.Cfile)
- return true; // complex/imaginary not deprecated in C code
- Type rt;
- switch (t.ty)
- {
- case Tcomplex32:
- case Timaginary32:
- rt = Type.tfloat32;
- break;
-
- case Tcomplex64:
- case Timaginary64:
- rt = Type.tfloat64;
- break;
-
- case Tcomplex80:
- case Timaginary80:
- rt = Type.tfloat80;
- break;
-
- default:
- assert(0);
- }
- // @@@DEPRECATED_2.117@@@
- // Deprecated in 2.097 - Can be made an error from 2.117.
- // The deprecation period is longer than usual as `cfloat`,
- // `cdouble`, and `creal` were quite widely used.
- if (t.iscomplex())
- {
- deprecation(loc, "use of complex type `%s` is deprecated, use `std.complex.Complex!(%s)` instead",
- toChars(), rt.toChars());
- return true;
- }
- else
- {
- deprecation(loc, "use of imaginary type `%s` is deprecated, use `%s` instead",
- toChars(), rt.toChars());
- return true;
- }
- }
- return false;
- }
-
// For eliminating dynamic_cast
TypeBasic isTypeBasic()
{
@@ -3531,24 +3332,6 @@ extern (C++) final class TypeSArray : TypeArray
return ae;
}
- override bool hasPointers()
- {
- /* Don't want to do this, because:
- * struct S { T* array[0]; }
- * may be a variable length struct.
- */
- //if (dim.toInteger() == 0)
- // return false;
-
- if (next.ty == Tvoid)
- {
- // Arrays of void contain arbitrary data, which may include pointers
- return true;
- }
- else
- return next.hasPointers();
- }
-
override bool hasSystemFields()
{
return next.hasSystemFields();
@@ -3673,11 +3456,6 @@ extern (C++) final class TypeDArray : TypeArray
return Type.implicitConvTo(to);
}
- override bool hasPointers()
- {
- return true;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -3734,11 +3512,6 @@ extern (C++) final class TypeAArray : TypeArray
return true;
}
- override bool hasPointers()
- {
- return true;
- }
-
override MATCH implicitConvTo(Type to)
{
//printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
@@ -3877,11 +3650,6 @@ extern (C++) final class TypePointer : TypeNext
return true;
}
- override bool hasPointers()
- {
- return true;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4059,39 +3827,6 @@ extern (C++) final class TypeFunction : TypeNext
}
/********************************************
- * Set 'purity' field of 'this'.
- * Do this lazily, as the parameter types might be forward referenced.
- */
- void purityLevel()
- {
- TypeFunction tf = this;
- if (tf.purity != PURE.fwdref)
- return;
-
- purity = PURE.const_; // assume strong until something weakens it
-
- /* Evaluate what kind of purity based on the modifiers for the parameters
- */
- foreach (i, fparam; tf.parameterList)
- {
- Type t = fparam.type;
- if (!t)
- continue;
-
- if (fparam.storageClass & (STC.lazy_ | STC.out_))
- {
- purity = PURE.weak;
- break;
- }
- const pref = (fparam.storageClass & STC.ref_) != 0;
- if (mutabilityOfType(pref, t) == 0)
- purity = PURE.weak;
- }
-
- tf.purity = purity;
- }
-
- /********************************************
* Return true if there are lazy parameters.
*/
bool hasLazyParameters()
@@ -4115,122 +3850,6 @@ extern (C++) final class TypeFunction : TypeNext
return linkage == LINK.d && parameterList.varargs == VarArg.variadic;
}
- /************************************
- * Take the specified storage class for p,
- * and use the function signature to infer whether
- * STC.scope_ and STC.return_ should be OR'd in.
- * (This will not affect the name mangling.)
- * Params:
- * tthis = type of `this` parameter, null if none
- * p = parameter to this function
- * outerVars = context variables p could escape into, if any
- * indirect = is this for an indirect or virtual function call?
- * Returns:
- * storage class with STC.scope_ or STC.return_ OR'd in
- */
- StorageClass parameterStorageClass(Type tthis, Parameter p, VarDeclarations* outerVars = null,
- bool indirect = false)
- {
- //printf("parameterStorageClass(p: %s)\n", p.toChars());
- auto stc = p.storageClass;
-
- // When the preview switch is enable, `in` parameters are `scope`
- if (stc & STC.constscoperef)
- return stc | STC.scope_;
-
- if (stc & (STC.scope_ | STC.return_ | STC.lazy_) || purity == PURE.impure)
- return stc;
-
- /* If haven't inferred the return type yet, can't infer storage classes
- */
- if (!nextOf() || !isnothrow())
- return stc;
-
- purityLevel();
-
- static bool mayHavePointers(Type t)
- {
- if (auto ts = t.isTypeStruct())
- {
- auto sym = ts.sym;
- if (sym.members && !sym.determineFields() && sym.type != Type.terror)
- // struct is forward referenced, so "may have" pointers
- return true;
- }
- return t.hasPointers();
- }
-
- // See if p can escape via any of the other parameters
- if (purity == PURE.weak)
- {
- /*
- * Indirect calls may escape p through a nested context
- * See:
- * https://issues.dlang.org/show_bug.cgi?id=24212
- * https://issues.dlang.org/show_bug.cgi?id=24213
- */
- if (indirect)
- return stc;
-
- // Check escaping through parameters
- foreach (i, fparam; parameterList)
- {
- Type t = fparam.type;
- if (!t)
- continue;
- t = t.baseElemOf(); // punch thru static arrays
- if (t.isMutable() && t.hasPointers())
- {
- if (fparam.isReference() && fparam != p)
- return stc;
-
- if (t.ty == Tdelegate)
- return stc; // could escape thru delegate
-
- if (t.ty == Tclass)
- return stc;
-
- /* if t is a pointer to mutable pointer
- */
- if (auto tn = t.nextOf())
- {
- if (tn.isMutable() && mayHavePointers(tn))
- return stc; // escape through pointers
- }
- }
- }
-
- // Check escaping through `this`
- if (tthis && tthis.isMutable())
- {
- foreach (VarDeclaration v; isAggregate(tthis).fields)
- {
- if (v.hasPointers())
- return stc;
- }
- }
-
- // Check escaping through nested context
- if (outerVars && this.isMutable())
- {
- foreach (VarDeclaration v; *outerVars)
- {
- if (v.hasPointers())
- return stc;
- }
- }
- }
-
- // Check escaping through return value
- Type tret = nextOf().toBasetype();
- if (isref || tret.hasPointers())
- {
- return stc | STC.scope_ | STC.return_ | STC.returnScope;
- }
- else
- return stc | STC.scope_;
- }
-
override Type addStorageClass(StorageClass stc)
{
//printf("addStorageClass(%llx) %d\n", stc, (stc & STC.scope_) != 0);
@@ -4631,11 +4250,6 @@ extern (C++) final class TypeDelegate : TypeNext
return true;
}
- override bool hasPointers()
- {
- return true;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4676,20 +4290,6 @@ extern (C++) final class TypeTraits : Type
return tt;
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- Type t;
- Expression e;
- Dsymbol s;
- resolve(this, loc, sc, e, t, s);
- if (t && t.ty != Terror)
- s = t.toDsymbol(sc);
- else if (e)
- s = getDsymbol(e);
-
- return s;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4729,20 +4329,6 @@ extern (C++) final class TypeMixin : Type
return new TypeMixin(loc, Expression.arraySyntaxCopy(exps));
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- Type t;
- Expression e;
- Dsymbol s;
- resolve(this, loc, sc, e, t, s);
- if (t)
- s = t.toDsymbol(sc);
- else if (e)
- s = getDsymbol(e);
-
- return s;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4867,28 +4453,6 @@ extern (C++) final class TypeIdentifier : TypeQualified
return t;
}
- /*****************************************
- * See if type resolves to a symbol, if so,
- * return that symbol.
- */
- override Dsymbol toDsymbol(Scope* sc)
- {
- //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
- if (!sc)
- return null;
-
- Type t;
- Expression e;
- Dsymbol s;
- resolve(this, loc, sc, e, t, s);
- if (t && t.ty != Tident)
- s = t.toDsymbol(sc);
- if (e)
- s = getDsymbol(e);
-
- return s;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4922,18 +4486,6 @@ extern (C++) final class TypeInstance : TypeQualified
return t;
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- Type t;
- Expression e;
- Dsymbol s;
- //printf("TypeInstance::semantic(%s)\n", toChars());
- resolve(this, loc, sc, e, t, s);
- if (t && t.ty != Tinstance)
- s = t.toDsymbol(sc);
- return s;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4967,16 +4519,6 @@ extern (C++) final class TypeTypeof : TypeQualified
return t;
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- //printf("TypeTypeof::toDsymbol('%s')\n", toChars());
- Expression e;
- Type t;
- Dsymbol s;
- resolve(this, loc, sc, e, t, s);
- return s;
- }
-
override uinteger_t size(const ref Loc loc)
{
if (exp.type)
@@ -5013,15 +4555,6 @@ extern (C++) final class TypeReturn : TypeQualified
return t;
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- Expression e;
- Type t;
- Dsymbol s;
- resolve(this, loc, sc, e, t, s);
- return s;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -5068,11 +4601,6 @@ extern (C++) final class TypeStruct : Type
return this;
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- return sym;
- }
-
override structalign_t alignment()
{
if (sym.alignment.isUnknown())
@@ -5214,15 +4742,6 @@ extern (C++) final class TypeStruct : Type
return false;
}
- override bool hasPointers()
- {
- if (sym.members && !sym.determineFields() && sym.type != Type.terror)
- error(sym.loc, "no size because of forward references");
-
- sym.determineTypeProperties();
- return sym.hasPointerField;
- }
-
override bool hasVoidInitPointers()
{
sym.size(Loc.initial); // give error for forward references
@@ -5393,9 +4912,9 @@ extern (C++) final class TypeEnum : Type
return sym.getMemtype(loc).size(loc);
}
- Type memType(const ref Loc loc = Loc.initial)
+ Type memType()
{
- return sym.getMemtype(loc);
+ return sym.getMemtype(Loc.initial);
}
override uint alignsize()
@@ -5406,11 +4925,6 @@ extern (C++) final class TypeEnum : Type
return t.alignsize();
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- return sym;
- }
-
override bool isintegral()
{
return memType().isintegral();
@@ -5511,11 +5025,6 @@ extern (C++) final class TypeEnum : Type
return sym.getDefaultValue(loc).toBool().hasValue(false);
}
- override bool hasPointers()
- {
- return memType().hasPointers();
- }
-
override bool hasVoidInitPointers()
{
return memType().hasVoidInitPointers();
@@ -5571,44 +5080,14 @@ extern (C++) final class TypeClass : Type
return this;
}
- override Dsymbol toDsymbol(Scope* sc)
- {
- return sym;
- }
-
override inout(ClassDeclaration) isClassHandle() inout
{
return sym;
}
- override bool isBaseOf(Type t, int* poffset)
- {
- if (t && t.ty == Tclass)
- {
- ClassDeclaration cd = (cast(TypeClass)t).sym;
- if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete())
- cd.dsymbolSemantic(null);
- if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
- sym.dsymbolSemantic(null);
-
- if (sym.isBaseOf(cd, poffset))
- return true;
- }
- return false;
- }
-
extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
{
- // Run semantic before checking whether class is convertible
ClassDeclaration cdto = to.isClassHandle();
- if (cdto)
- {
- //printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to.toChars(), toChars(), cdto.isBaseInfoComplete(), sym.isBaseInfoComplete());
- if (cdto.semanticRun < PASS.semanticdone && !cdto.isBaseInfoComplete())
- cdto.dsymbolSemantic(null);
- if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
- sym.dsymbolSemantic(null);
- }
MATCH m = constConv(to);
if (m > MATCH.nomatch)
return m;
@@ -5706,11 +5185,6 @@ extern (C++) final class TypeClass : Type
return true;
}
- override bool hasPointers()
- {
- return true;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -5952,14 +5426,6 @@ extern (C++) final class TypeNull : Type
return MATCH.nomatch;
}
- override bool hasPointers()
- {
- /* Although null isn't dereferencable, treat it as a pointer type for
- * attribute inference, generic code, etc.
- */
- return true;
- }
-
override bool isBoolean()
{
return true;
@@ -6633,39 +6099,6 @@ bool isIndexableNonAggregate(Type t)
t.ty == Ttuple || t.ty == Tvector);
}
-/***************************************************
- * Determine if type t is copyable.
- * Params:
- * t = type to check
- * Returns:
- * true if we can copy it
- */
-bool isCopyable(Type t)
-{
- //printf("isCopyable() %s\n", t.toChars());
- if (auto ts = t.isTypeStruct())
- {
- if (ts.sym.postblit &&
- ts.sym.postblit.storage_class & STC.disable)
- return false;
- if (ts.sym.hasCopyCtor)
- {
- // check if there is a matching overload of the copy constructor and whether it is disabled or not
- // `assert(ctor)` fails on Win32 and Win_32_64. See: https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=1&pullid=10575
- Dsymbol ctor = search_function(ts.sym, Id.ctor);
- assert(ctor);
- scope el = new IdentifierExp(Loc.initial, Id.p); // dummy lvalue
- el.type = cast() ts;
- Expressions* args = new Expressions();
- args.push(el);
- FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(args), FuncResolveFlag.quiet);
- if (!f || f.storage_class & STC.disable)
- return false;
- }
- }
- return true;
-}
-
/***************************************
* Computes how a parameter may be returned.
* Shrinking the representation is necessary because StorageClass is so wide
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 97a7ae3..c777f35 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -233,7 +233,6 @@ public:
uinteger_t size();
virtual uinteger_t size(const Loc &loc);
virtual unsigned alignsize();
- Type *trySemantic(const Loc &loc, Scope *sc);
Type *merge2();
void modToBuffer(OutBuffer& buf) const;
char *modToChars() const;
@@ -287,9 +286,7 @@ public:
virtual Type *makeSharedWild();
virtual Type *makeSharedWildConst();
virtual Type *makeMutable();
- virtual Dsymbol *toDsymbol(Scope *sc);
Type *toBasetype();
- virtual bool isBaseOf(Type *t, int *poffset);
virtual MATCH implicitConvTo(Type *to);
virtual MATCH constConv(Type *to);
virtual unsigned char deduceWild(Type *t, bool isRef);
@@ -302,9 +299,7 @@ public:
virtual structalign_t alignment();
virtual Expression *defaultInitLiteral(const Loc &loc);
virtual bool isZeroInit(const Loc &loc = Loc()); // if initializer is 0
- Identifier *getTypeInfoIdent();
virtual int hasWild() const;
- virtual bool hasPointers();
virtual bool hasVoidInitPointers();
virtual bool hasSystemFields();
virtual bool hasInvariant();
@@ -451,7 +446,6 @@ public:
MATCH constConv(Type *to) override;
MATCH implicitConvTo(Type *to) override;
Expression *defaultInitLiteral(const Loc &loc) override;
- bool hasPointers() override;
bool hasSystemFields() override;
bool hasVoidInitPointers() override;
bool hasInvariant() override;
@@ -474,7 +468,6 @@ public:
bool isZeroInit(const Loc &loc) override;
bool isBoolean() override;
MATCH implicitConvTo(Type *to) override;
- bool hasPointers() override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -491,7 +484,6 @@ public:
uinteger_t size(const Loc &loc) override;
bool isZeroInit(const Loc &loc) override;
bool isBoolean() override;
- bool hasPointers() override;
MATCH implicitConvTo(Type *to) override;
MATCH constConv(Type *to) override;
@@ -509,7 +501,6 @@ public:
MATCH constConv(Type *to) override;
bool isscalar() override;
bool isZeroInit(const Loc &loc) override;
- bool hasPointers() override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -605,10 +596,8 @@ public:
static TypeFunction *create(Parameters *parameters, Type *treturn, VarArg varargs, LINK linkage, StorageClass stc = 0);
const char *kind() override;
TypeFunction *syntaxCopy() override;
- void purityLevel();
bool hasLazyParameters();
bool isDstyleVariadic() const;
- StorageClass parameterStorageClass(Type* tthis, Parameter *p, VarDeclarations* outerVars = nullptr, bool indirect = false);
Type *addStorageClass(StorageClass stc) override;
Type *substWildTo(unsigned mod) override;
@@ -659,7 +648,6 @@ public:
MATCH implicitConvTo(Type *to) override;
bool isZeroInit(const Loc &loc) override;
bool isBoolean() override;
- bool hasPointers() override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -675,7 +663,6 @@ class TypeTraits final : public Type
const char *kind() override;
TypeTraits *syntaxCopy() override;
uinteger_t size(const Loc &loc) override;
- Dsymbol *toDsymbol(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -687,7 +674,6 @@ class TypeMixin final : public Type
const char *kind() override;
TypeMixin *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -713,7 +699,6 @@ public:
static TypeIdentifier *create(const Loc &loc, Identifier *ident);
const char *kind() override;
TypeIdentifier *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -726,7 +711,6 @@ public:
const char *kind() override;
TypeInstance *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -738,7 +722,6 @@ public:
const char *kind() override;
TypeTypeof *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
uinteger_t size(const Loc &loc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -748,7 +731,6 @@ class TypeReturn final : public TypeQualified
public:
const char *kind() override;
TypeReturn *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -776,7 +758,6 @@ public:
uinteger_t size(const Loc &loc) override;
unsigned alignsize() override;
TypeStruct *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
structalign_t alignment() override;
Expression *defaultInitLiteral(const Loc &loc) override;
bool isZeroInit(const Loc &loc) override;
@@ -785,7 +766,6 @@ public:
bool needsDestruction() override;
bool needsCopyOrPostblit() override;
bool needsNested() override;
- bool hasPointers() override;
bool hasVoidInitPointers() override;
bool hasSystemFields() override;
bool hasInvariant() override;
@@ -806,8 +786,7 @@ public:
TypeEnum *syntaxCopy() override;
uinteger_t size(const Loc &loc) override;
unsigned alignsize() override;
- Type *memType(const Loc &loc = Loc());
- Dsymbol *toDsymbol(Scope *sc) override;
+ Type *memType(const Loc &loc);
bool isintegral() override;
bool isfloating() override;
bool isreal() override;
@@ -824,7 +803,6 @@ public:
MATCH implicitConvTo(Type *to) override;
MATCH constConv(Type *to) override;
bool isZeroInit(const Loc &loc) override;
- bool hasPointers() override;
bool hasVoidInitPointers() override;
bool hasSystemFields() override;
bool hasInvariant() override;
@@ -843,9 +821,7 @@ public:
const char *kind() override;
uinteger_t size(const Loc &loc) override;
TypeClass *syntaxCopy() override;
- Dsymbol *toDsymbol(Scope *sc) override;
ClassDeclaration *isClassHandle() override;
- bool isBaseOf(Type *t, int *poffset) override;
MATCH implicitConvTo(Type *to) override;
MATCH constConv(Type *to) override;
unsigned char deduceWild(Type *t, bool isRef) override;
@@ -853,7 +829,6 @@ public:
bool isZeroInit(const Loc &loc) override;
bool isscope() override;
bool isBoolean() override;
- bool hasPointers() override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -894,7 +869,6 @@ public:
TypeNull *syntaxCopy() override;
MATCH implicitConvTo(Type *to) override;
- bool hasPointers() override;
bool isBoolean() override;
uinteger_t size(const Loc &loc) override;
@@ -925,6 +899,13 @@ public:
/**************************************************************/
+
// If the type is a class or struct, returns the symbol for it, else null.
AggregateDeclaration *isAggregate(Type *t);
+bool hasPointers(Type *t);
+// return the symbol to which type t resolves
+Dsymbol *toDsymbol(Type *t, Scope *sc);
Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
+bool isBaseOf(Type *tthis, Type *t, int *poffset);
+Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
+void purityLevel(TypeFunction *type);
diff --git a/gcc/d/dmd/mustuse.d b/gcc/d/dmd/mustuse.d
index b5601a2..c2fa5fb 100644
--- a/gcc/d/dmd/mustuse.d
+++ b/gcc/d/dmd/mustuse.d
@@ -31,6 +31,7 @@ import dmd.location;
bool checkMustUse(Expression e, Scope* sc)
{
import dmd.id : Id;
+ import dmd.typesem : toDsymbol;
assert(e.type);
if (auto sym = e.type.toDsymbol(sc))
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 785912e..0a59815 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -2566,6 +2566,7 @@ void checkObErrors(ref ObState obstate)
//printf("%s: ", obstate.vars[i].toChars()); pvs.print(obstate.vars[]);
if (pvs.state == PtrState.Owner)
{
+ import dmd.typesem : hasPointers;
auto v = obstate.vars[i];
if (v.type.hasPointers())
.error(v.loc, "%s `%s` is not disposed of before return", v.kind, v.toPrettyChars);
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index a012e0c..268622a 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -1675,7 +1675,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.assign) // = CondExpression
{
nextToken();
- tp_defaultvalue = parseDefaultInitExp();
+ tp_defaultvalue = parseAssignExp();
}
tp = new AST.TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
}
@@ -2969,7 +2969,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.assign) // = defaultArg
{
nextToken();
- ae = parseDefaultInitExp();
+ ae = parseAssignExp();
}
auto param = new AST.Parameter(loc, storageClass | STC.parameter, at, ai, ae, null);
if (udas)
@@ -6949,33 +6949,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
}
- /*****************************************
- * Parses default argument initializer expression that is an assign expression,
- * with special handling for __FILE__, __FILE_DIR__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__.
- */
- private AST.Expression parseDefaultInitExp()
- {
- AST.Expression e = null;
- const tv = peekNext();
- if (tv == TOK.comma || tv == TOK.rightParenthesis)
- {
- switch (token.value)
- {
- case TOK.file: e = new AST.FileInitExp(token.loc, EXP.file); break;
- case TOK.fileFullPath: e = new AST.FileInitExp(token.loc, EXP.fileFullPath); break;
- case TOK.line: e = new AST.LineInitExp(token.loc); break;
- case TOK.moduleString: e = new AST.ModuleInitExp(token.loc); break;
- case TOK.functionString: e = new AST.FuncInitExp(token.loc); break;
- case TOK.prettyFunction: e = new AST.PrettyFuncInitExp(token.loc); break;
- default: goto LExp;
- }
- nextToken();
- return e;
- }
- LExp:
- return parseAssignExp();
- }
-
/********************
* Parse inline assembler block.
* Enters with token on the `asm`.
@@ -8152,33 +8125,23 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
break;
case TOK.file:
- {
- const(char)* s = loc.filename ? loc.filename : mod.ident.toChars();
- e = new AST.StringExp(loc, s.toDString());
- nextToken();
- break;
- }
+ e = new AST.FileInitExp(loc, EXP.file);
+ nextToken();
+ break;
case TOK.fileFullPath:
- {
- assert(loc.isValid(), "__FILE_FULL_PATH__ does not work with an invalid location");
- const s = FileName.toAbsolute(loc.filename);
- e = new AST.StringExp(loc, s.toDString());
- nextToken();
- break;
- }
+ e = new AST.FileInitExp(loc, EXP.fileFullPath);
+ nextToken();
+ break;
case TOK.line:
- e = new AST.IntegerExp(loc, loc.linnum, AST.Type.tint32);
+ e = new AST.LineInitExp(loc);
nextToken();
break;
case TOK.moduleString:
- {
- const(char)* s = md ? md.toChars() : mod.toChars();
- e = new AST.StringExp(loc, s.toDString());
- nextToken();
- break;
- }
+ e = new AST.ModuleInitExp(loc);
+ nextToken();
+ break;
case TOK.functionString:
e = new AST.FuncInitExp(loc);
nextToken();
diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d
index af81bff..8b57f7f 100644
--- a/gcc/d/dmd/safe.d
+++ b/gcc/d/dmd/safe.d
@@ -26,6 +26,7 @@ import dmd.identifier;
import dmd.mtype;
import dmd.target;
import dmd.tokens;
+import dmd.typesem : hasPointers;
import dmd.func : setUnsafe, setUnsafePreview;
/*************************************************************
diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index 1535fd0..4b157cc 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/dmd/scope.h
@@ -87,6 +87,7 @@ struct Scope
Dsymbol *inunion; // !=null if processing members of a union
d_bool nofree; // true if shouldn't free it
d_bool inLoop; // true if inside a loop (where constructor calls aren't allowed)
+ d_bool inDefaultArg; // true if inside a default argument (where __FILE__, etc are evaluated at the call site)
int intypeof; // in typeof(exp)
VarDeclaration *lastVar; // Previous symbol used to prevent goto-skips-init
ErrorSink *eSink; // sink for error messages
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 520e05f..174d9b4 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -231,8 +231,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (sc.flags & SCOPE.Cfile && funcdecl.isCMain() && f.next.ty == Tint32)
return true;
- return f.next.ty == Tvoid &&
- (funcdecl.isMain() || global.params.betterC && funcdecl.isCMain());
+ return f.next.ty == Tvoid && (funcdecl.isMain() || funcdecl.isCMain());
}
VarDeclaration _arguments = null;
@@ -346,6 +345,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc2.tf = null;
sc2.os = null;
sc2.inLoop = false;
+ sc2.inDefaultArg = false;
sc2.userAttribDecl = null;
if (sc2.intypeof == 1)
sc2.intypeof = 2;
@@ -570,7 +570,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if ((needEnsure && global.params.useOut == CHECKENABLE.on) || fpostinv)
{
- funcdecl.returnLabel = funcdecl.searchLabel(Id.returnLabel);
+ funcdecl.returnLabel = funcdecl.searchLabel(Id.returnLabel, Loc.initial);
}
// scope of out contract (need for vresult.semantic)
diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d
index 59398a7..8038770 100644
--- a/gcc/d/dmd/sideeffect.d
+++ b/gcc/d/dmd/sideeffect.d
@@ -24,6 +24,7 @@ import dmd.init;
import dmd.mtype;
import dmd.postordervisitor;
import dmd.tokens;
+import dmd.typesem;
import dmd.visitor;
/**************************************************
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 229cf17..d4827ae 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -3753,7 +3753,10 @@ public bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc)
{
if (!global.params.useExceptions)
{
- loc.error("cannot use `throw` statements with %s", global.params.betterC ? "-betterC".ptr : "-nothrow".ptr);
+ version (IN_GCC)
+ loc.error("cannot use `throw` statements with `-fno-exceptions`");
+ else
+ loc.error("cannot use `throw` statements with %s", global.params.betterC ? "-betterC".ptr : "-nothrow".ptr);
return false;
}
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 09c4912..153eb4e 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -324,4 +324,4 @@ Tuple *isTuple(RootObject *o);
Parameter *isParameter(RootObject *o);
TemplateParameter *isTemplateParameter(RootObject *o);
bool isError(const RootObject *const o);
-void printTemplateStats();
+void printTemplateStats(bool listInstances, ErrorSink* eSink);
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 51b4ef8..714af8a 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -430,6 +430,123 @@ private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject i
return sm;
}
+/***************************************************
+ * Determine if type t is copyable.
+ * Params:
+ * t = type to check
+ * Returns:
+ * true if we can copy it
+ */
+bool isCopyable(Type t)
+{
+ //printf("isCopyable() %s\n", t.toChars());
+ if (auto ts = t.isTypeStruct())
+ {
+ if (ts.sym.postblit &&
+ ts.sym.postblit.storage_class & STC.disable)
+ return false;
+ if (ts.sym.hasCopyCtor)
+ {
+ // check if there is a matching overload of the copy constructor and whether it is disabled or not
+ // `assert(ctor)` fails on Win32 and Win_32_64. See: https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=1&pullid=10575
+ Dsymbol ctor = search_function(ts.sym, Id.ctor);
+ assert(ctor);
+ scope el = new IdentifierExp(Loc.initial, Id.p); // dummy lvalue
+ el.type = cast() ts;
+ Expressions* args = new Expressions();
+ args.push(el);
+ FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(args), FuncResolveFlag.quiet);
+ if (!f || f.storage_class & STC.disable)
+ return false;
+ }
+ }
+ return true;
+}
+
+/************************************
+ * Determine mutability of indirections in (ref) t.
+ *
+ * Returns: When the type has any mutable indirections, returns 0.
+ * When all indirections are immutable, returns 2.
+ * Otherwise, when the type has const/inout indirections, returns 1.
+ *
+ * Params:
+ * isref = if true, check `ref t`; otherwise, check just `t`
+ * t = the type that is being checked
+ */
+int mutabilityOfType(bool isref, Type t)
+{
+ if (isref)
+ {
+ if (t.mod & MODFlags.immutable_)
+ return 2;
+ if (t.mod & (MODFlags.const_ | MODFlags.wild))
+ return 1;
+ return 0;
+ }
+
+ t = t.baseElemOf();
+
+ if (!t.hasPointers() || t.mod & MODFlags.immutable_)
+ return 2;
+
+ /* Accept immutable(T)[] and immutable(T)* as being strongly pure
+ */
+ if (t.ty == Tarray || t.ty == Tpointer)
+ {
+ Type tn = t.nextOf().toBasetype();
+ if (tn.mod & MODFlags.immutable_)
+ return 2;
+ if (tn.mod & (MODFlags.const_ | MODFlags.wild))
+ return 1;
+ }
+
+ /* The rest of this is too strict; fix later.
+ * For example, the only pointer members of a struct may be immutable,
+ * which would maintain strong purity.
+ * (Just like for dynamic arrays and pointers above.)
+ */
+ if (t.mod & (MODFlags.const_ | MODFlags.wild))
+ return 1;
+
+ /* Should catch delegates and function pointers, and fold in their purity
+ */
+ return 0;
+}
+
+/********************************************
+ * Set 'purity' field of 'typeFunction'.
+ * Do this lazily, as the parameter types might be forward referenced.
+ */
+extern(C++) void purityLevel(TypeFunction typeFunction)
+{
+ TypeFunction tf = typeFunction;
+ if (tf.purity != PURE.fwdref)
+ return;
+
+ typeFunction.purity = PURE.const_; // assume strong until something weakens it
+
+ /* Evaluate what kind of purity based on the modifiers for the parameters
+ */
+ foreach (i, fparam; tf.parameterList)
+ {
+ Type t = fparam.type;
+ if (!t)
+ continue;
+
+ if (fparam.storageClass & (STC.lazy_ | STC.out_))
+ {
+ typeFunction.purity = PURE.weak;
+ break;
+ }
+ const pref = (fparam.storageClass & STC.ref_) != 0;
+ if (mutabilityOfType(pref, t) == 0)
+ typeFunction.purity = PURE.weak;
+ }
+
+ tf.purity = typeFunction.purity;
+}
+
/******************************************
* We've mistakenly parsed `t` as a type.
* Redo `t` as an Expression only if there are no type modifiers.
@@ -486,6 +603,77 @@ Expression typeToExpression(Type t)
}
}
+/*************************************
+ * https://issues.dlang.org/show_bug.cgi?id=14488
+ * Check if the inner most base type is complex or imaginary.
+ * Should only give alerts when set to emit transitional messages.
+ * Params:
+ * type = type to check
+ * loc = The source location.
+ * sc = scope of the type
+ */
+extern (D) bool checkComplexTransition(Type type, const ref Loc loc, Scope* sc)
+{
+ if (sc.isDeprecated())
+ return false;
+ // Don't complain if we're inside a template constraint
+ // https://issues.dlang.org/show_bug.cgi?id=21831
+ if (sc.flags & SCOPE.constraint)
+ return false;
+
+ Type t = type.baseElemOf();
+ while (t.ty == Tpointer || t.ty == Tarray)
+ t = t.nextOf().baseElemOf();
+
+ // Basetype is an opaque enum, nothing to check.
+ if (t.ty == Tenum && !(cast(TypeEnum)t).sym.memtype)
+ return false;
+
+ if (t.isimaginary() || t.iscomplex())
+ {
+ if (sc.flags & SCOPE.Cfile)
+ return true; // complex/imaginary not deprecated in C code
+ Type rt;
+ switch (t.ty)
+ {
+ case Tcomplex32:
+ case Timaginary32:
+ rt = Type.tfloat32;
+ break;
+
+ case Tcomplex64:
+ case Timaginary64:
+ rt = Type.tfloat64;
+ break;
+
+ case Tcomplex80:
+ case Timaginary80:
+ rt = Type.tfloat80;
+ break;
+
+ default:
+ assert(0);
+ }
+ // @@@DEPRECATED_2.117@@@
+ // Deprecated in 2.097 - Can be made an error from 2.117.
+ // The deprecation period is longer than usual as `cfloat`,
+ // `cdouble`, and `creal` were quite widely used.
+ if (t.iscomplex())
+ {
+ deprecation(loc, "use of complex type `%s` is deprecated, use `std.complex.Complex!(%s)` instead",
+ type.toChars(), rt.toChars());
+ return true;
+ }
+ else
+ {
+ deprecation(loc, "use of imaginary type `%s` is deprecated, use `%s` instead",
+ type.toChars(), rt.toChars());
+ return true;
+ }
+ }
+ return false;
+}
+
/********************************
* 'args' are being matched to function type 'tf'
* Determine match level.
@@ -494,12 +682,12 @@ Expression typeToExpression(Type t)
* tthis = type of `this` pointer, null if not member function
* argumentList = arguments to function call
* flag = 1: performing a partial ordering match
- * pMessage = address to store error message, or null
+ * errorHelper = delegate to call for error messages
* sc = context
* Returns:
* MATCHxxxx
*/
-extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentList, int flag = 0, const(char)** pMessage = null, Scope* sc = null)
+extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentList, int flag = 0, void delegate(const(char)*) scope errorHelper = null, Scope* sc = null)
{
//printf("TypeFunction::callMatch() %s\n", tf.toChars());
MATCH match = MATCH.exact; // assume exact match
@@ -542,7 +730,7 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis
{
// suppress early exit if an error message is wanted,
// so we can check any matching args are valid
- if (!pMessage)
+ if (!errorHelper)
return MATCH.nomatch;
}
// too many args; no match
@@ -552,18 +740,25 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis
// https://issues.dlang.org/show_bug.cgi?id=22997
if (parameterList.varargs == VarArg.none && nparams > argumentList.length && !parameterList.hasDefaultArgs)
{
- OutBuffer buf;
- buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)argumentList.length);
- if (pMessage)
- *pMessage = buf.extractChars();
+ if (errorHelper)
+ {
+ OutBuffer buf;
+ buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)argumentList.length);
+ errorHelper(buf.peekChars());
+ }
return MATCH.nomatch;
}
+ const(char)* failMessage;
+ const(char)** pMessage = errorHelper ? &failMessage : null;
auto resolvedArgs = tf.resolveNamedArgs(argumentList, pMessage);
Expression[] args;
if (!resolvedArgs)
{
- if (!pMessage || *pMessage)
+ if (failMessage)
+ {
+ errorHelper(failMessage);
return MATCH.nomatch;
+ }
// if no message was provided, it was because of overflow which will be diagnosed below
match = MATCH.nomatch;
@@ -642,6 +837,8 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis
if (auto vmatch = matchTypeSafeVarArgs(tf, p, trailingArgs, pMessage))
return vmatch < match ? vmatch : match;
// Error message was already generated in `matchTypeSafeVarArgs`
+ if (failMessage)
+ errorHelper(failMessage);
return MATCH.nomatch;
}
if (pMessage && u >= args.length)
@@ -651,16 +848,18 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis
else if (pMessage && !*pMessage)
*pMessage = tf.getParamError(args[u], p);
+ if (errorHelper)
+ errorHelper(*pMessage);
return MATCH.nomatch;
}
if (m < match)
match = m; // pick worst match
}
- if (pMessage && !parameterList.varargs && args.length > nparams)
+ if (errorHelper && !parameterList.varargs && args.length > nparams)
{
// all parameters had a match, but there are surplus args
- *pMessage = tf.getMatchError("expected %d argument(s), not %d", nparams, args.length);
+ errorHelper(tf.getMatchError("expected %d argument(s), not %d", nparams, args.length));
return MATCH.nomatch;
}
//printf("match = %d\n", match);
@@ -687,7 +886,7 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct,
Expression e = new DotIdExp(arg.loc, ve, Id.ctor);
e = new CallExp(arg.loc, e, arg);
//printf("e = %s\n", e.toChars());
- if (.trySemantic(e, sc))
+ if (dmd.expressionsem.trySemantic(e, sc))
return true;
if (pMessage)
@@ -1017,6 +1216,70 @@ private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p,
}
}
+/***************************************
+ * Return !=0 if type has pointers that need to
+ * be scanned by the GC during a collection cycle.
+ */
+extern(C++) bool hasPointers(Type t)
+{
+ bool visitType(Type _) { return false; }
+ bool visitDArray(TypeDArray _) { return true; }
+ bool visitAArray(TypeAArray _) { return true; }
+ bool visitPointer(TypePointer _) { return true; }
+ bool visitDelegate(TypeDelegate _) { return true; }
+ bool visitClass(TypeClass _) { return true; }
+ bool visitEnum(TypeEnum t) { return t.memType().hasPointers(); }
+
+ /* Although null isn't dereferencable, treat it as a pointer type for
+ * attribute inference, generic code, etc.
+ */
+ bool visitNull(TypeNull _) { return true; }
+
+ bool visitSArray(TypeSArray t)
+ {
+ /* Don't want to do this, because:
+ * struct S { T* array[0]; }
+ * may be a variable length struct.
+ */
+ //if (dim.toInteger() == 0)
+ // return false;
+
+ if (t.next.ty == Tvoid)
+ {
+ // Arrays of void contain arbitrary data, which may include pointers
+ return true;
+ }
+ else
+ return t.next.hasPointers();
+ }
+
+ bool visitStruct(TypeStruct t)
+ {
+ StructDeclaration sym = t.sym;
+
+ if (sym.members && !sym.determineFields() && sym.type != Type.terror)
+ error(sym.loc, "no size because of forward references");
+
+ sym.determineTypeProperties();
+ return sym.hasPointerField;
+ }
+
+
+ switch(t.ty)
+ {
+ default: return visitType(t);
+ case Tsarray: return visitSArray(t.isTypeSArray());
+ case Tarray: return visitDArray(t.isTypeDArray());
+ case Taarray: return visitAArray(t.isTypeAArray());
+ case Tpointer: return visitPointer(t.isTypePointer());
+ case Tdelegate: return visitDelegate(t.isTypeDelegate());
+ case Tstruct: return visitStruct(t.isTypeStruct());
+ case Tenum: return visitEnum(t.isTypeEnum());
+ case Tclass: return visitClass(t.isTypeClass());
+ case Tnull: return visitNull(t.isTypeNull());
+ }
+}
+
/******************************************
* Perform semantic analysis on a type.
* Params:
@@ -1661,9 +1924,12 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
else
{
e = inferType(e, fparam.type);
+ Scope* sc2 = sc.push();
+ sc2.inDefaultArg = true;
Initializer iz = new ExpInitializer(e.loc, e);
- iz = iz.initializerSemantic(sc, fparam.type, INITnointerpret);
+ iz = iz.initializerSemantic(sc2, fparam.type, INITnointerpret);
e = iz.initializerToExpression();
+ sc2.pop();
}
if (e.op == EXP.function_) // https://issues.dlang.org/show_bug.cgi?id=4820
{
@@ -2553,6 +2819,31 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
}
}
+extern(C++) Type trySemantic(Type type, const ref Loc loc, Scope* sc)
+{
+ //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
+
+ // Needed to display any deprecations that were gagged
+ auto tcopy = type.syntaxCopy();
+
+ const errors = global.startGagging();
+ Type t = typeSemantic(type, loc, sc);
+ if (global.endGagging(errors) || t.ty == Terror) // if any errors happened
+ {
+ t = null;
+ }
+ else
+ {
+ // If `typeSemantic` succeeded, there may have been deprecations that
+ // were gagged due the `startGagging` above. Run again to display
+ // those deprecations. https://issues.dlang.org/show_bug.cgi?id=19107
+ if (global.gaggedWarnings > 0)
+ typeSemantic(tcopy, loc, sc);
+ }
+ //printf("-trySemantic(%s) %d\n", toChars(), global.errors);
+ return t;
+}
+
/************************************
* If an identical type to `type` is in `type.stringtable`, return
* the latter one. Otherwise, add it to `type.stringtable`.
@@ -5216,6 +5507,117 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
}
}
+/*
+If `type` resolves to a dsymbol, then that
+dsymbol is returned.
+
+Params:
+ type = the type that is checked
+ sc = the scope where the type is used
+
+Returns:
+ The dsymbol to which the type resolve or `null`
+ if the type does resolve to any symbol (for example,
+ in the case of basic types).
+*/
+extern(C++) Dsymbol toDsymbol(Type type, Scope* sc)
+{
+ Dsymbol visitType(Type _) { return null; }
+ Dsymbol visitStruct(TypeStruct type) { return type.sym; }
+ Dsymbol visitEnum(TypeEnum type) { return type.sym; }
+ Dsymbol visitClass(TypeClass type) { return type.sym; }
+
+ Dsymbol visitTraits(TypeTraits type)
+ {
+ Type t;
+ Expression e;
+ Dsymbol s;
+ resolve(type, type.loc, sc, e, t, s);
+ if (t && t.ty != Terror)
+ s = t.toDsymbol(sc);
+ else if (e)
+ s = getDsymbol(e);
+
+ return s;
+ }
+
+ Dsymbol visitMixin(TypeMixin type)
+ {
+ Type t;
+ Expression e;
+ Dsymbol s;
+ resolve(type, type.loc, sc, e, t, s);
+ if (t)
+ s = t.toDsymbol(sc);
+ else if (e)
+ s = getDsymbol(e);
+
+ return s;
+ }
+
+ Dsymbol visitIdentifier(TypeIdentifier type)
+ {
+ //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
+ if (!sc)
+ return null;
+
+ Type t;
+ Expression e;
+ Dsymbol s;
+ resolve(type, type.loc, sc, e, t, s);
+ if (t && t.ty != Tident)
+ s = t.toDsymbol(sc);
+ if (e)
+ s = getDsymbol(e);
+
+ return s;
+ }
+
+ Dsymbol visitInstance(TypeInstance type)
+ {
+ Type t;
+ Expression e;
+ Dsymbol s;
+ //printf("TypeInstance::semantic(%s)\n", toChars());
+ resolve(type, type.loc, sc, e, t, s);
+ if (t && t.ty != Tinstance)
+ s = t.toDsymbol(sc);
+ return s;
+ }
+
+ Dsymbol visitTypeof(TypeTypeof type)
+ {
+ //printf("TypeTypeof::toDsymbol('%s')\n", toChars());
+ Expression e;
+ Type t;
+ Dsymbol s;
+ resolve(type, type.loc, sc, e, t, s);
+ return s;
+ }
+
+ Dsymbol visitReturn(TypeReturn type)
+ {
+ Expression e;
+ Type t;
+ Dsymbol s;
+ resolve(type, type.loc, sc, e, t, s);
+ return s;
+ }
+
+ switch(type.ty)
+ {
+ default: return visitType(type);
+ case Ttraits: return visitTraits(type.isTypeTraits());
+ case Tmixin: return visitMixin(type.isTypeMixin());
+ case Tident: return visitIdentifier(type.isTypeIdentifier());
+ case Tinstance: return visitInstance(type.isTypeInstance());
+ case Ttypeof: return visitTypeof(type.isTypeTypeof());
+ case Treturn: return visitReturn(type.isTypeReturn());
+ case Tstruct: return visitStruct(type.isTypeStruct());
+ case Tenum: return visitEnum(type.isTypeEnum());
+ case Tclass: return visitClass(type.isTypeClass());
+ }
+}
/**********************************************
* Extract complex type from core.stdc.config
@@ -5541,6 +5943,144 @@ Lnotcovariant:
return Covariant.no;
}
+/************************************
+ * Take the specified storage class for p,
+ * and use the function signature to infer whether
+ * STC.scope_ and STC.return_ should be OR'd in.
+ * (This will not affect the name mangling.)
+ * Params:
+ * tf = TypeFunction to use to get the signature from
+ * tthis = type of `this` parameter, null if none
+ * p = parameter to this function
+ * outerVars = context variables p could escape into, if any
+ * indirect = is this for an indirect or virtual function call?
+ * Returns:
+ * storage class with STC.scope_ or STC.return_ OR'd in
+ */
+StorageClass parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarations* outerVars = null,
+ bool indirect = false)
+{
+ //printf("parameterStorageClass(p: %s)\n", p.toChars());
+ auto stc = p.storageClass;
+
+ // When the preview switch is enable, `in` parameters are `scope`
+ if (stc & STC.constscoperef)
+ return stc | STC.scope_;
+
+ if (stc & (STC.scope_ | STC.return_ | STC.lazy_) || tf.purity == PURE.impure)
+ return stc;
+
+ /* If haven't inferred the return type yet, can't infer storage classes
+ */
+ if (!tf.nextOf() || !tf.isnothrow())
+ return stc;
+
+ tf.purityLevel();
+
+ static bool mayHavePointers(Type t)
+ {
+ if (auto ts = t.isTypeStruct())
+ {
+ auto sym = ts.sym;
+ if (sym.members && !sym.determineFields() && sym.type != Type.terror)
+ // struct is forward referenced, so "may have" pointers
+ return true;
+ }
+ return t.hasPointers();
+ }
+
+ // See if p can escape via any of the other parameters
+ if (tf.purity == PURE.weak)
+ {
+ /*
+ * Indirect calls may escape p through a nested context
+ * See:
+ * https://issues.dlang.org/show_bug.cgi?id=24212
+ * https://issues.dlang.org/show_bug.cgi?id=24213
+ */
+ if (indirect)
+ return stc;
+
+ // Check escaping through parameters
+ foreach (i, fparam; tf.parameterList)
+ {
+ Type t = fparam.type;
+ if (!t)
+ continue;
+ t = t.baseElemOf(); // punch thru static arrays
+ if (t.isMutable() && t.hasPointers())
+ {
+ if (fparam.isReference() && fparam != p)
+ return stc;
+
+ if (t.ty == Tdelegate)
+ return stc; // could escape thru delegate
+
+ if (t.ty == Tclass)
+ return stc;
+
+ /* if t is a pointer to mutable pointer
+ */
+ if (auto tn = t.nextOf())
+ {
+ if (tn.isMutable() && mayHavePointers(tn))
+ return stc; // escape through pointers
+ }
+ }
+ }
+
+ // Check escaping through `this`
+ if (tthis && tthis.isMutable())
+ {
+ foreach (VarDeclaration v; isAggregate(tthis).fields)
+ {
+ if (v.hasPointers())
+ return stc;
+ }
+ }
+
+ // Check escaping through nested context
+ if (outerVars && tf.isMutable())
+ {
+ foreach (VarDeclaration v; *outerVars)
+ {
+ if (v.hasPointers())
+ return stc;
+ }
+ }
+ }
+
+ // Check escaping through return value
+ Type tret = tf.nextOf().toBasetype();
+ if (tf.isref || tret.hasPointers())
+ {
+ return stc | STC.scope_ | STC.return_ | STC.returnScope;
+ }
+ else
+ return stc | STC.scope_;
+}
+
+extern(C++) bool isBaseOf(Type tthis, Type t, int* poffset)
+{
+ auto tc = tthis.isTypeClass();
+ if (!tc)
+ return false;
+
+ if (!t || t.ty != Tclass)
+ return false;
+
+ ClassDeclaration cd = t.isTypeClass().sym;
+ if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete())
+ cd.dsymbolSemantic(null);
+ if (tc.sym.semanticRun < PASS.semanticdone && !tc.sym.isBaseInfoComplete())
+ tc.sym.dsymbolSemantic(null);
+
+ if (tc.sym.isBaseOf(cd, poffset))
+ return true;
+
+ return false;
+}
+
/******************************* Private *****************************************/
private: