aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/defines.c25
-rw-r--r--gcc/testsuite/gdc.test/compilable/testdefines.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/warn13679.d4
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/Makefile.am22
-rw-r--r--libphobos/libdruntime/Makefile.in31
-rw-r--r--libphobos/libdruntime/core/sys/freebsd/ifaddrs.d3
-rw-r--r--libphobos/libdruntime/core/sys/freebsd/net/if_.d493
-rw-r--r--libphobos/libdruntime/core/sys/linux/sys/socket.d1
-rw-r--r--libphobos/libdruntime/core/thread/fiber.d2
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/std/typecons.d35
36 files changed, 1417 insertions, 792 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
diff --git a/gcc/testsuite/gdc.test/compilable/imports/defines.c b/gcc/testsuite/gdc.test/compilable/imports/defines.c
index 8a5601a..6b0746f 100644
--- a/gcc/testsuite/gdc.test/compilable/imports/defines.c
+++ b/gcc/testsuite/gdc.test/compilable/imports/defines.c
@@ -30,3 +30,28 @@ _Static_assert(SSS[0] == 'h', "10");
#define ABC 12
#define GHI (size) abbadabba
#define DEF (ABC + 5)
+
+#define ADD(a, b) a + b
+#define SUB() 3 - 2
+
+#define NO_BODY()
+#define NO_BODY_PARAMS(a, b)
+#define DO_WHILE() do { } while(0)
+
+#define pr16199_trigger(cond,func,args) _Generic (cond, default: func args)
+#define pr16199_skipped1(a) (1)
+#define pr16199_skipped2(b) (2)
+#define pr16199_ice 0x3
+
+#define M16199Ea(TYPE) (TYPE __x;)
+#define M16199E(X,S,M) ({ M16199Ea(S *); })
+
+#define M16199Da(TYPE,VAR) ((TYPE)(VAR))
+#define M16199D(X,S,M) ({ int *__x = (X); M16199Da(S *, __x); })
+int pr16199d() { return 7; }
+
+#define M16199C(X,S,M) ({ int __x; })
+int pr16199c()
+{
+ return 8;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testdefines.d b/gcc/testsuite/gdc.test/compilable/testdefines.d
index 9dd8cf2..060e962 100644
--- a/gcc/testsuite/gdc.test/compilable/testdefines.d
+++ b/gcc/testsuite/gdc.test/compilable/testdefines.d
@@ -15,3 +15,13 @@ static assert(SSS == "hello");
static assert(ABC == 12);
static assert(DEF == 17);
+
+static assert(ADD(3, 4) == 7);
+static assert(SUB() == 1);
+
+static assert(pr16199_skipped1(5) == 1);
+static assert(pr16199_skipped2(6) == 2);
+static assert(pr16199_ice == 3);
+
+static assert(pr16199d() == 7);
+static assert(pr16199c() == 8);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/warn13679.d b/gcc/testsuite/gdc.test/fail_compilation/warn13679.d
index 74d4564..2291039 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/warn13679.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/warn13679.d
@@ -3,9 +3,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/warn13679.d(15): Warning: cannot use `foreach_reverse` with an associative array
-Error: warnings are treated as errors
- Use -wi if you wish to treat warnings only as informational.
+fail_compilation/warn13679.d(13): Error: cannot use `foreach_reverse` with an associative array
---
*/
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 021149a..f11c5fb 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/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/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index d2fb6e2..f17d8be 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -266,17 +266,17 @@ DRUNTIME_DSOURCES_ELF = core/sys/elf/package.d
DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/config.d \
core/sys/freebsd/dlfcn.d core/sys/freebsd/err.d \
core/sys/freebsd/execinfo.d core/sys/freebsd/ifaddrs.d \
- core/sys/freebsd/net/if_dl.d core/sys/freebsd/netinet/in_.d \
- core/sys/freebsd/pthread_np.d core/sys/freebsd/stdlib.d \
- core/sys/freebsd/string.d core/sys/freebsd/sys/_bitset.d \
- core/sys/freebsd/sys/_cpuset.d core/sys/freebsd/sys/cdefs.d \
- core/sys/freebsd/sys/elf.d core/sys/freebsd/sys/elf32.d \
- core/sys/freebsd/sys/elf64.d core/sys/freebsd/sys/elf_common.d \
- core/sys/freebsd/sys/event.d core/sys/freebsd/sys/link_elf.d \
- core/sys/freebsd/sys/mman.d core/sys/freebsd/sys/mount.d \
- core/sys/freebsd/sys/socket.d core/sys/freebsd/sys/sysctl.d \
- core/sys/freebsd/sys/types.d core/sys/freebsd/time.d \
- core/sys/freebsd/unistd.d
+ core/sys/freebsd/net/if_.d core/sys/freebsd/net/if_dl.d \
+ core/sys/freebsd/netinet/in_.d core/sys/freebsd/pthread_np.d \
+ core/sys/freebsd/stdlib.d core/sys/freebsd/string.d \
+ core/sys/freebsd/sys/_bitset.d core/sys/freebsd/sys/_cpuset.d \
+ core/sys/freebsd/sys/cdefs.d core/sys/freebsd/sys/elf.d \
+ core/sys/freebsd/sys/elf32.d core/sys/freebsd/sys/elf64.d \
+ core/sys/freebsd/sys/elf_common.d core/sys/freebsd/sys/event.d \
+ core/sys/freebsd/sys/link_elf.d core/sys/freebsd/sys/mman.d \
+ core/sys/freebsd/sys/mount.d core/sys/freebsd/sys/socket.d \
+ core/sys/freebsd/sys/sysctl.d core/sys/freebsd/sys/types.d \
+ core/sys/freebsd/time.d core/sys/freebsd/unistd.d
DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 3e3ab56..b6d9036 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -329,10 +329,10 @@ am__objects_11 = core/sys/bionic/err.lo core/sys/bionic/fcntl.lo \
@DRUNTIME_OS_ANDROID_TRUE@am__objects_12 = $(am__objects_11)
am__objects_13 = core/sys/freebsd/config.lo core/sys/freebsd/dlfcn.lo \
core/sys/freebsd/err.lo core/sys/freebsd/execinfo.lo \
- core/sys/freebsd/ifaddrs.lo core/sys/freebsd/net/if_dl.lo \
- core/sys/freebsd/netinet/in_.lo core/sys/freebsd/pthread_np.lo \
- core/sys/freebsd/stdlib.lo core/sys/freebsd/string.lo \
- core/sys/freebsd/sys/_bitset.lo \
+ core/sys/freebsd/ifaddrs.lo core/sys/freebsd/net/if_.lo \
+ core/sys/freebsd/net/if_dl.lo core/sys/freebsd/netinet/in_.lo \
+ core/sys/freebsd/pthread_np.lo core/sys/freebsd/stdlib.lo \
+ core/sys/freebsd/string.lo core/sys/freebsd/sys/_bitset.lo \
core/sys/freebsd/sys/_cpuset.lo core/sys/freebsd/sys/cdefs.lo \
core/sys/freebsd/sys/elf.lo core/sys/freebsd/sys/elf32.lo \
core/sys/freebsd/sys/elf64.lo \
@@ -943,17 +943,17 @@ DRUNTIME_DSOURCES_ELF = core/sys/elf/package.d
DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/config.d \
core/sys/freebsd/dlfcn.d core/sys/freebsd/err.d \
core/sys/freebsd/execinfo.d core/sys/freebsd/ifaddrs.d \
- core/sys/freebsd/net/if_dl.d core/sys/freebsd/netinet/in_.d \
- core/sys/freebsd/pthread_np.d core/sys/freebsd/stdlib.d \
- core/sys/freebsd/string.d core/sys/freebsd/sys/_bitset.d \
- core/sys/freebsd/sys/_cpuset.d core/sys/freebsd/sys/cdefs.d \
- core/sys/freebsd/sys/elf.d core/sys/freebsd/sys/elf32.d \
- core/sys/freebsd/sys/elf64.d core/sys/freebsd/sys/elf_common.d \
- core/sys/freebsd/sys/event.d core/sys/freebsd/sys/link_elf.d \
- core/sys/freebsd/sys/mman.d core/sys/freebsd/sys/mount.d \
- core/sys/freebsd/sys/socket.d core/sys/freebsd/sys/sysctl.d \
- core/sys/freebsd/sys/types.d core/sys/freebsd/time.d \
- core/sys/freebsd/unistd.d
+ core/sys/freebsd/net/if_.d core/sys/freebsd/net/if_dl.d \
+ core/sys/freebsd/netinet/in_.d core/sys/freebsd/pthread_np.d \
+ core/sys/freebsd/stdlib.d core/sys/freebsd/string.d \
+ core/sys/freebsd/sys/_bitset.d core/sys/freebsd/sys/_cpuset.d \
+ core/sys/freebsd/sys/cdefs.d core/sys/freebsd/sys/elf.d \
+ core/sys/freebsd/sys/elf32.d core/sys/freebsd/sys/elf64.d \
+ core/sys/freebsd/sys/elf_common.d core/sys/freebsd/sys/event.d \
+ core/sys/freebsd/sys/link_elf.d core/sys/freebsd/sys/mman.d \
+ core/sys/freebsd/sys/mount.d core/sys/freebsd/sys/socket.d \
+ core/sys/freebsd/sys/sysctl.d core/sys/freebsd/sys/types.d \
+ core/sys/freebsd/time.d core/sys/freebsd/unistd.d
DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \
@@ -1613,6 +1613,7 @@ core/sys/freebsd/ifaddrs.lo: core/sys/freebsd/$(am__dirstamp)
core/sys/freebsd/net/$(am__dirstamp):
@$(MKDIR_P) core/sys/freebsd/net
@: > core/sys/freebsd/net/$(am__dirstamp)
+core/sys/freebsd/net/if_.lo: core/sys/freebsd/net/$(am__dirstamp)
core/sys/freebsd/net/if_dl.lo: core/sys/freebsd/net/$(am__dirstamp)
core/sys/freebsd/netinet/$(am__dirstamp):
@$(MKDIR_P) core/sys/freebsd/netinet
diff --git a/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d b/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d
index aa39ac4..a08b8ed 100644
--- a/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d
+++ b/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d
@@ -3,7 +3,7 @@
/++
D header file for FreeBSD's ifaddrs.h.
- Copyright: Copyright 2023
+ Copyright: Copyright 2023 - 2024
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: $(HTTP jmdavisprog.com, Jonathan M Davis)
+/
@@ -23,6 +23,7 @@ struct ifaddrs
uint ifa_flags;
sockaddr* ifa_addr;
sockaddr* ifa_netmask;
+ alias ifa_broadaddr = ifa_dstaddr;
sockaddr* ifa_dstaddr;
void* ifa_data;
}
diff --git a/libphobos/libdruntime/core/sys/freebsd/net/if_.d b/libphobos/libdruntime/core/sys/freebsd/net/if_.d
new file mode 100644
index 0000000..e050f1b
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/freebsd/net/if_.d
@@ -0,0 +1,493 @@
+//Written in the D programming language
+
+/++
+ D header file for FreeBSD's net/if.h.
+
+ Copyright: Copyright 2024
+ License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ Authors: $(HTTP jmdavisprog.com, Jonathan M Davis)
+ +/
+module core.sys.freebsd.net.if_;
+
+public import core.sys.posix.net.if_;
+
+version (FreeBSD):
+extern(C):
+@nogc:
+nothrow:
+
+import core.stdc.config;
+import core.sys.freebsd.sys.types : caddr_t;
+import core.sys.posix.sys.socket : sockaddr;
+import core.sys.posix.sys.time : time_t, timeval;
+
+enum IF_MAXUNIT = 0x7fff;
+
+struct if_clonereq
+{
+ int ifcr_total;
+ int ifcr_count;
+ ubyte* ifcr_buffer;
+}
+
+struct if_data
+{
+ ubyte ifi_type;
+ ubyte ifi_physical;
+ ubyte ifi_addrlen;
+ ubyte ifi_hdrlen;
+ ubyte ifi_link_state;
+ ubyte ifi_vhid;
+ ushort ifi_datalen;
+ uint ifi_mtu;
+ uint ifi_metric;
+ ulong ifi_baudrate;
+
+ ulong ifi_ipackets;
+ ulong ifi_ierrors;
+ ulong ifi_opackets;
+ ulong ifi_oerrors;
+ ulong ifi_collisions;
+ ulong ifi_ibytes;
+ ulong ifi_obytes;
+ ulong ifi_imcasts;
+ ulong ifi_omcasts;
+ ulong ifi_iqdrops;
+ ulong ifi_oqdrops;
+ ulong ifi_noproto;
+ ulong ifi_hwassist;
+
+ union
+ {
+ time_t ifi_epoch;
+ private ulong ph;
+ }
+
+ union
+ {
+ timeval ifi_lastchange;
+ struct
+ {
+ private ulong ph1;
+ private ulong ph2;
+ }
+ }
+}
+
+enum IFF_UP = 0x1;
+enum IFF_BROADCAST = 0x2;
+enum IFF_DEBUG = 0x4;
+enum IFF_LOOPBACK = 0x8;
+enum IFF_POINTOPOINT = 0x10;
+enum IFF_NEEDSEPOCH = 0x20;
+enum IFF_DRV_RUNNING = 0x40;
+enum IFF_NOARP = 0x80;
+enum IFF_PROMISC = 0x100;
+enum IFF_ALLMULTI = 0x200;
+enum IFF_DRV_OACTIVE = 0x400;
+enum IFF_SIMPLEX = 0x800;
+enum IFF_LINK0 = 0x1000;
+enum IFF_LINK1 = 0x2000;
+enum IFF_LINK2 = 0x4000;
+enum IFF_ALTPHYS = IFF_LINK2;
+enum IFF_MULTICAST = 0x8000;
+enum IFF_CANTCONFIG = 0x10000;
+enum IFF_PPROMISC = 0x20000;
+enum IFF_MONITOR = 0x40000;
+enum IFF_STATICARP = 0x80000;
+enum IFF_STICKYARP = 0x100000;
+enum IFF_DYING = 0x200000;
+enum IFF_RENAMING = 0x400000;
+enum IFF_SPARE = 0x800000;
+enum IFF_NETLINK_1 = 0x1000000;
+
+enum IFF_RUNNING = IFF_DRV_RUNNING;
+enum IFF_OACTIVE = IFF_DRV_OACTIVE;
+
+enum IFF_CANTCHANGE = IFF_BROADCAST |
+ IFF_POINTOPOINT |
+ IFF_DRV_RUNNING |
+ IFF_DRV_OACTIVE |
+ IFF_SIMPLEX |
+ IFF_MULTICAST |
+ IFF_ALLMULTI |
+ IFF_PROMISC |
+ IFF_DYING |
+ IFF_CANTCONFIG |
+ IFF_NEEDSEPOCH;
+
+enum LINK_STATE_UNKNOWN = 0;
+enum LINK_STATE_DOWN = 1;
+enum LINK_STATE_UP = 2;
+
+auto IF_Kbps(T)(T x) { return uintmax_t(x) * 1000; }
+auto IF_Mbps(T)(T x) { return IF_Kbps(x * 1000); }
+auto IF_Gbps(T)(T x) { return IF_Mbps(x * 1000); }
+
+enum IFCAP_B_RXCSUM = 0;
+enum IFCAP_B_TXCSUM = 1;
+enum IFCAP_B_NETCONS = 2;
+enum IFCAP_B_VLAN_MTU = 3;
+enum IFCAP_B_VLAN_HWTAGGING = 4;
+enum IFCAP_B_JUMBO_MTU = 5;
+enum IFCAP_B_POLLING = 6;
+enum IFCAP_B_VLAN_HWCSUM = 7;
+enum IFCAP_B_TSO4 = 8;
+enum IFCAP_B_TSO6 = 9;
+enum IFCAP_B_LRO = 10;
+enum IFCAP_B_WOL_UCAST = 11;
+enum IFCAP_B_WOL_MCAST = 12;
+enum IFCAP_B_WOL_MAGIC = 13;
+enum IFCAP_B_TOE4 = 14;
+enum IFCAP_B_TOE6 = 15;
+enum IFCAP_B_VLAN_HWFILTER = 16;
+enum IFCAP_B_NV = 17;
+enum IFCAP_B_VLAN_HWTSO = 18;
+enum IFCAP_B_LINKSTATE = 19;
+enum IFCAP_B_NETMAP = 20;
+enum IFCAP_B_RXCSUM_IPV6 = 21;
+enum IFCAP_B_TXCSUM_IPV6 = 22;
+enum IFCAP_B_HWSTATS = 23;
+enum IFCAP_B_TXRTLMT = 24;
+enum IFCAP_B_HWRXTSTMP = 25;
+enum IFCAP_B_MEXTPG = 26;
+enum IFCAP_B_TXTLS4 = 27;
+enum IFCAP_B_TXTLS6 = 28;
+enum IFCAP_B_VXLAN_HWCSUM = 29;
+enum IFCAP_B_VXLAN_HWTSO = 30;
+enum IFCAP_B_TXTLS_RTLMT = 31;
+enum IFCAP_B_RXTLS4 = 32;
+enum IFCAP_B_RXTLS6 = 33;
+enum __IFCAP_B_SIZE = 34;
+
+// IFCAP_B_MAX is defined in net/if.h, but __IFCAP_B_MAX doesn't seem to be defined anywhere.
+// enum IFCAP_B_MAX = __IFCAP_B_MAX - 1;
+enum IFCAP_B_SIZE = __IFCAP_B_SIZE;
+
+auto IFCAP_BIT(T)(T x) { return 1 << x; }
+
+enum IFCAP_RXCSUM = IFCAP_BIT(IFCAP_B_RXCSUM);
+enum IFCAP_TXCSUM = IFCAP_BIT(IFCAP_B_TXCSUM);
+enum IFCAP_NETCONS = IFCAP_BIT(IFCAP_B_NETCONS);
+enum IFCAP_VLAN_MTU = IFCAP_BIT(IFCAP_B_VLAN_MTU);
+enum IFCAP_VLAN_HWTAGGING = IFCAP_BIT(IFCAP_B_VLAN_HWTAGGING);
+enum IFCAP_JUMBO_MTU = IFCAP_BIT(IFCAP_B_JUMBO_MTU);
+enum IFCAP_POLLING = IFCAP_BIT(IFCAP_B_POLLING);
+enum IFCAP_VLAN_HWCSUM = IFCAP_BIT(IFCAP_B_VLAN_HWCSUM);
+enum IFCAP_TSO4 = IFCAP_BIT(IFCAP_B_TSO4);
+enum IFCAP_TSO6 = IFCAP_BIT(IFCAP_B_TSO6);
+enum IFCAP_LRO = IFCAP_BIT(IFCAP_B_LRO);
+enum IFCAP_WOL_UCAST = IFCAP_BIT(IFCAP_B_WOL_UCAST);
+enum IFCAP_WOL_MCAST = IFCAP_BIT(IFCAP_B_WOL_MCAST);
+enum IFCAP_WOL_MAGIC = IFCAP_BIT(IFCAP_B_WOL_MAGIC);
+enum IFCAP_TOE4 = IFCAP_BIT(IFCAP_B_TOE4);
+enum IFCAP_TOE6 = IFCAP_BIT(IFCAP_B_TOE6);
+enum IFCAP_VLAN_HWFILTER = IFCAP_BIT(IFCAP_B_VLAN_HWFILTER);
+enum IFCAP_NV = IFCAP_BIT(IFCAP_B_NV);
+enum IFCAP_VLAN_HWTSO = IFCAP_BIT(IFCAP_B_VLAN_HWTSO);
+enum IFCAP_LINKSTATE = IFCAP_BIT(IFCAP_B_LINKSTATE);
+enum IFCAP_NETMAP = IFCAP_BIT(IFCAP_B_NETMAP);
+enum IFCAP_RXCSUM_IPV6 = IFCAP_BIT(IFCAP_B_RXCSUM_IPV6);
+enum IFCAP_TXCSUM_IPV6 = IFCAP_BIT(IFCAP_B_TXCSUM_IPV6);
+enum IFCAP_HWSTATS = IFCAP_BIT(IFCAP_B_HWSTATS);
+enum IFCAP_TXRTLMT = IFCAP_BIT(IFCAP_B_TXRTLMT);
+enum IFCAP_HWRXTSTMP = IFCAP_BIT(IFCAP_B_HWRXTSTMP);
+enum IFCAP_MEXTPG = IFCAP_BIT(IFCAP_B_MEXTPG);
+enum IFCAP_TXTLS4 = IFCAP_BIT(IFCAP_B_TXTLS4);
+enum IFCAP_TXTLS6 = IFCAP_BIT(IFCAP_B_TXTLS6);
+enum IFCAP_VXLAN_HWCSUM = IFCAP_BIT(IFCAP_B_VXLAN_HWCSUM);
+enum IFCAP_VXLAN_HWTSO = IFCAP_BIT(IFCAP_B_VXLAN_HWTSO);
+enum IFCAP_TXTLS_RTLMT = IFCAP_BIT(IFCAP_B_TXTLS_RTLMT);
+
+enum IFCAP2_RXTLS4 = IFCAP_B_RXTLS4 - 32;
+enum IFCAP2_RXTLS6 = IFCAP_B_RXTLS6 - 32;
+
+auto IFCAP2_BIT(T)(T x) { return 1UL << x; }
+
+enum IFCAP_HWCSUM_IPV6 = IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6;
+
+enum IFCAP_HWCSUM = IFCAP_RXCSUM | IFCAP_TXCSUM;
+enum IFCAP_TSO = IFCAP_TSO4 | IFCAP_TSO6;
+enum IFCAP_WOL = IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC;
+enum IFCAP_TOE = IFCAP_TOE4 | IFCAP_TOE6;
+enum IFCAP_TXTLS = IFCAP_TXTLS4 | IFCAP_TXTLS6;
+
+enum IFCAP_CANTCHANGE = IFCAP_NETMAP | IFCAP_NV;
+enum IFCAP_ALLCAPS = 0xffffffff;
+
+enum IFQ_MAXLEN = 50;
+enum IFNET_SLOWHZ = 1;
+
+struct if_msghdr
+{
+ ushort ifm_msglen;
+ ubyte ifm_version;
+ ubyte ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ ushort ifm_index;
+ ushort _ifm_spare1;
+ if_data ifm_data;
+}
+
+auto IF_MSGHDRL_IFM_DATA(T)(T _l) { return cast(if_data*) (cast(ubyte*) _l + _l.ifm_data_off); }
+
+auto IF_MSGHDRL_RTA(T)(T_l) { return cast(void*) (cast(uintptr_t) _l + _l.ifm_len); }
+
+struct if_msghdrl
+{
+ ushort ifm_msglen;
+ ubyte ifm_version;
+ ubyte ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ ushort ifm_index;
+ ushort _ifm_spare1;
+ ushort ifm_len;
+ ushort ifm_data_off;
+ int _ifm_spare2;
+ if_data ifm_data;
+}
+
+struct ifa_msghdr
+{
+ ushort ifam_msglen;
+ ubyte ifam_version;
+ ubyte ifam_type;
+ int ifam_addrs;
+ int ifam_flags;
+ ushort ifam_index;
+ ushort _ifam_spare1;
+ int ifam_metric;
+}
+
+auto IFA_MSGHDRL_IFAM_DATA(T)(T _l) { return cast(if_data*) (cast(ubyte*) _l + _l.ifam_data_off); }
+
+auto IFA_MSGHDRL_RTA(T)(T _l) { return cast(void*) (cast(uintptr_t) _l + _l.ifam_len); }
+
+struct ifa_msghdrl
+{
+ ushort ifam_msglen;
+ ubyte ifam_version;
+ ubyte ifam_type;
+ int ifam_addrs;
+ int ifam_flags;
+ ushort ifam_index;
+ ushort _ifam_spare1;
+ ushort ifam_len;
+ ushort ifam_data_off;
+ int ifam_metric;
+ if_data ifam_data;
+}
+
+struct ifma_msghdr
+{
+ ushort ifmam_msglen;
+ ubyte ifmam_version;
+ ubyte ifmam_type;
+ int ifmam_addrs;
+ int ifmam_flags;
+ ushort ifmam_index;
+ ushort _ifmam_spare1;
+}
+
+struct if_announcemsghdr
+{
+ ushort ifan_msglen;
+ ubyte ifan_version;
+ ubyte ifan_type;
+ ushort ifan_index;
+ char[IF_NAMESIZE] ifan_name;
+ ushort ifan_what;
+}
+
+enum IFAN_ARRIVAL = 0;
+enum IFAN_DEPARTURE = 1;
+
+struct ifreq_buffer
+{
+ size_t length;
+ void* buffer;
+}
+
+struct ifreq_nv_req
+{
+ uint buf_length;
+ uint length;
+ void* buffer;
+}
+
+enum IFR_CAP_NV_MAXBUFSIZE = 2 * 1024 * 1024;
+
+struct ifreq
+{
+ char[IF_NAMESIZE] ifr_name;
+
+ union
+ {
+ sockaddr ifr_addr;
+ sockaddr ifr_dstaddr;
+ sockaddr ifr_broadaddr;
+ ifreq_buffer ifr_buffer;
+ private short[2] ifru_flags;
+ short ifr_index;
+ int ifr_jid;
+ int ifr_metric;
+ int ifr_mtu;
+ int ifr_phys;
+ int ifr_media;
+ caddr_t ifr_data;
+ private int[2] ifru_cap;
+ uint ifr_fib;
+ ubyte ifr_vlan_pcp;
+ ifreq_nv_req ifr_cap_nv;
+ }
+
+ @property ref ifr_flags() { return ifru_flags[0]; }
+ @property ref ifr_flagshigh() { return ifru_flags[1]; }
+ @property ref ifr_reqcap() { return ifru_cap[0]; }
+ @property ref ifr_curcap() { return ifru_cap[1]; }
+ alias ifr_lan_pcp = ifr_vlan_pcp;
+}
+
+auto _SIZEOF_ADDR_IFREQ(T)(T ifr) { return ifr.ifr_addr.sa_len > sockaddr.sizeof ?
+ ifreq.sizeof - sockaddr.sizeof + ifr.ifr_addr.sa_len :
+ ifreq.sizeof; }
+
+struct ifaliasreq
+{
+ char[IF_NAMESIZE] ifra_name;
+ sockaddr ifra_addr;
+ sockaddr ifra_broadaddr;
+ sockaddr ifra_mask;
+ int ifra_vhid;
+}
+
+struct oifaliasreq
+{
+ char[IF_NAMESIZE] ifra_name;
+ sockaddr ifra_addr;
+ sockaddr ifra_broadaddr;
+ sockaddr ifra_mask;
+ }
+
+struct ifmediareq
+{
+ char[IF_NAMESIZE] ifm_name;
+ int ifm_current;
+ int ifm_mask;
+ int ifm_status;
+ int ifm_active;
+ int ifm_count;
+ int* ifm_ulist;
+}
+
+struct ifdrv
+{
+ char[IF_NAMESIZE] ifd_name;
+ c_ulong ifd_cmd;
+ size_t ifd_len;
+ void* ifd_data;
+}
+
+enum IFSTATMAX = 800;
+struct ifstat
+{
+ char[IF_NAMESIZE] ifs_name;
+ char[IFSTATMAX + 1] ascii;
+}
+
+struct ifconf
+{
+ int ifc_len;
+ union
+ {
+ caddr_t ifc_buf;
+ ifreq* ifc_req;
+ }
+}
+
+enum IFG_ALL = "all";
+enum IFG_EGRESS = "egress";
+
+struct ifg_req
+{
+ union
+ {
+ char[IF_NAMESIZE] ifgrq_group;
+ char[IF_NAMESIZE] ifgrq_member;
+ }
+}
+
+struct ifgroupreq
+{
+ char[IF_NAMESIZE] ifgr_name;
+ uint ifgr_len;
+ union
+ {
+ char[IF_NAMESIZE] ifgr_group;
+ ifg_req* ifgr_groups;
+ }
+}
+
+struct ifi2creq
+{
+ ubyte dev_addr;
+ ubyte offset;
+ ubyte len;
+ ubyte spare0;
+ uint spare1;
+ ubyte[8] data;
+}
+
+enum RSS_FUNC_NONE = 0;
+enum RSS_FUNC_PRIVATE = 1;
+enum RSS_FUNC_TOEPLITZ = 2;
+
+enum RSS_TYPE_IPV4 = 0x00000001;
+enum RSS_TYPE_TCP_IPV4 = 0x00000002;
+enum RSS_TYPE_IPV6 = 0x00000004;
+enum RSS_TYPE_IPV6_EX = 0x00000008;
+enum RSS_TYPE_TCP_IPV6 = 0x00000010;
+enum RSS_TYPE_TCP_IPV6_EX = 0x00000020;
+enum RSS_TYPE_UDP_IPV4 = 0x00000040;
+enum RSS_TYPE_UDP_IPV6 = 0x00000080;
+enum RSS_TYPE_UDP_IPV6_EX = 0x00000100;
+
+enum RSS_KEYLEN = 128;
+
+struct ifrsskey
+{
+ char[IF_NAMESIZE] ifrk_name;
+ ubyte ifrk_func;
+ ubyte ifrk_spare0;
+ ushort ifrk_keylen;
+ ubyte[RSS_KEYLEN] ifrk_key;
+}
+
+struct ifrsshash
+{
+ char[IF_NAMESIZE] ifrh_name;
+ ubyte ifrh_func;
+ ubyte ifrh_spare0;
+ ushort ifrh_spare1;
+ uint ifrh_types;
+}
+
+enum IFNET_PCP_NONE = 0xff;
+
+enum IFDR_MSG_SIZE = 64;
+enum IFDR_REASON_MSG = 1;
+enum IFDR_REASON_VENDOR = 2;
+
+struct ifdownreason
+{
+ char[IF_NAMESIZE] ifdr_name;
+ uint ifdr_reason;
+ uint ifdr_vendor;
+ char[IFDR_MSG_SIZE] ifdr_msg;
+}
+
+// FIXME It's not clear where ifnet is supposed to be coming from, so this is
+// commented out for now.
+//alias if_t = ifnet*;
diff --git a/libphobos/libdruntime/core/sys/linux/sys/socket.d b/libphobos/libdruntime/core/sys/linux/sys/socket.d
index 339a602..dc274e4 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/socket.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/socket.d
@@ -71,7 +71,6 @@ enum
AF_BRIDGE = PF_BRIDGE,
AF_ATMPVC = PF_ATMPVC,
AF_X25 = PF_X25,
- AF_INET6 = PF_INET6,
AF_ROSE = PF_ROSE,
AF_DECnet = PF_DECnet,
AF_NETBEUI = PF_NETBEUI,
diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d
index dd2462f..48b6f9e 100644
--- a/libphobos/libdruntime/core/thread/fiber.d
+++ b/libphobos/libdruntime/core/thread/fiber.d
@@ -1393,7 +1393,7 @@ private:
// At present, it is not safe to migrate fibers between threads, but if that
// changes, then updating the value of R13 will also need to be handled.
version (PPC64)
- *cast(size_t*)(pstack + wsize) = cast(size_t) Thread.getThis().m_addr;
+ *cast(size_t*)(pstack + wsize) = cast(size_t) ThreadBase.getThis().m_addr;
assert( (cast(size_t) pstack & 0x0f) == 0 );
}
else version (AsmMIPS_O32_Posix)
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 4125fd7..50d71f5 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-5478868465ae1ad743ff76ac5bb92691463ffec5
+dcbfbd43ac321e81af60afd795bd0f3c3f47cfa0
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 13ae294..5fac1c9 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -3276,7 +3276,9 @@ struct Nullable(T)
{
if (!_isNull)
{
- destroy(_value.payload);
+ import std.traits : Unqual;
+ auto ptr = () @trusted { return cast(Unqual!T*) &_value.payload; }();
+ destroy!false(*ptr);
}
}
}
@@ -4319,6 +4321,37 @@ auto nullable(T)(T t)
assert(b.empty);
}
+// https://issues.dlang.org/show_bug.cgi?id=24403
+@safe unittest
+{
+ static bool destroyed;
+ static struct S { ~this() { destroyed = true; } }
+
+ {
+ Nullable!S s = S.init;
+ destroyed = false;
+ }
+ assert(destroyed);
+
+ {
+ Nullable!(const S) s = S.init;
+ destroyed = false;
+ }
+ assert(destroyed);
+
+ {
+ Nullable!(immutable S) s = S.init;
+ destroyed = false;
+ }
+ assert(destroyed);
+
+ {
+ Nullable!(shared S) s = S.init;
+ destroyed = false;
+ }
+ assert(destroyed);
+}
+
/**
Just like `Nullable!T`, except that the null state is defined as a
particular value. For example, $(D Nullable!(uint, uint.max)) is an