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.
This commit is contained in:
parent
3f58f96a4e
commit
94687d17ba
36 changed files with 1417 additions and 792 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "root/object.h"
|
||||
#include "rootobject.h"
|
||||
|
||||
class Visitor;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
// assume filenames encoded in system default Windows ANSI code page
|
||||
enum CodePage = CP_ACP;
|
||||
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;
|
||||
|
||||
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.
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -123,105 +117,6 @@ extern (C++) final class Import : Dsymbol
|
|||
return si;
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* 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
|
||||
|
|
|
@ -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[];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
394
gcc/d/dmd/func.d
394
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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "root/dcompat.h"
|
||||
#include "root/object.h"
|
||||
#include "rootobject.h"
|
||||
|
||||
class Identifier final : public RootObject
|
||||
{
|
||||
|
|
|
@ -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)[])
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "dsystem.h"
|
||||
#include "object.h"
|
||||
#include "rmem.h"
|
||||
|
||||
struct BitArray
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
493
libphobos/libdruntime/core/sys/freebsd/net/if_.d
Normal file
493
libphobos/libdruntime/core/sys/freebsd/net/if_.d
Normal file
|
@ -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*;
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue