aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2024-02-24 10:26:09 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2024-02-26 00:06:22 +0100
commit94687d17ba79cdb9fd01c87b2b40b63512471569 (patch)
treedb4abf352a61c392db2c4c512dc9a8c061541f22 /gcc/d
parent3f58f96a4e8255e222953f9856bcd6c25f7b33cd (diff)
downloadgcc-94687d17ba79cdb9fd01c87b2b40b63512471569.zip
gcc-94687d17ba79cdb9fd01c87b2b40b63512471569.tar.gz
gcc-94687d17ba79cdb9fd01c87b2b40b63512471569.tar.bz2
Merge dmd, druntime ceff48bf7d, phobos dcbfbd43a
D front-end changes: - Import latest fixes from dmd v2.107.1-rc.1. D runtime changes: - Import latest fixes from druntime v2.107.1-rc.1. Phobos changes: - Import latest fixes from phobos v2.107.1-rc.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd ceff48bf7d. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime ceff48bf7d. * libdruntime/Makefile.am (DRUNTIME_DSOURCES_FREEBSD): Add core/sys/freebsd/net/if_.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos dcbfbd43a.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/arrayop.d2
-rw-r--r--gcc/d/dmd/ast_node.h2
-rw-r--r--gcc/d/dmd/common/file.d89
-rw-r--r--gcc/d/dmd/common/smallbuffer.d30
-rw-r--r--gcc/d/dmd/cparse.d150
-rw-r--r--gcc/d/dmd/dimport.d109
-rw-r--r--gcc/d/dmd/dmodule.d32
-rw-r--r--gcc/d/dmd/dsymbolsem.d97
-rw-r--r--gcc/d/dmd/expression.d4
-rw-r--r--gcc/d/dmd/expression.h2
-rw-r--r--gcc/d/dmd/expressionsem.d97
-rw-r--r--gcc/d/dmd/func.d394
-rw-r--r--gcc/d/dmd/funcsem.d390
-rw-r--r--gcc/d/dmd/identifier.h2
-rw-r--r--gcc/d/dmd/importc.d7
-rw-r--r--gcc/d/dmd/mtype.d1
-rw-r--r--gcc/d/dmd/parse.d48
-rw-r--r--gcc/d/dmd/root/array.h3
-rw-r--r--gcc/d/dmd/root/bitarray.h1
-rw-r--r--gcc/d/dmd/rootobject.h (renamed from gcc/d/dmd/root/object.h)6
-rw-r--r--gcc/d/dmd/statementsem.d2
-rw-r--r--gcc/d/dmd/staticcond.d107
-rw-r--r--gcc/d/dmd/template.h2
24 files changed, 822 insertions, 757 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 021149a..f11c5fb 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-9471b25db9ed44d71e0e27956430c0c6a09c16db
+ceff48bf7db05503117f54fdc0cefcb89b711136
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/arrayop.d b/gcc/d/dmd/arrayop.d
index afe6054..af3875e 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -22,7 +22,7 @@ import dmd.dsymbol;
import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
-import dmd.func;
+import dmd.funcsem;
import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
diff --git a/gcc/d/dmd/ast_node.h b/gcc/d/dmd/ast_node.h
index a24218a..db8608e 100644
--- a/gcc/d/dmd/ast_node.h
+++ b/gcc/d/dmd/ast_node.h
@@ -10,7 +10,7 @@
#pragma once
-#include "root/object.h"
+#include "rootobject.h"
class Visitor;
diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d
index 8a28424..80677f6 100644
--- a/gcc/d/dmd/common/file.d
+++ b/gcc/d/dmd/common/file.d
@@ -16,24 +16,37 @@ module dmd.common.file;
import core.stdc.errno : errno;
import core.stdc.stdio : fprintf, remove, rename, stderr;
-import core.stdc.stdlib : exit;
-import core.stdc.string : strerror, strlen;
-import core.sys.windows.winbase;
-import core.sys.windows.winnt;
-import core.sys.posix.fcntl;
-import core.sys.posix.unistd;
+import core.stdc.stdlib;
+import core.stdc.string : strerror, strlen, memcpy;
import dmd.common.smallbuffer;
-nothrow:
-
version (Windows)
{
+ import core.sys.windows.winbase;
import core.sys.windows.winnls : CP_ACP;
+ import core.sys.windows.winnt;
+
+ enum CodePage = CP_ACP; // assume filenames encoded in system default Windows ANSI code page
+ enum invalidHandle = INVALID_HANDLE_VALUE;
+}
+else version (Posix)
+{
+ import core.sys.posix.fcntl;
+ import core.sys.posix.sys.mman;
+ import core.sys.posix.sys.stat;
+ import core.sys.posix.unistd;
+ import core.sys.posix.utime;
- // assume filenames encoded in system default Windows ANSI code page
- enum CodePage = CP_ACP;
+ enum invalidHandle = -1;
}
+else
+ static assert(0);
+
+
+
+
+nothrow:
/**
Encapsulated management of a memory-mapped file.
@@ -48,9 +61,6 @@ struct FileMapping(Datum)
static assert(__traits(isPOD, Datum) && Datum.sizeof == 1,
"Not tested with other data types yet. Add new types with care.");
- version(Posix) enum invalidHandle = -1;
- else version(Windows) enum invalidHandle = INVALID_HANDLE_VALUE;
-
// state {
/// Handle of underlying file
private auto handle = invalidHandle;
@@ -82,9 +92,6 @@ struct FileMapping(Datum)
{
version (Posix)
{
- import core.sys.posix.sys.mman;
- import core.sys.posix.fcntl : open, O_CREAT, O_RDONLY, O_RDWR, S_IRGRP, S_IROTH, S_IRUSR, S_IWUSR;
-
handle = open(filename, is(Datum == const) ? O_RDONLY : (O_CREAT | O_RDWR),
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
@@ -150,9 +157,6 @@ struct FileMapping(Datum)
// Save the name for later. Technically there's no need: on Linux one can use readlink on /proc/self/fd/NNN.
// On BSD and OSX one can use fcntl with F_GETPATH. On Windows one can use GetFileInformationByHandleEx.
// But just saving the name is simplest, fastest, and most portable...
- import core.stdc.string : strlen;
- import core.stdc.stdlib : malloc;
- import core.stdc.string : memcpy;
const totalNameLength = filename.strlen() + 1;
auto namex = cast(char*) malloc(totalNameLength);
if (!namex)
@@ -224,9 +228,6 @@ struct FileMapping(Datum)
fakePure({
version (Posix)
{
- import core.sys.posix.sys.mman : munmap;
- import core.sys.posix.unistd : close;
-
// Cannot call fprintf from inside a destructor, so exiting silently.
if (data.ptr && munmap(cast(void*) data.ptr, data.length) != 0)
@@ -234,7 +235,7 @@ struct FileMapping(Datum)
exit(1);
}
data = null;
- if (handle != invalidHandle && close(handle) != 0)
+ if (handle != invalidHandle && .close(handle) != 0)
{
exit(1);
}
@@ -303,7 +304,6 @@ struct FileMapping(Datum)
// In-memory resource freed, now get rid of the underlying temp file.
version(Posix)
{
- import core.sys.posix.unistd : unlink;
if (unlink(deleteme) != 0)
{
fprintf(stderr, "unlink(\"%s\") failed: %s\n", filename, strerror(errno));
@@ -312,7 +312,6 @@ struct FileMapping(Datum)
}
else version(Windows)
{
- import core.sys.windows.winbase;
if (deleteme[0 .. strlen(deleteme)].extendedPathThen!(p => DeleteFileW(p.ptr)) == 0)
{
fprintf(stderr, "DeleteFileW error %d\n", GetLastError());
@@ -361,9 +360,6 @@ struct FileMapping(Datum)
fakePure({
version(Posix)
{
- import core.sys.posix.unistd : ftruncate;
- import core.sys.posix.sys.mman;
-
if (data.length)
{
assert(data.ptr, "Corrupt memory mapping");
@@ -431,7 +427,6 @@ struct FileMapping(Datum)
// Fetch the name and then set it to `null` so it doesn't get deallocated
auto oldname = name;
- import core.stdc.stdlib;
scope(exit) free(cast(void*) oldname);
name = null;
close();
@@ -447,7 +442,6 @@ struct FileMapping(Datum)
}
else version(Windows)
{
- import core.sys.windows.winbase;
auto r = oldname[0 .. strlen(oldname)].extendedPathThen!(
p1 => filename[0 .. strlen(filename)].extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING))
);
@@ -527,8 +521,6 @@ bool touchFile(const char* namez)
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
- import core.stdc.string : strlen;
-
// get handle to file
HANDLE h = namez[0 .. namez.strlen()].extendedPathThen!(p => CreateFile(p.ptr,
FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE,
@@ -546,7 +538,6 @@ bool touchFile(const char* namez)
}
else version (Posix)
{
- import core.sys.posix.utime;
return utime(namez, null) == 0;
}
else
@@ -560,24 +551,28 @@ Params: fd = file handle
Returns: file size in bytes, or `ulong.max` on any error.
*/
version (Posix)
-private ulong fileSize(int fd)
{
- import core.sys.posix.sys.stat;
- stat_t buf;
- if (fstat(fd, &buf) == 0)
- return buf.st_size;
- return ulong.max;
+ private ulong fileSize(int fd)
+ {
+ stat_t buf;
+ if (fstat(fd, &buf) == 0)
+ return buf.st_size;
+ return ulong.max;
+ }
}
-
-/// Ditto
-version (Windows)
-private ulong fileSize(HANDLE fd)
+else version (Windows)
{
- ulong result;
- if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
- return result;
- return ulong.max;
+ /// Ditto
+ private ulong fileSize(HANDLE fd)
+ {
+ ulong result;
+ if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
+ return result;
+ return ulong.max;
+ }
}
+else
+ static assert(0);
/**
Runs a non-pure function or delegate as pure code. Use with caution.
diff --git a/gcc/d/dmd/common/smallbuffer.d b/gcc/d/dmd/common/smallbuffer.d
index c6aa7ab..608ecc8 100644
--- a/gcc/d/dmd/common/smallbuffer.d
+++ b/gcc/d/dmd/common/smallbuffer.d
@@ -107,28 +107,30 @@ unittest
}
/**
-(Windows only) Converts a narrow string to a wide string using `buffer` as strorage. Returns a slice managed by
-`buffer` containing the converted string. The terminating zero is not part of the returned slice,
-but is guaranteed to follow it.
+ * (Windows only) Converts a narrow string to a wide string using `buffer` as strorage.
+ * Params:
+ * narrow = string to be converted
+ * buffer = where to place the converted string
+ * Returns: a slice of `buffer` containing the converted string. A zero follows the slice.
*/
version(Windows) wchar[] toWStringz(scope const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow
{
- import core.sys.windows.winnls : MultiByteToWideChar;
- import dmd.common.file : CodePage;
-
if (narrow is null)
return null;
- size_t length;
- int i;
- while (1)
+ size_t charsToWchars(scope const(char)[] narrow, scope wchar[] buffer)
{
// https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar
- length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
- if (length < buffer.length)
- break;
- buffer.create(length + 1);
- assert(++i == 1); // ensure loop should only execute once or twice
+ import core.sys.windows.winnls : MultiByteToWideChar, CP_ACP;
+ return MultiByteToWideChar(CP_ACP, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length);
+ }
+
+ size_t length = charsToWchars(narrow, buffer[]);
+ if (length >= buffer.length) // not enough room in buffer[]
+ {
+ buffer.create(length + 1); // extend buffer length
+ length = charsToWchars(narrow, buffer[]); // try again
+ assert(length < buffer.length);
}
buffer[length] = 0;
return buffer[0 .. length];
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 536a212..e917d2c 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -1682,9 +1682,12 @@ final class CParser(AST) : Parser!AST
AST.ParameterList parameterList;
StorageClass stc = 0;
const loc = token.loc;
+ auto symbolsSave = symbols;
+ symbols = new AST.Dsymbols();
typedefTab.push(null);
auto fbody = cparseStatement(ParseStatementFlags.scope_);
typedefTab.pop(); // end of function scope
+ symbols = symbolsSave;
// Rewrite last ExpStatement (if there is one) as a ReturnStatement
auto ss = fbody.isScopeStatement();
@@ -1693,8 +1696,11 @@ final class CParser(AST) : Parser!AST
if (const len = (*cs.statements).length)
{
auto s = (*cs.statements)[len - 1];
- if (auto es = s.isExpStatement())
- (*cs.statements)[len - 1] = new AST.ReturnStatement(es.loc, es.exp);
+ if (s) // error recovery should be with ErrorStatement, not null
+ {
+ if (auto es = s.isExpStatement())
+ (*cs.statements)[len - 1] = new AST.ReturnStatement(es.loc, es.exp);
+ }
}
auto tf = new AST.TypeFunction(parameterList, null, LINK.d, stc);
@@ -5520,7 +5526,7 @@ final class CParser(AST) : Parser!AST
defines.writeByte('#');
defines.writestring(n.ident.toString());
skipToNextLine(defines);
- defines.writeByte('\n');
+ defines.writeByte(0); // each #define line is 0 terminated
return true;
}
else if (n.ident == Id.__pragma)
@@ -5840,7 +5846,8 @@ final class CParser(AST) : Parser!AST
const length = buf.length;
buf.writeByte(0);
auto slice = buf.peekChars()[0 .. length];
- resetDefineLines(slice); // reset lexer
+ auto scanlocSave = scanloc;
+ resetDefineLines(slice); // reset lexer
auto save = eSink;
auto eLatch = new ErrorSinkLatch();
eSink = eLatch;
@@ -5865,12 +5872,14 @@ final class CParser(AST) : Parser!AST
(*symbols)[*pd] = s;
return;
}
+ assert(symbols, "symbols is null");
defineTab[cast(void*)s.ident] = symbols.length;
symbols.push(s);
}
while (p < endp)
{
+ //printf("|%s|\n", p);
if (p[0 .. 7] == "#define")
{
p += 7;
@@ -5884,10 +5893,11 @@ final class CParser(AST) : Parser!AST
AST.Type t;
+ Lswitch:
switch (token.value)
{
- case TOK.endOfLine: // #define identifier
- nextDefineLine();
+ case TOK.endOfFile: // #define identifier
+ ++p;
continue;
case TOK.int32Literal:
@@ -5901,7 +5911,7 @@ final class CParser(AST) : Parser!AST
Linteger:
const intvalue = token.intvalue;
nextToken();
- if (token.value == TOK.endOfLine)
+ if (token.value == TOK.endOfFile)
{
/* Declare manifest constant:
* enum id = intvalue;
@@ -5909,7 +5919,7 @@ final class CParser(AST) : Parser!AST
AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t);
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addVar(v);
- nextDefineLine();
+ ++p;
continue;
}
break;
@@ -5924,7 +5934,7 @@ final class CParser(AST) : Parser!AST
Lfloat:
const floatvalue = token.floatvalue;
nextToken();
- if (token.value == TOK.endOfLine)
+ if (token.value == TOK.endOfFile)
{
/* Declare manifest constant:
* enum id = floatvalue;
@@ -5932,7 +5942,7 @@ final class CParser(AST) : Parser!AST
AST.Expression e = new AST.RealExp(scanloc, floatvalue, t);
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addVar(v);
- nextDefineLine();
+ ++p;
continue;
}
break;
@@ -5942,7 +5952,7 @@ final class CParser(AST) : Parser!AST
const len = token.len;
const postfix = token.postfix;
nextToken();
- if (token.value == TOK.endOfLine)
+ if (token.value == TOK.endOfFile)
{
/* Declare manifest constant:
* enum id = "string";
@@ -5950,19 +5960,20 @@ final class CParser(AST) : Parser!AST
AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix);
auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
addVar(v);
- nextDefineLine();
+ ++p;
continue;
}
break;
case TOK.leftParenthesis:
+ {
/* Look for:
* #define ID ( expression )
* and rewrite it to a template function:
* auto ID()() { return expression; }
*/
if (params)
- break; // no parameters
+ goto caseFunctionLike; // version with parameters
nextToken();
eLatch.sawErrors = false;
auto exp = cparseExpression();
@@ -5971,7 +5982,7 @@ final class CParser(AST) : Parser!AST
if (token.value != TOK.rightParenthesis)
break;
nextToken();
- if (token.value != TOK.endOfLine)
+ if (token.value != TOK.endOfFile)
break;
auto ret = new AST.ReturnStatement(exp.loc, exp);
auto parameterList = AST.ParameterList(new AST.Parameters(), VarArg.none, 0);
@@ -5985,26 +5996,115 @@ final class CParser(AST) : Parser!AST
AST.Expression constraint = null;
auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, constraint, decldefs, false);
addVar(tempdecl);
- nextDefineLine();
+ ++p;
continue;
+ }
+
+ caseFunctionLike:
+ {
+ /* Parse `( a, b ) expression`
+ * Create template function:
+ * auto id(__MP1, __MP2)(__MP1 a, __MP1 b) { return expression; }
+ */
+ //printf("functionlike %s\n", id.toChars());
+
+ // Capture the parameter list
+ VarArg varargs = VarArg.none;
+ auto parameters = new AST.Parameters();
+ nextToken(); // skip past `(`
+ Lwhile:
+ while (1)
+ {
+ if (token.value == TOK.rightParenthesis)
+ break;
+ if (token.value == TOK.dotDotDot)
+ {
+ static if (0) // variadic macros not supported yet
+ {
+ varargs = AST.VarArg.variadic; // C-style variadics
+ nextToken();
+ if (token.value == TOK.rightParenthesis)
+ break Lwhile;
+ }
+ break Lswitch;
+ }
+
+ if (token.value != TOK.identifier)
+ break Lswitch;
+ auto param = new AST.Parameter(token.loc, 0, null, token.ident, null, null);
+ parameters.push(param);
+ nextToken();
+ if (token.value == TOK.comma)
+ {
+ nextToken();
+ continue;
+ }
+ break;
+ }
+ if (token.value != TOK.rightParenthesis)
+ break;
+
+ //auto pstart = p;
+ nextToken();
+ auto parameterList = AST.ParameterList(parameters, varargs, 0);
+ /* Create a type for each parameter. Add it to the template parameter list,
+ * and the parameter list.
+ */
+ auto tpl = new AST.TemplateParameters();
+ foreach (param; (*parameters)[])
+ {
+ auto idtype = Identifier.generateId("__MP");
+ auto loc = param.loc;
+ auto tp = new AST.TemplateTypeParameter(loc, idtype, null, null);
+ tpl.push(tp);
+
+ auto at = new AST.TypeIdentifier(loc, idtype);
+ param.type = at;
+ }
+
+ eLatch.sawErrors = false;
+ auto exp = cparseExpression();
+
+ //printf("exp: %s tok: %s\n", exp.toChars(), Token.toChars(token.value));
+ //printf("parsed: '%.*s'\n", cast(int)(p - pstart), pstart);
+ assert(symbols);
+
+ if (eLatch.sawErrors) // parsing errors
+ break; // abandon this #define
+
+ if (token.value != TOK.endOfFile) // did not consume the entire line
+ break;
+
+ // Generate function
+ auto ret = new AST.ReturnStatement(exp.loc, exp);
+ StorageClass stc = STC.auto_;
+ auto tf = new AST.TypeFunction(parameterList, null, LINK.d, stc);
+ auto fd = new AST.FuncDeclaration(exp.loc, exp.loc, id, stc, tf, 0);
+ fd.fbody = ret;
+
+ // Wrap it in an eponymous template
+ AST.Dsymbols* decldefs = new AST.Dsymbols();
+ decldefs.push(fd);
+ auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, null, decldefs, false);
+ addVar(tempdecl);
+
+ ++p;
+ continue;
+ }
default:
break;
}
}
- skipToNextLine();
- }
- else
- {
- scan(&token);
- if (token.value != TOK.endOfLine)
- {
- skipToNextLine();
- }
}
- nextDefineLine();
+ // scan to end of line
+ while (*p)
+ ++p;
+ ++p; // advance to start of next line
+ scanloc.linnum = scanloc.linnum + 1;
}
+ scanloc = scanlocSave;
eSink = save;
defines = buf;
}
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index b083c03..2efdd31 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -12,21 +12,13 @@
module dmd.dimport;
import dmd.arraytypes;
-import dmd.astenums;
-import dmd.declaration;
import dmd.dmodule;
-import dmd.dscope;
import dmd.dsymbol;
-import dmd.dsymbolsem;
import dmd.errors;
-import dmd.expression;
-import dmd.globals;
import dmd.identifier;
import dmd.location;
-import dmd.mtype;
import dmd.visitor;
-import core.stdc.stdio;
/***********************************************************
*/
extern (C++) final class Import : Dsymbol
@@ -76,6 +68,8 @@ extern (C++) final class Import : Dsymbol
assert(id);
version (none)
{
+ import core.stdc.stdio;
+
printf("Import::Import(");
foreach (id; packages)
{
@@ -124,105 +118,6 @@ extern (C++) final class Import : Dsymbol
}
/*******************************
- * Load this module.
- * Returns:
- * true for errors, false for success
- */
- extern (D) bool load(Scope* sc)
- {
- //printf("Import::load('%s') %p\n", toPrettyChars(), this);
- // See if existing module
- const errors = global.errors;
- DsymbolTable dst = Package.resolve(packages, null, &pkg);
- version (none)
- {
- if (pkg && pkg.isModule())
- {
- .error(loc, "can only import from a module, not from a member of module `%s`. Did you mean `import %s : %s`?", pkg.toChars(), pkg.toPrettyChars(), id.toChars());
- mod = pkg.isModule(); // Error recovery - treat as import of that module
- return true;
- }
- }
- Dsymbol s = dst.lookup(id);
- if (s)
- {
- if (s.isModule())
- mod = cast(Module)s;
- else
- {
- if (s.isAliasDeclaration())
- {
- .error(loc, "%s `%s` conflicts with `%s`", s.kind(), s.toPrettyChars(), id.toChars());
- }
- else if (Package p = s.isPackage())
- {
- if (p.isPkgMod == PKG.unknown)
- {
- uint preverrors = global.errors;
- mod = Module.load(loc, packages, id);
- if (!mod)
- p.isPkgMod = PKG.package_;
- else
- {
- // mod is a package.d, or a normal module which conflicts with the package name.
- if (mod.isPackageFile)
- mod.tag = p.tag; // reuse the same package tag
- else
- {
- // show error if Module.load does not
- if (preverrors == global.errors)
- .error(loc, "%s `%s` from file %s conflicts with %s `%s`", mod.kind(), mod.toPrettyChars(), mod.srcfile.toChars, p.kind(), p.toPrettyChars());
- return true;
- }
- }
- }
- else
- {
- mod = p.isPackageMod();
- }
- if (!mod)
- {
- .error(loc, "can only import from a module, not from package `%s.%s`", p.toPrettyChars(), id.toChars());
- }
- }
- else if (pkg)
- {
- .error(loc, "can only import from a module, not from package `%s.%s`", pkg.toPrettyChars(), id.toChars());
- }
- else
- {
- .error(loc, "can only import from a module, not from package `%s`", id.toChars());
- }
- }
- }
- if (!mod)
- {
- // Load module
- mod = Module.load(loc, packages, id);
- if (mod)
- {
- // id may be different from mod.ident, if so then insert alias
- dst.insert(id, mod);
- }
- }
- if (mod && !mod.importedFrom)
- mod.importedFrom = sc ? sc._module.importedFrom : Module.rootModule;
- if (!pkg)
- {
- if (mod && mod.isPackageFile)
- {
- // one level depth package.d file (import pkg; ./pkg/package.d)
- // it's necessary to use the wrapping Package already created
- pkg = mod.pkg;
- }
- else
- pkg = mod;
- }
- //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
- return global.errors != errors;
- }
-
- /*******************************
* Mark the imported packages as accessible from the current
* scope. This access check is necessary when using FQN b/c
* we're using a single global package tree.
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 07d5077..a77e4f3 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -16,12 +16,14 @@ module dmd.dmodule;
import core.stdc.stdio;
import core.stdc.stdlib;
import core.stdc.string;
+
import dmd.aggregate;
import dmd.arraytypes;
import dmd.astcodegen;
import dmd.astenums;
+import dmd.common.outbuffer;
import dmd.compiler;
-import dmd.gluelayer;
+import dmd.cparse;
import dmd.dimport;
import dmd.dmacro;
import dmd.doc;
@@ -35,25 +37,37 @@ import dmd.expressionsem;
import dmd.file_manager;
import dmd.func;
import dmd.globals;
+import dmd.gluelayer;
import dmd.id;
import dmd.identifier;
import dmd.location;
import dmd.parse;
-import dmd.cparse;
import dmd.root.array;
import dmd.root.file;
import dmd.root.filename;
-import dmd.common.outbuffer;
import dmd.root.port;
import dmd.root.rmem;
-import dmd.rootobject;
import dmd.root.string;
+import dmd.rootobject;
import dmd.semantic2;
import dmd.semantic3;
import dmd.target;
import dmd.utils;
import dmd.visitor;
+version (Windows)
+{
+ import core.sys.windows.winbase : getpid = GetCurrentProcessId;
+ enum PathSeparator = '\\';
+}
+else version (Posix)
+{
+ import core.sys.posix.unistd : getpid;
+ enum PathSeparator = '/';
+}
+else
+ static assert(0);
+
version (IN_GCC) {}
else version (IN_LLVM) {}
else version = MARS;
@@ -141,11 +155,7 @@ private const(char)[] getFilename(Identifier[] packages, Identifier ident) nothr
buf.writestring(p);
if (modAliases.length)
checkModFileAlias(p);
- version (Windows)
- enum FileSeparator = '\\';
- else
- enum FileSeparator = '/';
- buf.writeByte(FileSeparator);
+ buf.writeByte(PathSeparator);
}
buf.writestring(filename);
if (modAliases.length)
@@ -558,10 +568,6 @@ extern (C++) final class Module : Package
OutBuffer buf;
if (arg == "__stdin.d")
{
- version (Posix)
- import core.sys.posix.unistd : getpid;
- else version (Windows)
- import core.sys.windows.winbase : getpid = GetCurrentProcessId;
buf.printf("__stdin_%d.d", getpid());
arg = buf[];
}
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index c15d925..bb0a1d6 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -6916,6 +6916,103 @@ extern(C++) class ImportAllVisitor : Visitor
override void visit(StaticForeachDeclaration _) {}
}
+/*******************************
+ * Load module.
+ * Returns:
+ * true for errors, false for success
+ */
+extern (D) bool load(Import imp, Scope* sc)
+{
+ // See if existing module
+ const errors = global.errors;
+ DsymbolTable dst = Package.resolve(imp.packages, null, &imp.pkg);
+ version (none)
+ {
+ if (pkg && pkg.isModule())
+ {
+ .error(loc, "can only import from a module, not from a member of module `%s`. Did you mean `import %s : %s`?", pkg.toChars(), pkg.toPrettyChars(), id.toChars());
+ mod = pkg.isModule(); // Error recovery - treat as import of that module
+ return true;
+ }
+ }
+ Dsymbol s = dst.lookup(imp.id);
+ if (s)
+ {
+ if (s.isModule())
+ imp.mod = cast(Module)s;
+ else
+ {
+ if (s.isAliasDeclaration())
+ {
+ .error(imp.loc, "%s `%s` conflicts with `%s`", s.kind(), s.toPrettyChars(), imp.id.toChars());
+ }
+ else if (Package p = s.isPackage())
+ {
+ if (p.isPkgMod == PKG.unknown)
+ {
+ uint preverrors = global.errors;
+ imp.mod = Module.load(imp.loc, imp.packages, imp.id);
+ if (!imp.mod)
+ p.isPkgMod = PKG.package_;
+ else
+ {
+ // imp.mod is a package.d, or a normal module which conflicts with the package name.
+ if (imp.mod.isPackageFile)
+ imp.mod.tag = p.tag; // reuse the same package tag
+ else
+ {
+ // show error if Module.load does not
+ if (preverrors == global.errors)
+ .error(imp.loc, "%s `%s` from file %s conflicts with %s `%s`", imp.mod.kind(), imp.mod.toPrettyChars(), imp.mod.srcfile.toChars, p.kind(), p.toPrettyChars());
+ return true;
+ }
+ }
+ }
+ else
+ {
+ imp.mod = p.isPackageMod();
+ }
+ if (!imp.mod)
+ {
+ .error(imp.loc, "can only import from a module, not from package `%s.%s`", p.toPrettyChars(), imp.id.toChars());
+ }
+ }
+ else if (imp.pkg)
+ {
+ .error(imp.loc, "can only import from a module, not from package `%s.%s`", imp.pkg.toPrettyChars(), imp.id.toChars());
+ }
+ else
+ {
+ .error(imp.loc, "can only import from a module, not from package `%s`", imp.id.toChars());
+ }
+ }
+ }
+ if (!imp.mod)
+ {
+ // Load module
+ imp.mod = Module.load(imp.loc, imp.packages, imp.id);
+ if (imp.mod)
+ {
+ // imp.id may be different from mod.ident, if so then insert alias
+ dst.insert(imp.id, imp.mod);
+ }
+ }
+ if (imp.mod && !imp.mod.importedFrom)
+ imp.mod.importedFrom = sc ? sc._module.importedFrom : Module.rootModule;
+ if (!imp.pkg)
+ {
+ if (imp.mod && imp.mod.isPackageFile)
+ {
+ // one level depth package.d file (import pkg; ./pkg/package.d)
+ // it's necessary to use the wrapping Package already created
+ imp.pkg = imp.mod.pkg;
+ }
+ else
+ imp.pkg = imp.mod;
+ }
+ return global.errors != errors;
+}
+
void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion)
{
scope v = new SetFieldOffsetVisitor(ad, fieldState, isunion);
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index bc907cf..479ad3a 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -314,6 +314,7 @@ extern (C++) abstract class Expression : ASTNode
Type type; // !=null means that semantic() has been run
Loc loc; // file location
const EXP op; // to minimize use of dynamic_cast
+ bool parens; // if this is a parenthesized expression
extern (D) this(const ref Loc loc, EXP op) scope @safe
{
@@ -1310,7 +1311,6 @@ extern (C++) final class ComplexExp : Expression
extern (C++) class IdentifierExp : Expression
{
Identifier ident;
- bool parens; // if it appears as (identifier)
extern (D) this(const ref Loc loc, Identifier ident) scope @safe
{
@@ -2432,8 +2432,6 @@ extern (C++) final class CompoundLiteralExp : Expression
*/
extern (C++) final class TypeExp : Expression
{
- bool parens; // if this is a parenthesized expression
-
extern (D) this(const ref Loc loc, Type type) @safe
{
super(loc, EXP.type);
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 3bd8ca7..9cd73a9 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -90,6 +90,7 @@ public:
Type *type; // !=NULL means that semantic() has been run
Loc loc; // file location
EXP op; // to minimize use of dynamic_cast
+ d_bool parens; // if this is a parenthesized expression
size_t size() const;
static void _init();
@@ -300,7 +301,6 @@ class IdentifierExp : public Expression
{
public:
Identifier *ident;
- d_bool parens;
static IdentifierExp *create(const Loc &loc, Identifier *ident);
bool isLvalue() override final;
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index cc589b9..b4d5274 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -16628,3 +16628,100 @@ Expression toBoolean(Expression exp, Scope* sc)
return e;
}
}
+
+/********************************************
+ * Semantically analyze and then evaluate a static condition at compile time.
+ * This is special because short circuit operators &&, || and ?: at the top
+ * level are not semantically analyzed if the result of the expression is not
+ * necessary.
+ * Params:
+ * sc = instantiating scope
+ * original = original expression, for error messages
+ * e = resulting expression
+ * errors = set to `true` if errors occurred
+ * negatives = array to store negative clauses
+ * Returns:
+ * true if evaluates to true
+ */
+bool evalStaticCondition(Scope* sc, Expression original, Expression e, out bool errors, Expressions* negatives = null)
+{
+ if (negatives)
+ negatives.setDim(0);
+
+ bool impl(Expression e)
+ {
+ if (e.isNotExp())
+ {
+ NotExp ne = cast(NotExp)e;
+ return !impl(ne.e1);
+ }
+
+ if (e.op == EXP.andAnd || e.op == EXP.orOr)
+ {
+ LogicalExp aae = cast(LogicalExp)e;
+ bool result = impl(aae.e1);
+ if (errors)
+ return false;
+ if (e.op == EXP.andAnd)
+ {
+ if (!result)
+ return false;
+ }
+ else
+ {
+ if (result)
+ return true;
+ }
+ result = impl(aae.e2);
+ return !errors && result;
+ }
+
+ if (e.op == EXP.question)
+ {
+ CondExp ce = cast(CondExp)e;
+ bool result = impl(ce.econd);
+ if (errors)
+ return false;
+ Expression leg = result ? ce.e1 : ce.e2;
+ result = impl(leg);
+ return !errors && result;
+ }
+
+ Expression before = e;
+ const uint nerrors = global.errors;
+
+ sc = sc.startCTFE();
+ sc.flags |= SCOPE.condition;
+
+ e = e.expressionSemantic(sc);
+ e = resolveProperties(sc, e);
+ e = e.toBoolean(sc);
+
+ sc = sc.endCTFE();
+ e = e.optimize(WANTvalue);
+
+ if (nerrors != global.errors ||
+ e.isErrorExp() ||
+ e.type.toBasetype() == Type.terror)
+ {
+ errors = true;
+ return false;
+ }
+
+ e = e.ctfeInterpret();
+
+ const opt = e.toBool();
+ if (opt.isEmpty())
+ {
+ if (!e.type.isTypeError())
+ error(e.loc, "expression `%s` is not constant", e.toChars());
+ errors = true;
+ return false;
+ }
+
+ if (negatives && !opt.get())
+ negatives.push(before);
+ return opt.get();
+ }
+ return impl(e);
+}
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 4881ad6..d890811 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -58,7 +58,6 @@ import dmd.semantic3;
import dmd.statement_rewrite_walker;
import dmd.statement;
import dmd.statementsem;
-import dmd.templatesem;
import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
@@ -2925,395 +2924,6 @@ unittest
assert(mismatches.isMutable);
}
-/// Flag used by $(LREF resolveFuncCall).
-enum FuncResolveFlag : ubyte
-{
- standard = 0, /// issue error messages, solve the call.
- quiet = 1, /// do not issue error message on no match, just return `null`.
- overloadOnly = 2, /// only resolve overloads, i.e. do not issue error on ambiguous
- /// matches and need explicit this.
- ufcs = 4, /// trying to resolve UFCS call
-}
-
-/*******************************************
- * Given a symbol that could be either a FuncDeclaration or
- * a function template, resolve it to a function symbol.
- * Params:
- * loc = instantiation location
- * sc = instantiation scope
- * s = instantiation symbol
- * tiargs = initial list of template arguments
- * tthis = if !NULL, the `this` argument type
- * argumentList = arguments to function
- * flags = see $(LREF FuncResolveFlag).
- * Returns:
- * if match is found, then function symbol, else null
- */
-FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
- Objects* tiargs, Type tthis, ArgumentList argumentList, FuncResolveFlag flags)
-{
- auto fargs = argumentList.arguments;
- if (!s)
- return null; // no match
-
- version (none)
- {
- printf("resolveFuncCall('%s')\n", s.toChars());
- if (tthis)
- printf("\tthis: %s\n", tthis.toChars());
- if (fargs)
- {
- for (size_t i = 0; i < fargs.length; i++)
- {
- Expression arg = (*fargs)[i];
- assert(arg.type);
- printf("\t%s: %s\n", arg.toChars(), arg.type.toChars());
- }
- }
- printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
- }
-
- if (tiargs && arrayObjectIsError(*tiargs))
- return null;
- if (fargs !is null)
- foreach (arg; *fargs)
- if (isError(arg))
- return null;
-
- MatchAccumulator m;
- functionResolve(m, s, loc, sc, tiargs, tthis, argumentList);
- auto orig_s = s;
-
- if (m.last > MATCH.nomatch && m.lastf)
- {
- if (m.count == 1) // exactly one match
- {
- if (!(flags & FuncResolveFlag.quiet))
- functionSemantic(m.lastf);
- return m.lastf;
- }
- if ((flags & FuncResolveFlag.overloadOnly) && !tthis && m.lastf.needThis())
- {
- return m.lastf;
- }
- }
-
- /* Failed to find a best match.
- * Do nothing or print error.
- */
- if (m.last == MATCH.nomatch)
- {
- // error was caused on matched function, not on the matching itself,
- // so return the function to produce a better diagnostic
- if (m.count == 1)
- return m.lastf;
- }
-
- // We are done at this point, as the rest of this function generate
- // a diagnostic on invalid match
- if (flags & FuncResolveFlag.quiet)
- return null;
-
- auto fd = s.isFuncDeclaration();
- auto od = s.isOverDeclaration();
- auto td = s.isTemplateDeclaration();
- if (td && td.funcroot)
- s = fd = td.funcroot;
-
- OutBuffer tiargsBuf;
- arrayObjectsToBuffer(tiargsBuf, tiargs);
-
- OutBuffer fargsBuf;
- fargsBuf.writeByte('(');
- argExpTypesToCBuffer(fargsBuf, fargs);
- fargsBuf.writeByte(')');
- if (tthis)
- tthis.modToBuffer(fargsBuf);
-
- // The call is ambiguous
- if (m.lastf && m.nextf)
- {
- TypeFunction tf1 = m.lastf.type.toTypeFunction();
- TypeFunction tf2 = m.nextf.type.toTypeFunction();
- const(char)* lastprms = parametersTypeToChars(tf1.parameterList);
- const(char)* nextprms = parametersTypeToChars(tf2.parameterList);
-
- .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`",
- s.parent.toPrettyChars(), s.ident.toChars(),
- fargsBuf.peekChars(),
- m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(),
- m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars());
- return null;
- }
-
- // no match, generate an error messages
- if (flags & FuncResolveFlag.ufcs)
- {
- auto arg = (*fargs)[0];
- .error(loc, "no property `%s` for `%s` of type `%s`", s.ident.toChars(), arg.toChars(), arg.type.toChars());
- .errorSupplemental(loc, "the following error occured while looking for a UFCS match");
- }
-
- if (!fd)
- {
- // all of overloads are templates
- if (td)
- {
- if (!od && !td.overnext)
- {
- .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`",
- td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
- }
- else
- {
- .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
- td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
- tiargsBuf.peekChars(), fargsBuf.peekChars());
- }
-
-
- if (!global.gag || global.params.v.showGaggedErrors)
- printCandidates(loc, td, sc.isDeprecated());
- return null;
- }
- /* This case used to happen when several ctors are mixed in an agregate.
- A (bad) error message is already generated in overloadApply().
- see https://issues.dlang.org/show_bug.cgi?id=19729
- and https://issues.dlang.org/show_bug.cgi?id=17259
- */
- if (!od)
- return null;
- }
-
- if (od)
- {
- .error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`",
- od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
- return null;
- }
-
- // remove when deprecation period of class allocators and deallocators is over
- if (fd.isNewDeclaration() && fd.checkDisabled(loc, sc))
- return null;
-
- bool hasOverloads = fd.overnext !is null;
- auto tf = fd.type.isTypeFunction();
- // if type is an error, the original type should be there for better diagnostics
- if (!tf)
- tf = fd.originalType.toTypeFunction();
-
- // modifier mismatch
- if (tthis && (fd.isCtorDeclaration() ?
- !MODimplicitConv(tf.mod, tthis.mod) :
- !MODimplicitConv(tthis.mod, tf.mod)))
- {
- OutBuffer thisBuf, funcBuf;
- MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
- auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
- if (hasOverloads)
- {
- OutBuffer buf;
- buf.argExpTypesToCBuffer(fargs);
- if (fd.isCtorDeclaration())
- .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`",
- fd.toChars(), thisBuf.peekChars(), buf.peekChars());
- else
- .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`",
- fd.toChars(), thisBuf.peekChars(), buf.peekChars());
-
- if (!global.gag || global.params.v.showGaggedErrors)
- printCandidates(loc, fd, sc.isDeprecated());
- return null;
- }
-
- 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);
- 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());
- else
- .error(loc, "%smethod `%s` is not callable using a %sobject",
- funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars());
-
- if (mismatches.isNotShared)
- .errorSupplemental(fd.loc, "Consider adding `shared` here");
- else if (mismatches.isMutable)
- .errorSupplemental(fd.loc, "Consider adding `const` or `inout` here");
- return null;
- }
-
- //printf("tf = %s, args = %s\n", tf.deco, (*fargs)[0].type.deco);
- if (hasOverloads)
- {
- .error(loc, "none of the overloads of `%s` are callable using argument types `%s`",
- fd.toChars(), fargsBuf.peekChars());
- if (!global.gag || global.params.v.showGaggedErrors)
- printCandidates(loc, fd, sc.isDeprecated());
- return null;
- }
-
- .error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
- fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
- tf.modToChars(), fargsBuf.peekChars());
-
- // re-resolve to check for supplemental message
- if (!global.gag || global.params.v.showGaggedErrors)
- {
- if (tthis)
- {
- if (auto classType = tthis.isTypeClass())
- {
- if (auto baseClass = classType.sym.baseClass)
- {
- if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident))
- {
- MatchAccumulator mErr;
- functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList);
- if (mErr.last > MATCH.nomatch && mErr.lastf)
- {
- errorSupplemental(loc, "%s `%s` hides base class function `%s`",
- fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
- errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
- fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
- return null;
- }
- }
- }
- }
- }
-
- void errorHelper2(const(char)* failMessage) scope
- {
- errorSupplemental(loc, failMessage);
- }
-
- functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper2);
- }
- return null;
-}
-
-/*******************************************
- * Prints template and function overload candidates as supplemental errors.
- * Params:
- * loc = instantiation location
- * declaration = the declaration to print overload candidates for
- * showDeprecated = If `false`, `deprecated` function won't be shown
- */
-private void printCandidates(Decl)(const ref Loc loc, Decl declaration, bool showDeprecated)
-if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
-{
- // max num of overloads to print (-v or -verror-supplements overrides this).
- const uint DisplayLimit = global.params.v.errorSupplementCount();
- const(char)* constraintsTip;
- // determine if the first candidate was printed
- int printed;
-
- bool matchSymbol(Dsymbol s, bool print, bool single_candidate = false)
- {
- if (auto fd = s.isFuncDeclaration())
- {
- // Don't print overloads which have errors.
- // Not that if the whole overload set has errors, we'll never reach
- // this point so there's no risk of printing no candidate
- if (fd.errors || fd.type.ty == Terror)
- return false;
- // Don't print disabled functions, or `deprecated` outside of deprecated scope
- if (fd.storage_class & STC.disable || (fd.isDeprecated() && !showDeprecated))
- return false;
- if (!print)
- return true;
- auto tf = cast(TypeFunction) fd.type;
- OutBuffer buf;
- buf.writestring(fd.toPrettyChars());
- buf.writestring(parametersTypeToChars(tf.parameterList));
- if (tf.mod)
- {
- buf.writeByte(' ');
- buf.MODtoBuffer(tf.mod);
- }
- .errorSupplemental(fd.loc,
- printed ? " `%s`" :
- single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars());
- }
- else if (auto td = s.isTemplateDeclaration())
- {
- import dmd.staticcond;
-
- if (!print)
- return true;
- OutBuffer buf;
- HdrGenState hgs;
- hgs.skipConstraints = true;
- toCharsMaybeConstraints(td, buf, hgs);
- const tmsg = buf.peekChars();
- const cmsg = td.getConstraintEvalError(constraintsTip);
-
- // add blank space if there are multiple candidates
- // the length of the blank space is `strlen("Candidates are: ")`
-
- if (cmsg)
- {
- .errorSupplemental(td.loc,
- printed ? " `%s`\n%s" :
- single_candidate ? "Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s",
- tmsg, cmsg);
- }
- else
- {
- .errorSupplemental(td.loc,
- printed ? " `%s`" :
- single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`",
- tmsg);
- }
- }
- return true;
- }
- // determine if there's > 1 candidate
- int count = 0;
- overloadApply(declaration, (s) {
- if (matchSymbol(s, false))
- count++;
- return count > 1;
- });
- int skipped = 0;
- overloadApply(declaration, (s) {
- if (global.params.v.verbose || printed < DisplayLimit)
- {
- if (matchSymbol(s, true, count == 1))
- printed++;
- }
- else
- {
- // Too many overloads to sensibly display.
- // Just show count of remaining overloads.
- if (matchSymbol(s, false))
- skipped++;
- }
- return 0;
- });
- if (skipped > 0)
- .errorSupplemental(loc, "... (%d more, -v to show) ...", skipped);
-
- // Nothing was displayed, all overloads are either disabled or deprecated
- if (!printed)
- .errorSupplemental(loc, "All possible candidates are marked as `deprecated` or `@disable`");
- // should be only in verbose mode
- if (constraintsTip)
- .tip(constraintsTip);
-}
-
/**************************************
* Returns an indirect type one step from t.
*/
@@ -4336,9 +3946,9 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)
return false;
if (sc.func.isSafeBypassingInference())
{
- if (!gag)
+ if (!gag && !sc.isDeprecated())
{
- warning(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
+ deprecation(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
}
}
else if (!sc.func.safetyViolation)
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
index 49da6b2..b8b185c 100644
--- a/gcc/d/dmd/funcsem.d
+++ b/gcc/d/dmd/funcsem.d
@@ -60,6 +60,7 @@ import dmd.statement_rewrite_walker;
import dmd.statement;
import dmd.statementsem;
import dmd.target;
+import dmd.templatesem;
import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
@@ -1365,3 +1366,392 @@ BaseClass* overrideInterface(FuncDeclaration fd)
}
return null;
}
+
+/// Flag used by $(LREF resolveFuncCall).
+enum FuncResolveFlag : ubyte
+{
+ standard = 0, /// issue error messages, solve the call.
+ quiet = 1, /// do not issue error message on no match, just return `null`.
+ overloadOnly = 2, /// only resolve overloads, i.e. do not issue error on ambiguous
+ /// matches and need explicit this.
+ ufcs = 4, /// trying to resolve UFCS call
+}
+
+/*******************************************
+ * Given a symbol that could be either a FuncDeclaration or
+ * a function template, resolve it to a function symbol.
+ * Params:
+ * loc = instantiation location
+ * sc = instantiation scope
+ * s = instantiation symbol
+ * tiargs = initial list of template arguments
+ * tthis = if !NULL, the `this` argument type
+ * argumentList = arguments to function
+ * flags = see $(LREF FuncResolveFlag).
+ * Returns:
+ * if match is found, then function symbol, else null
+ */
+FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
+ Objects* tiargs, Type tthis, ArgumentList argumentList, FuncResolveFlag flags)
+{
+ auto fargs = argumentList.arguments;
+ if (!s)
+ return null; // no match
+
+ version (none)
+ {
+ printf("resolveFuncCall('%s')\n", s.toChars());
+ if (tthis)
+ printf("\tthis: %s\n", tthis.toChars());
+ if (fargs)
+ {
+ for (size_t i = 0; i < fargs.length; i++)
+ {
+ Expression arg = (*fargs)[i];
+ assert(arg.type);
+ printf("\t%s: %s\n", arg.toChars(), arg.type.toChars());
+ }
+ }
+ printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
+ }
+
+ if (tiargs && arrayObjectIsError(*tiargs))
+ return null;
+ if (fargs !is null)
+ foreach (arg; *fargs)
+ if (isError(arg))
+ return null;
+
+ MatchAccumulator m;
+ functionResolve(m, s, loc, sc, tiargs, tthis, argumentList);
+ auto orig_s = s;
+
+ if (m.last > MATCH.nomatch && m.lastf)
+ {
+ if (m.count == 1) // exactly one match
+ {
+ if (!(flags & FuncResolveFlag.quiet))
+ functionSemantic(m.lastf);
+ return m.lastf;
+ }
+ if ((flags & FuncResolveFlag.overloadOnly) && !tthis && m.lastf.needThis())
+ {
+ return m.lastf;
+ }
+ }
+
+ /* Failed to find a best match.
+ * Do nothing or print error.
+ */
+ if (m.last == MATCH.nomatch)
+ {
+ // error was caused on matched function, not on the matching itself,
+ // so return the function to produce a better diagnostic
+ if (m.count == 1)
+ return m.lastf;
+ }
+
+ // We are done at this point, as the rest of this function generate
+ // a diagnostic on invalid match
+ if (flags & FuncResolveFlag.quiet)
+ return null;
+
+ auto fd = s.isFuncDeclaration();
+ auto od = s.isOverDeclaration();
+ auto td = s.isTemplateDeclaration();
+ if (td && td.funcroot)
+ s = fd = td.funcroot;
+
+ OutBuffer tiargsBuf;
+ arrayObjectsToBuffer(tiargsBuf, tiargs);
+
+ OutBuffer fargsBuf;
+ fargsBuf.writeByte('(');
+ argExpTypesToCBuffer(fargsBuf, fargs);
+ fargsBuf.writeByte(')');
+ if (tthis)
+ tthis.modToBuffer(fargsBuf);
+
+ // The call is ambiguous
+ if (m.lastf && m.nextf)
+ {
+ TypeFunction tf1 = m.lastf.type.toTypeFunction();
+ TypeFunction tf2 = m.nextf.type.toTypeFunction();
+ const(char)* lastprms = parametersTypeToChars(tf1.parameterList);
+ const(char)* nextprms = parametersTypeToChars(tf2.parameterList);
+
+ .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`",
+ s.parent.toPrettyChars(), s.ident.toChars(),
+ fargsBuf.peekChars(),
+ m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(),
+ m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars());
+ return null;
+ }
+
+ // no match, generate an error messages
+ if (flags & FuncResolveFlag.ufcs)
+ {
+ auto arg = (*fargs)[0];
+ .error(loc, "no property `%s` for `%s` of type `%s`", s.ident.toChars(), arg.toChars(), arg.type.toChars());
+ .errorSupplemental(loc, "the following error occured while looking for a UFCS match");
+ }
+
+ if (!fd)
+ {
+ // all of overloads are templates
+ if (td)
+ {
+ if (!od && !td.overnext)
+ {
+ .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`",
+ td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+ }
+ else
+ {
+ .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
+ td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
+ tiargsBuf.peekChars(), fargsBuf.peekChars());
+ }
+
+
+ if (!global.gag || global.params.v.showGaggedErrors)
+ printCandidates(loc, td, sc.isDeprecated());
+ return null;
+ }
+ /* This case used to happen when several ctors are mixed in an agregate.
+ A (bad) error message is already generated in overloadApply().
+ see https://issues.dlang.org/show_bug.cgi?id=19729
+ and https://issues.dlang.org/show_bug.cgi?id=17259
+ */
+ if (!od)
+ return null;
+ }
+
+ if (od)
+ {
+ .error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`",
+ od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+ return null;
+ }
+
+ // remove when deprecation period of class allocators and deallocators is over
+ if (fd.isNewDeclaration() && fd.checkDisabled(loc, sc))
+ return null;
+
+ bool hasOverloads = fd.overnext !is null;
+ auto tf = fd.type.isTypeFunction();
+ // if type is an error, the original type should be there for better diagnostics
+ if (!tf)
+ tf = fd.originalType.toTypeFunction();
+
+ // modifier mismatch
+ if (tthis && (fd.isCtorDeclaration() ?
+ !MODimplicitConv(tf.mod, tthis.mod) :
+ !MODimplicitConv(tthis.mod, tf.mod)))
+ {
+ OutBuffer thisBuf, funcBuf;
+ MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
+ auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
+ if (hasOverloads)
+ {
+ OutBuffer buf;
+ buf.argExpTypesToCBuffer(fargs);
+ if (fd.isCtorDeclaration())
+ .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`",
+ fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+ else
+ .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`",
+ fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+
+ if (!global.gag || global.params.v.showGaggedErrors)
+ printCandidates(loc, fd, sc.isDeprecated());
+ return null;
+ }
+
+ 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);
+ 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());
+ else
+ .error(loc, "%smethod `%s` is not callable using a %sobject",
+ funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars());
+
+ if (mismatches.isNotShared)
+ .errorSupplemental(fd.loc, "Consider adding `shared` here");
+ else if (mismatches.isMutable)
+ .errorSupplemental(fd.loc, "Consider adding `const` or `inout` here");
+ return null;
+ }
+
+ //printf("tf = %s, args = %s\n", tf.deco, (*fargs)[0].type.deco);
+ if (hasOverloads)
+ {
+ .error(loc, "none of the overloads of `%s` are callable using argument types `%s`",
+ fd.toChars(), fargsBuf.peekChars());
+ if (!global.gag || global.params.v.showGaggedErrors)
+ printCandidates(loc, fd, sc.isDeprecated());
+ return null;
+ }
+
+ .error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
+ fd.kind(), fd.toPrettyChars(), parametersTypeToChars(tf.parameterList),
+ tf.modToChars(), fargsBuf.peekChars());
+
+ // re-resolve to check for supplemental message
+ if (!global.gag || global.params.v.showGaggedErrors)
+ {
+ if (tthis)
+ {
+ if (auto classType = tthis.isTypeClass())
+ {
+ if (auto baseClass = classType.sym.baseClass)
+ {
+ if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident))
+ {
+ MatchAccumulator mErr;
+ functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList);
+ if (mErr.last > MATCH.nomatch && mErr.lastf)
+ {
+ errorSupplemental(loc, "%s `%s` hides base class function `%s`",
+ fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
+ errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
+ fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
+ return null;
+ }
+ }
+ }
+ }
+ }
+
+ void errorHelper2(const(char)* failMessage) scope
+ {
+ errorSupplemental(loc, failMessage);
+ }
+
+ functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &errorHelper2);
+ }
+ return null;
+}
+
+/*******************************************
+ * Prints template and function overload candidates as supplemental errors.
+ * Params:
+ * loc = instantiation location
+ * declaration = the declaration to print overload candidates for
+ * showDeprecated = If `false`, `deprecated` function won't be shown
+ */
+private void printCandidates(Decl)(const ref Loc loc, Decl declaration, bool showDeprecated)
+if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
+{
+ // max num of overloads to print (-v or -verror-supplements overrides this).
+ const uint DisplayLimit = global.params.v.errorSupplementCount();
+ const(char)* constraintsTip;
+ // determine if the first candidate was printed
+ int printed;
+
+ bool matchSymbol(Dsymbol s, bool print, bool single_candidate = false)
+ {
+ if (auto fd = s.isFuncDeclaration())
+ {
+ // Don't print overloads which have errors.
+ // Not that if the whole overload set has errors, we'll never reach
+ // this point so there's no risk of printing no candidate
+ if (fd.errors || fd.type.ty == Terror)
+ return false;
+ // Don't print disabled functions, or `deprecated` outside of deprecated scope
+ if (fd.storage_class & STC.disable || (fd.isDeprecated() && !showDeprecated))
+ return false;
+ if (!print)
+ return true;
+ auto tf = cast(TypeFunction) fd.type;
+ OutBuffer buf;
+ buf.writestring(fd.toPrettyChars());
+ buf.writestring(parametersTypeToChars(tf.parameterList));
+ if (tf.mod)
+ {
+ buf.writeByte(' ');
+ buf.MODtoBuffer(tf.mod);
+ }
+ .errorSupplemental(fd.loc,
+ printed ? " `%s`" :
+ single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars());
+ }
+ else if (auto td = s.isTemplateDeclaration())
+ {
+ import dmd.staticcond;
+
+ if (!print)
+ return true;
+ OutBuffer buf;
+ HdrGenState hgs;
+ hgs.skipConstraints = true;
+ toCharsMaybeConstraints(td, buf, hgs);
+ const tmsg = buf.peekChars();
+ const cmsg = td.getConstraintEvalError(constraintsTip);
+
+ // add blank space if there are multiple candidates
+ // the length of the blank space is `strlen("Candidates are: ")`
+
+ if (cmsg)
+ {
+ .errorSupplemental(td.loc,
+ printed ? " `%s`\n%s" :
+ single_candidate ? "Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s",
+ tmsg, cmsg);
+ }
+ else
+ {
+ .errorSupplemental(td.loc,
+ printed ? " `%s`" :
+ single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`",
+ tmsg);
+ }
+ }
+ return true;
+ }
+ // determine if there's > 1 candidate
+ int count = 0;
+ overloadApply(declaration, (s) {
+ if (matchSymbol(s, false))
+ count++;
+ return count > 1;
+ });
+ int skipped = 0;
+ overloadApply(declaration, (s) {
+ if (global.params.v.verbose || printed < DisplayLimit)
+ {
+ if (matchSymbol(s, true, count == 1))
+ printed++;
+ }
+ else
+ {
+ // Too many overloads to sensibly display.
+ // Just show count of remaining overloads.
+ if (matchSymbol(s, false))
+ skipped++;
+ }
+ return 0;
+ });
+ if (skipped > 0)
+ .errorSupplemental(loc, "... (%d more, -v to show) ...", skipped);
+
+ // Nothing was displayed, all overloads are either disabled or deprecated
+ if (!printed)
+ .errorSupplemental(loc, "All possible candidates are marked as `deprecated` or `@disable`");
+ // should be only in verbose mode
+ if (constraintsTip)
+ .tip(constraintsTip);
+}
diff --git a/gcc/d/dmd/identifier.h b/gcc/d/dmd/identifier.h
index afd3664..4f26801 100644
--- a/gcc/d/dmd/identifier.h
+++ b/gcc/d/dmd/identifier.h
@@ -11,7 +11,7 @@
#pragma once
#include "root/dcompat.h"
-#include "root/object.h"
+#include "rootobject.h"
class Identifier final : public RootObject
{
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index e4d5aa2..ece56c8d 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -243,16 +243,15 @@ Expression castCallAmbiguity(Expression e, Scope* sc)
case EXP.call:
auto ce = (*pe).isCallExp();
- auto ie = ce.e1.isIdentifierExp();
- if (ie && ie.parens)
+ if (ce.e1.parens)
{
- ce.e1 = expressionSemantic(ie, sc);
+ ce.e1 = expressionSemantic(ce.e1, sc);
if (ce.e1.op == EXP.type)
{
const numArgs = ce.arguments ? ce.arguments.length : 0;
if (numArgs >= 1)
{
- ie.parens = false;
+ ce.e1.parens = false;
Expression arg;
foreach (a; (*ce.arguments)[])
{
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 09ed630..843c402 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -30,7 +30,6 @@ import dmd.dtemplate;
import dmd.enumsem;
import dmd.errors;
import dmd.expression;
-import dmd.func;
import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 9c446eb..646c4b7 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -7130,7 +7130,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private void checkParens(TOK value, AST.Expression e)
{
- if (precedence[e.op] == PREC.rel)
+ if (precedence[e.op] == PREC.rel && !e.parens)
error(e.loc, "`%s` must be surrounded by parentheses when next to operator `%s`", e.toChars(), Token.toChars(value));
}
@@ -8550,6 +8550,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// ( expression )
nextToken();
e = parseExpression();
+ e.parens = true;
check(loc, TOK.rightParenthesis);
break;
}
@@ -8874,9 +8875,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
return AST.ErrorExp.get();
}
- auto te = new AST.TypeExp(loc, t);
- te.parens = true;
- e = parsePostExp(te);
+ e = new AST.TypeExp(loc, t);
+ e.parens = true;
+ e = parsePostExp(e);
}
else if (token.value == TOK.leftParenthesis ||
token.value == TOK.plusPlus || token.value == TOK.minusMinus)
@@ -9193,18 +9194,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseAndExp()
{
Loc loc = token.loc;
- bool parens = token.value == TOK.leftParenthesis;
auto e = parseCmpExp();
while (token.value == TOK.and)
{
- if (!parens)
- checkParens(TOK.and, e);
- parens = nextToken() == TOK.leftParenthesis;
+ checkParens(TOK.and, e);
+ nextToken();
auto e2 = parseCmpExp();
- if (!parens)
- checkParens(TOK.and, e2);
+ checkParens(TOK.and, e2);
e = new AST.AndExp(loc, e, e2);
- parens = true; // don't call checkParens() for And
loc = token.loc;
}
return e;
@@ -9212,42 +9209,32 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
private AST.Expression parseXorExp()
{
- Loc loc = token.loc;
+ const loc = token.loc;
- bool parens = token.value == TOK.leftParenthesis;
auto e = parseAndExp();
while (token.value == TOK.xor)
{
- if (!parens)
- checkParens(TOK.xor, e);
- parens = nextToken() == TOK.leftParenthesis;
+ checkParens(TOK.xor, e);
+ nextToken();
auto e2 = parseAndExp();
- if (!parens)
- checkParens(TOK.xor, e2);
+ checkParens(TOK.xor, e2);
e = new AST.XorExp(loc, e, e2);
- parens = true;
- loc = token.loc;
}
return e;
}
private AST.Expression parseOrExp()
{
- Loc loc = token.loc;
+ const loc = token.loc;
- bool parens = token.value == TOK.leftParenthesis;
auto e = parseXorExp();
while (token.value == TOK.or)
{
- if (!parens)
- checkParens(TOK.or, e);
- parens = nextToken() == TOK.leftParenthesis;
+ checkParens(TOK.or, e);
+ nextToken();
auto e2 = parseXorExp();
- if (!parens)
- checkParens(TOK.or, e2);
+ checkParens(TOK.or, e2);
e = new AST.OrExp(loc, e, e2);
- parens = true;
- loc = token.loc;
}
return e;
}
@@ -9298,7 +9285,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
AST.Expression parseAssignExp()
{
- bool parens = token.value == TOK.leftParenthesis;
AST.Expression e;
e = parseCondExp();
if (e is null)
@@ -9307,7 +9293,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
// require parens for e.g. `t ? a = 1 : b = 2`
void checkRequiredParens()
{
- if (e.op == EXP.question && !parens)
+ if (e.op == EXP.question && !e.parens)
eSink.error(e.loc, "`%s` must be surrounded by parentheses when next to operator `%s`",
e.toChars(), Token.toChars(token.value));
}
diff --git a/gcc/d/dmd/root/array.h b/gcc/d/dmd/root/array.h
index 1033b22..3e28804 100644
--- a/gcc/d/dmd/root/array.h
+++ b/gcc/d/dmd/root/array.h
@@ -9,7 +9,6 @@
#pragma once
#include "dsystem.h"
-#include "object.h"
#include "rmem.h"
template <typename TYPE>
@@ -44,7 +43,7 @@ struct Array
d_size_t len = 2;
for (d_size_t u = 0; u < length; u++)
{
- buf[u] = ((RootObject *)data.ptr[u])->toChars();
+ buf[u] = ((TYPE)data.ptr[u])->toChars();
len += strlen(buf[u]) + 1;
}
char *str = (char *)mem.xmalloc(len);
diff --git a/gcc/d/dmd/root/bitarray.h b/gcc/d/dmd/root/bitarray.h
index 2cd7152..2a82703 100644
--- a/gcc/d/dmd/root/bitarray.h
+++ b/gcc/d/dmd/root/bitarray.h
@@ -9,7 +9,6 @@
#pragma once
#include "dsystem.h"
-#include "object.h"
#include "rmem.h"
struct BitArray
diff --git a/gcc/d/dmd/root/object.h b/gcc/d/dmd/rootobject.h
index f56cb17..718a54f 100644
--- a/gcc/d/dmd/root/object.h
+++ b/gcc/d/dmd/rootobject.h
@@ -4,13 +4,13 @@
* https://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* https://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/object.h
+ * https://github.com/dlang/dmd/blob/master/src/dmd/rootobject.h
*/
#pragma once
-#include "dsystem.h"
-#include "dcompat.h"
+#include "root/dsystem.h"
+#include "root/dcompat.h"
typedef size_t hash_t;
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 5013c56..1bf36e3 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -1196,7 +1196,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
}
case Taarray:
if (fs.op == TOK.foreach_reverse_)
- warning(fs.loc, "cannot use `foreach_reverse` with an associative array");
+ error(fs.loc, "cannot use `foreach_reverse` with an associative array");
if (checkForArgTypes(fs))
return retError();
diff --git a/gcc/d/dmd/staticcond.d b/gcc/d/dmd/staticcond.d
index 72afe02..3ab6885 100644
--- a/gcc/d/dmd/staticcond.d
+++ b/gcc/d/dmd/staticcond.d
@@ -11,120 +11,13 @@
module dmd.staticcond;
-import dmd.arraytypes;
-import dmd.dinterpret;
-import dmd.dmodule;
-import dmd.dscope;
-import dmd.dsymbol;
-import dmd.errors;
import dmd.expression;
-import dmd.expressionsem;
-import dmd.globals;
-import dmd.identifier;
-import dmd.mtype;
-import dmd.optimize;
import dmd.root.array;
import dmd.common.outbuffer;
import dmd.tokens;
-/********************************************
- * Semantically analyze and then evaluate a static condition at compile time.
- * This is special because short circuit operators &&, || and ?: at the top
- * level are not semantically analyzed if the result of the expression is not
- * necessary.
- * Params:
- * sc = instantiating scope
- * original = original expression, for error messages
- * e = resulting expression
- * errors = set to `true` if errors occurred
- * negatives = array to store negative clauses
- * Returns:
- * true if evaluates to true
- */
-bool evalStaticCondition(Scope* sc, Expression original, Expression e, out bool errors, Expressions* negatives = null)
-{
- if (negatives)
- negatives.setDim(0);
-
- bool impl(Expression e)
- {
- if (e.isNotExp())
- {
- NotExp ne = cast(NotExp)e;
- return !impl(ne.e1);
- }
-
- if (e.op == EXP.andAnd || e.op == EXP.orOr)
- {
- LogicalExp aae = cast(LogicalExp)e;
- bool result = impl(aae.e1);
- if (errors)
- return false;
- if (e.op == EXP.andAnd)
- {
- if (!result)
- return false;
- }
- else
- {
- if (result)
- return true;
- }
- result = impl(aae.e2);
- return !errors && result;
- }
-
- if (e.op == EXP.question)
- {
- CondExp ce = cast(CondExp)e;
- bool result = impl(ce.econd);
- if (errors)
- return false;
- Expression leg = result ? ce.e1 : ce.e2;
- result = impl(leg);
- return !errors && result;
- }
-
- Expression before = e;
- const uint nerrors = global.errors;
-
- sc = sc.startCTFE();
- sc.flags |= SCOPE.condition;
-
- e = e.expressionSemantic(sc);
- e = resolveProperties(sc, e);
- e = e.toBoolean(sc);
-
- sc = sc.endCTFE();
- e = e.optimize(WANTvalue);
-
- if (nerrors != global.errors ||
- e.isErrorExp() ||
- e.type.toBasetype() == Type.terror)
- {
- errors = true;
- return false;
- }
-
- e = e.ctfeInterpret();
-
- const opt = e.toBool();
- if (opt.isEmpty())
- {
- if (!e.type.isTypeError())
- error(e.loc, "expression `%s` is not constant", e.toChars());
- errors = true;
- return false;
- }
-
- if (negatives && !opt.get())
- negatives.push(before);
- return opt.get();
- }
- return impl(e);
-}
/********************************************
* Format a static condition as a tree-like structure, marking failed and
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 6f12ac3..0f96a1b 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -36,7 +36,7 @@ public:
// kludge for template.isType()
DYNCAST dyncast() const override { return DYNCAST_TUPLE; }
- const char *toChars() const override { return objects.toChars(); }
+ const char *toChars() const override;
};
struct TemplatePrevious