d: Merge upstream dmd d7772a2369, phobos 5748ca43f.

In upstream dmd, the compiler front-end and run-time have been merged
together into one repository.  Both dmd and libdruntime now track that.

D front-end changes:

    - Deprecated `scope(failure)' blocks that contain `return' statements.
    - Deprecated using integers for `version' or `debug' conditions.
    - Deprecated returning a discarded void value from a function.
    - `new' can now allocate an associative array.

D runtime changes:

    - Added avx512f detection to core.cpuid module.

Phobos changes:

    - Changed std.experimental.logger.core.sharedLog to return
      shared(Logger).

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd d7772a2369.
	* dmd/VERSION: Bump version to v2.100.1.
	* d-codegen.cc (get_frameinfo): Check whether decision to generate
	closure changed since semantic finished.
	* d-lang.cc (d_handle_option): Remove handling of -fdebug=level and
	-fversion=level.
	* decl.cc (DeclVisitor::visit (VarDeclaration *)): Generate evaluation
	of noreturn variable initializers before throw.
	* expr.cc (ExprVisitor::visit (AssignExp *)): Don't generate
	assignment for noreturn types, only evaluate for side effects.
	* lang.opt (fdebug=): Undocument -fdebug=level.
	(fversion=): Undocument -fversion=level.

libphobos/ChangeLog:

	* configure: Regenerate.
	* configure.ac (libtool_VERSION): Update to 4:0:0.
	* libdruntime/MERGE: Merge upstream druntime d7772a2369.
	* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
	core/internal/array/duplication.d.
	* libdruntime/Makefile.in: Regenerate.
	* src/MERGE: Merge upstream phobos 5748ca43f.
	* testsuite/libphobos.gc/nocollect.d:
This commit is contained in:
Iain Buclaw 2022-07-26 17:42:23 +02:00
parent 64ce76d940
commit b6df113247
143 changed files with 2502 additions and 1292 deletions

View File

@ -2826,8 +2826,15 @@ get_frameinfo (FuncDeclaration *fd)
DECL_LANG_FRAMEINFO (fds) = ffi;
const bool requiresClosure = fd->requiresClosure;
if (fd->needsClosure ())
{
/* This can shift due to templates being expanded that access alias
symbols, give it a decent error for now. */
if (requiresClosure != fd->requiresClosure
&& (fd->nrvo_var || global.params.betterC))
fd->checkClosure ();
/* Set-up a closure frame, this will be allocated on the heap. */
FRAMEINFO_CREATES_FRAME (ffi) = 1;
FRAMEINFO_IS_CLOSURE (ffi) = 1;

View File

@ -456,16 +456,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_fdebug_:
if (ISDIGIT (arg[0]))
{
int level = integral_argument (arg);
if (level != -1)
{
global.params.debuglevel = level;
break;
}
}
if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
{
if (!global.params.debugids)
@ -713,16 +703,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_fversion_:
if (ISDIGIT (arg[0]))
{
int level = integral_argument (arg);
if (level != -1)
{
global.params.versionlevel = level;
break;
}
}
if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
{
if (!global.params.versionids)

View File

@ -646,9 +646,12 @@ public:
if (!d->isDataseg () && !d->isMember ()
&& d->_init && !d->_init->isVoidInitializer ())
{
/* Evaluate RHS for side effects first. */
Expression *ie = initializerToExpression (d->_init);
add_stmt (build_expr (ie));
Expression *e = d->type->defaultInitLiteral (d->loc);
tree exp = build_expr (e);
add_stmt (exp);
add_stmt (build_expr (e));
}
return;

View File

@ -1,4 +1,4 @@
56589f0f4d724c1c8022c57509a243f16a04228a
d7772a236983ec37b92d21b28bad3cd2de57b945
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View File

@ -1 +1 @@
v2.100.0
v2.100.1

View File

@ -111,8 +111,8 @@ bool checkNonAssignmentArrayOp(Expression e, bool suggestion = false)
* evaluation order as the actual array operations have no
* side-effect.
* References:
* https://github.com/dlang/druntime/blob/master/src/object.d#L3944
* https://github.com/dlang/druntime/blob/master/src/core/internal/array/operations.d
* https://github.com/dlang/dmd/blob/cdfadf8a18f474e6a1b8352af2541efe3e3467cc/druntime/src/object.d#L4694
* https://github.com/dlang/dmd/blob/master/druntime/src/core/internal/array/operations.d
*/
Expression arrayOp(BinExp e, Scope* sc)
{

View File

@ -62,7 +62,7 @@ import dmd.target;
bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list)
{
//printf("checkPrintFormat('%.*s')\n", cast(int)format.length, format.ptr);
size_t n, gnu_m_count; // index in args / number of Format.GNU_m
size_t n; // index in args
for (size_t i = 0; i < format.length;)
{
if (format[i] != '%')
@ -79,6 +79,8 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
if (fmt == Format.percent)
continue; // "%%", no arguments
if (fmt == Format.GNU_m)
continue; // "%m", no arguments
if (isVa_list)
{
@ -88,14 +90,11 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
continue;
}
if (fmt == Format.GNU_m)
++gnu_m_count;
Expression getNextArg(ref bool skip)
{
if (n == args.length)
{
if (args.length < (n + 1) - gnu_m_count)
if (args.length < (n + 1))
deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
else
skip = true;
@ -207,7 +206,6 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
errorMsg(null, e, "ptrdiff_t", t);
break;
case Format.GNU_a: // Format.GNU_a is only for scanf
case Format.lg:
case Format.g: // double
if (t.ty != Tfloat64 && t.ty != Timaginary64)
@ -289,8 +287,8 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
break;
case Format.GNU_m:
break; // not assert(0) because it may go through it if there are extra arguments
case Format.POSIX_ms:
case Format.POSIX_mls:
case Format.percent:
assert(0);
}
@ -481,8 +479,6 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
errorMsg(null, e, "real*", t);
break;
case Format.GNU_a:
case Format.GNU_m:
case Format.c:
case Format.s: // pointer to char string
if (!(t.ty == Tpointer && (tnext.ty == Tchar || tnext.ty == Tint8 || tnext.ty == Tuns8)))
@ -500,10 +496,23 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
errorMsg(null, e, "void**", t);
break;
case Format.POSIX_ms: // pointer to pointer to char string
Type tnext2 = tnext ? tnext.nextOf() : null;
if (!(t.ty == Tpointer && tnext.ty == Tpointer && (tnext2.ty == Tchar || tnext2.ty == Tint8 || tnext2.ty == Tuns8)))
errorMsg(null, e, "char**", t);
break;
case Format.POSIX_mls: // pointer to pointer to wchar_t string
Type tnext2 = tnext ? tnext.nextOf() : null;
if (!(t.ty == Tpointer && tnext.ty == Tpointer && tnext2.ty.isSomeChar && tnext2.size() == target.c.wchar_tsize))
errorMsg(null, e, "wchar_t**", t);
break;
case Format.error:
deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
break;
case Format.GNU_m:
case Format.percent:
assert(0);
}
@ -567,35 +576,97 @@ Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
return error();
}
/* Read the scanset
* A scanset can be anything, so we just check that it is paired
*/
if (format[i] == '[')
{
while (i < length)
{
if (format[i] == ']')
break;
++i;
}
// no `]` found
if (i == length)
return error();
++i;
// no specifier after `]`
// it could be mixed with the one above, but then idx won't have the right index
if (i == length)
return error();
}
/* Read the specifier
*/
char genSpec;
Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
if (specifier == Format.error)
return error();
Format specifier;
Modifier flags = Modifier.none;
switch (format[i])
{
case 'm':
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html
// POSIX.1-2017 C Extension (CX)
flags = Modifier.m;
++i;
if (i == length)
return error();
if (format[i] == 'l')
{
++i;
if (i == length)
return error();
flags = Modifier.ml;
}
// Check valid conversion types for %m.
if (format[i] == 'c' || format[i] == 's')
specifier = flags == Modifier.ml ? Format.POSIX_mls :
Format.POSIX_ms;
else if (format[i] == 'C' || format[i] == 'S')
specifier = flags == Modifier.m ? Format.POSIX_mls :
Format.error;
else if (format[i] == '[')
goto case '[';
else
specifier = Format.error;
++i;
break;
case 'l':
// Look for wchar_t scanset %l[..]
immutable j = i + 1;
if (j < length && format[j] == '[')
{
i = j;
flags = Modifier.l;
goto case '[';
}
goto default;
case '[':
// Read the scanset
i++;
if (i == length)
return error();
// If the conversion specifier begins with `[]` or `[^]`, the right
// bracket character is not the terminator, but in the scanlist.
if (format[i] == '^')
{
i++;
if (i == length)
return error();
}
if (format[i] == ']')
{
i++;
if (i == length)
return error();
}
// A scanset can be anything, so we just check that it is paired
while (i < length)
{
if (format[i] == ']')
break;
++i;
}
// no `]` found
if (i == length)
return error();
specifier = flags == Modifier.none ? Format.s :
flags == Modifier.l ? Format.ls :
flags == Modifier.m ? Format.POSIX_ms :
flags == Modifier.ml ? Format.POSIX_mls :
Format.error;
++i;
break;
default:
char genSpec;
specifier = parseGenericFormatSpecifier(format, i, genSpec);
if (specifier == Format.error)
return error();
break;
}
idx = i;
return specifier; // success
@ -613,11 +684,13 @@ Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
* even if `Format.error` is returned
* widthStar = set if * for width
* precisionStar = set if * for precision
* useGNUExts = true if parsing GNU format extensions
* Returns:
* Format
*/
Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
out bool widthStar, out bool precisionStar) nothrow pure @safe
out bool widthStar, out bool precisionStar, bool useGNUExts =
findCondition(global.versionids, Identifier.idPool("CRuntime_Glibc"))) nothrow pure @safe
{
auto i = idx;
assert(format[i] == '%');
@ -730,14 +803,33 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
/* Read the specifier
*/
char genSpec;
Format specifier = parseGenericFormatSpecifier(format, i, genSpec);
if (specifier == Format.error)
return error();
Format specifier;
switch (format[i])
{
case 'm':
// https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
if (useGNUExts)
{
specifier = Format.GNU_m;
genSpec = format[i];
++i;
break;
}
goto default;
default:
specifier = parseGenericFormatSpecifier(format, i, genSpec);
if (specifier == Format.error)
return error();
break;
}
switch (genSpec)
{
case 'c':
case 's':
case 'C':
case 'S':
if (hash || zero)
return error();
break;
@ -748,6 +840,11 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
return error();
break;
case 'm':
if (hash || zero || flags)
return error();
break;
case 'n':
if (hash || zero || precision || width || flags)
return error();
@ -761,6 +858,22 @@ Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
return specifier; // success
}
/* Different kinds of conversion modifiers. */
enum Modifier
{
none,
h, // short
hh, // char
j, // intmax_t
l, // wint_t/wchar_t
ll, // long long int
L, // long double
m, // char**
ml, // wchar_t**
t, // ptrdiff_t
z // size_t
}
/* Different kinds of formatting specifications, variations we don't
care about are merged. (Like we don't care about the difference between
f, e, g, a, etc.)
@ -799,8 +912,9 @@ enum Format
jn, // pointer to intmax_t
zn, // pointer to size_t
tn, // pointer to ptrdiff_t
GNU_a, // GNU ext. : address to a string with no maximum size (scanf)
GNU_m, // GNU ext. : string corresponding to the error code in errno (printf) / length modifier (scanf)
GNU_m, // GNU ext. : string corresponding to the error code in errno (printf)
POSIX_ms, // POSIX ext. : dynamically allocated char string (scanf)
POSIX_mls, // POSIX ext. : dynamically allocated wchar_t string (scanf)
percent, // %% (i.e. no argument)
error, // invalid format specification
}
@ -820,38 +934,48 @@ enum Format
* Format
*/
Format parseGenericFormatSpecifier(scope const char[] format,
ref size_t idx, out char genSpecifier, bool useGNUExts =
findCondition(global.versionids, Identifier.idPool("CRuntime_Glibc"))) nothrow pure @trusted
ref size_t idx, out char genSpecifier) nothrow pure @safe
{
const length = format.length;
/* Read the `length modifier`
*/
const lm = format[idx];
bool lm1; // if jztL
bool lm2; // if `hh` or `ll`
if (lm == 'j' ||
lm == 'z' ||
lm == 't' ||
lm == 'L')
Modifier flags;
switch (lm)
{
++idx;
if (idx == length)
return Format.error;
lm1 = true;
}
else if (lm == 'h' || lm == 'l')
{
++idx;
if (idx == length)
return Format.error;
lm2 = lm == format[idx];
if (lm2)
{
case 'j':
case 'z':
case 't':
case 'L':
flags = lm == 'j' ? Modifier.j :
lm == 'z' ? Modifier.z :
lm == 't' ? Modifier.t :
Modifier.L;
++idx;
if (idx == length)
return Format.error;
}
break;
case 'h':
case 'l':
++idx;
if (idx == length)
return Format.error;
if (lm == format[idx])
{
flags = lm == 'h' ? Modifier.hh : Modifier.ll;
++idx;
if (idx == length)
return Format.error;
}
else
flags = lm == 'h' ? Modifier.h : Modifier.l;
break;
default:
flags = Modifier.none;
break;
}
/* Read the `specifier`
@ -863,103 +987,88 @@ Format parseGenericFormatSpecifier(scope const char[] format,
{
case 'd':
case 'i':
if (lm == 'L')
specifier = Format.error;
else
specifier = lm == 'h' && lm2 ? Format.hhd :
lm == 'h' ? Format.hd :
lm == 'l' && lm2 ? Format.lld :
lm == 'l' ? Format.ld :
lm == 'j' ? Format.jd :
lm == 'z' ? Format.zd :
lm == 't' ? Format.td :
Format.d;
specifier = flags == Modifier.none ? Format.d :
flags == Modifier.hh ? Format.hhd :
flags == Modifier.h ? Format.hd :
flags == Modifier.ll ? Format.lld :
flags == Modifier.l ? Format.ld :
flags == Modifier.j ? Format.jd :
flags == Modifier.z ? Format.zd :
flags == Modifier.t ? Format.td :
Format.error;
break;
case 'u':
case 'o':
case 'x':
case 'X':
if (lm == 'L')
specifier = Format.error;
else
specifier = lm == 'h' && lm2 ? Format.hhu :
lm == 'h' ? Format.hu :
lm == 'l' && lm2 ? Format.llu :
lm == 'l' ? Format.lu :
lm == 'j' ? Format.ju :
lm == 'z' ? Format.zd :
lm == 't' ? Format.td :
Format.u;
specifier = flags == Modifier.none ? Format.u :
flags == Modifier.hh ? Format.hhu :
flags == Modifier.h ? Format.hu :
flags == Modifier.ll ? Format.llu :
flags == Modifier.l ? Format.lu :
flags == Modifier.j ? Format.ju :
flags == Modifier.z ? Format.zd :
flags == Modifier.t ? Format.td :
Format.error;
break;
case 'a':
if (useGNUExts)
{
// https://www.gnu.org/software/libc/manual/html_node/Dynamic-String-Input.html
specifier = Format.GNU_a;
break;
}
goto case;
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
case 'a':
case 'A':
if (lm == 'L')
specifier = Format.Lg;
else if (lm1 || lm2 || lm == 'h')
specifier = Format.error;
else
specifier = lm == 'l' ? Format.lg : Format.g;
specifier = flags == Modifier.none ? Format.g :
flags == Modifier.L ? Format.Lg :
flags == Modifier.l ? Format.lg :
Format.error;
break;
case 'c':
if (lm1 || lm2 || lm == 'h')
specifier = Format.error;
else
specifier = lm == 'l' ? Format.lc : Format.c;
specifier = flags == Modifier.none ? Format.c :
flags == Modifier.l ? Format.lc :
Format.error;
break;
case 's':
if (lm1 || lm2 || lm == 'h')
specifier = Format.error;
else
specifier = lm == 'l' ? Format.ls : Format.s;
specifier = flags == Modifier.none ? Format.s :
flags == Modifier.l ? Format.ls :
Format.error;
break;
case 'p':
if (lm1 || lm2 || lm == 'h' || lm == 'l')
specifier = Format.error;
else
specifier = Format.p;
specifier = flags == Modifier.none ? Format.p :
Format.error;
break;
case 'n':
if (lm == 'L')
specifier = Format.error;
else
specifier = lm == 'l' && lm2 ? Format.lln :
lm == 'l' ? Format.ln :
lm == 'h' && lm2 ? Format.hhn :
lm == 'h' ? Format.hn :
lm == 'j' ? Format.jn :
lm == 'z' ? Format.zn :
lm == 't' ? Format.tn :
Format.n;
specifier = flags == Modifier.none ? Format.n :
flags == Modifier.ll ? Format.lln :
flags == Modifier.l ? Format.ln :
flags == Modifier.hh ? Format.hhn :
flags == Modifier.h ? Format.hn :
flags == Modifier.j ? Format.jn :
flags == Modifier.z ? Format.zn :
flags == Modifier.t ? Format.tn :
Format.error;
break;
case 'm':
if (useGNUExts)
{
// https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
specifier = Format.GNU_m;
break;
}
goto default;
case 'C':
// POSIX.1-2017 X/Open System Interfaces (XSI)
// %C format is equivalent to %lc
specifier = flags == Modifier.none ? Format.lc :
Format.error;
break;
case 'S':
// POSIX.1-2017 X/Open System Interfaces (XSI)
// %S format is equivalent to %ls
specifier = flags == Modifier.none ? Format.ls :
Format.error;
break;
default:
specifier = Format.error;
@ -1126,10 +1235,13 @@ unittest
assert(idx == 2);
idx = 0;
Format g = parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar);
assert(g == Format.g || g == Format.GNU_a);
assert(parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%La", idx, widthStar, precisionStar) == Format.Lg);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%A", idx, widthStar, precisionStar) == Format.g);
assert(idx == 2);
@ -1296,8 +1408,7 @@ unittest
assert(idx == 2);
idx = 0;
g = parseScanfFormatSpecifier("%a", idx, asterisk);
assert(g == Format.g || g == Format.GNU_a);
assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g);
assert(idx == 2);
idx = 0;
@ -1322,15 +1433,25 @@ unittest
// scansets
idx = 0;
assert(parseScanfFormatSpecifier("%[a-zA-Z]s", idx, asterisk) == Format.s);
assert(idx == 10);
assert(parseScanfFormatSpecifier("%[a-zA-Z]", idx, asterisk) == Format.s);
assert(idx == 9);
assert(!asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%*25[a-z]hhd", idx, asterisk) == Format.hhd);
assert(idx == 12);
assert(parseScanfFormatSpecifier("%*25l[a-z]", idx, asterisk) == Format.ls);
assert(idx == 10);
assert(asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%[]]", idx, asterisk) == Format.s);
assert(idx == 4);
assert(!asterisk);
idx = 0;
assert(parseScanfFormatSpecifier("%[^]]", idx, asterisk) == Format.s);
assert(idx == 5);
assert(!asterisk);
// Too short formats
foreach (s; ["%", "% ", "%#", "%0", "%*", "%1", "%19",
"%j", "%z", "%t", "%l", "%h", "%ll", "%hh", "%K"])
@ -1354,11 +1475,108 @@ unittest
}
// Invalid scansets
foreach (s; ["%[]", "%[s", "%[0-9lld", "%[", "%[a-z]"])
foreach (s; ["%[]", "%[^", "%[^]", "%[s", "%[0-9lld", "%[", "%l[^]"])
{
idx = 0;
assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
assert(idx == s.length);
}
// Posix extensions
foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
"%m", "%ma", "%md", "%ml", "%mm", "%mlb", "%mlj", "%mlr", "%mlz",
"%LC", "%lC", "%llC", "%jC", "%tC", "%hC", "%hhC", "%zC",
"%LS", "%lS", "%llS", "%jS", "%tS", "%hS", "%hhS", "%zS"])
{
idx = 0;
assert(parseScanfFormatSpecifier(s, idx, asterisk) == Format.error);
assert(idx == s.length);
}
idx = 0;
assert(parseScanfFormatSpecifier("%mc", idx, asterisk) == Format.POSIX_ms);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%ms", idx, asterisk) == Format.POSIX_ms);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%m[0-9]", idx, asterisk) == Format.POSIX_ms);
assert(idx == 7);
idx = 0;
assert(parseScanfFormatSpecifier("%mlc", idx, asterisk) == Format.POSIX_mls);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%mls", idx, asterisk) == Format.POSIX_mls);
assert(idx == 4);
idx = 0;
assert(parseScanfFormatSpecifier("%ml[^0-9]", idx, asterisk) == Format.POSIX_mls);
assert(idx == 9);
idx = 0;
assert(parseScanfFormatSpecifier("%mC", idx, asterisk) == Format.POSIX_mls);
assert(idx == 3);
idx = 0;
assert(parseScanfFormatSpecifier("%mS", idx, asterisk) == Format.POSIX_mls);
assert(idx == 3);
idx = 0;
assert(parsePrintfFormatSpecifier("%C", idx, widthStar, precisionStar) == Format.lc);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%C", idx, asterisk) == Format.lc);
assert(idx == 2);
idx = 0;
assert(parsePrintfFormatSpecifier("%S", idx, widthStar, precisionStar) == Format.ls);
assert(idx == 2);
idx = 0;
assert(parseScanfFormatSpecifier("%S", idx, asterisk) == Format.ls);
assert(idx == 2);
// GNU extensions: explicitly toggle ISO/GNU flag.
// ISO printf()
bool useGNUExts = false;
{
foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
"%#m", "%+m", "%-m", "% m", "%0m"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
assert(idx == s.length);
}
foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
assert(idx == 2);
}
}
// GNU printf()
useGNUExts = true;
{
foreach (s; ["%jm", "%zm", "%tm", "%Lm", "%hm", "%hhm", "%lm", "%llm",
"%#m", "%+m", "%-m", "% m", "%0m"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.error);
assert(idx == s.length);
}
// valid cases, all parsed as `%m`
foreach (s; ["%m", "%md", "%mz", "%mc", "%mm", "%msyz", "%ml", "%mlz", "%mlc", "%mlm"])
{
idx = 0;
assert(parsePrintfFormatSpecifier(s, idx, widthStar, precisionStar, useGNUExts) == Format.GNU_m);
assert(idx == 2);
}
}
}

View File

@ -1121,6 +1121,10 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
if (!dtor)
return null;
// Don't try to call `@disable`d dtors
if (dtor.storage_class & STC.disable)
return null;
// Generate shim only when ABI incompatible on target platform
if (ad.classKind != ClassKind.cpp || !target.cpp.wrapDtorInExternD)
return dtor;

View File

@ -234,99 +234,9 @@ UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
UnionExp Min(const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
if (type.isreal())
{
emplaceExp!(RealExp)(&ue, loc, e1.toReal() - e2.toReal(), type);
}
else if (type.isimaginary())
{
emplaceExp!(RealExp)(&ue, loc, e1.toImaginary() - e2.toImaginary(), type);
}
else if (type.iscomplex())
{
// This rigamarole is necessary so that -0.0 doesn't get
// converted to +0.0 by doing an extraneous add with +0.0
auto c1 = complex_t(CTFloat.zero);
real_t r1 = CTFloat.zero;
real_t i1 = CTFloat.zero;
auto c2 = complex_t(CTFloat.zero);
real_t r2 = CTFloat.zero;
real_t i2 = CTFloat.zero;
auto v = complex_t(CTFloat.zero);
int x;
if (e1.type.isreal())
{
r1 = e1.toReal();
x = 0;
}
else if (e1.type.isimaginary())
{
i1 = e1.toImaginary();
x = 3;
}
else
{
c1 = e1.toComplex();
x = 6;
}
if (e2.type.isreal())
{
r2 = e2.toReal();
}
else if (e2.type.isimaginary())
{
i2 = e2.toImaginary();
x += 1;
}
else
{
c2 = e2.toComplex();
x += 2;
}
switch (x)
{
case 0 + 0:
v = complex_t(r1 - r2);
break;
case 0 + 1:
v = complex_t(r1, -i2);
break;
case 0 + 2:
v = complex_t(r1 - creall(c2), -cimagl(c2));
break;
case 3 + 0:
v = complex_t(-r2, i1);
break;
case 3 + 1:
v = complex_t(CTFloat.zero, i1 - i2);
break;
case 3 + 2:
v = complex_t(-creall(c2), i1 - cimagl(c2));
break;
case 6 + 0:
v = complex_t(creall(c1) - r2, cimagl(c1));
break;
case 6 + 1:
v = complex_t(creall(c1), cimagl(c1) - i2);
break;
case 6 + 2:
v = c1 - c2;
break;
default:
assert(0);
}
emplaceExp!(ComplexExp)(&ue, loc, v, type);
}
else if (SymOffExp soe = e1.isSymOffExp())
{
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset - e2.toInteger());
ue.exp().type = type;
}
else
{
emplaceExp!(IntegerExp)(&ue, loc, e1.toInteger() - e2.toInteger(), type);
}
// Compute e1-e2 as e1+(-e2)
UnionExp neg = Neg(e2.type, e2);
UnionExp ue = Add(loc, type, e1, neg.exp());
return ue;
}
@ -1213,6 +1123,10 @@ UnionExp ArrayLength(Type type, Expression e1)
Expression e = (cast(TypeSArray)e1.type.toBasetype()).dim;
emplaceExp!(UnionExp)(&ue, e);
}
else if (e1.isNullExp())
{
emplaceExp!(IntegerExp)(&ue, loc, 0, type);
}
else
cantExp(ue);
return ue;
@ -1505,17 +1419,11 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
Type t2 = e2.type.toBasetype();
//printf("Cat(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
//printf("\tt1 = %s, t2 = %s, type = %s\n", t1.toChars(), t2.toChars(), type.toChars());
if (e1.op == EXP.null_ && (e2.op == EXP.int64 || e2.op == EXP.structLiteral))
/* e is the non-null operand, t is the type of the null operand
*/
UnionExp catNull(Expression e, Type t)
{
e = e2;
t = t1;
goto L2;
}
else if ((e1.op == EXP.int64 || e1.op == EXP.structLiteral) && e2.op == EXP.null_)
{
e = e1;
t = t2;
L2:
Type tn = e.type.toBasetype();
if (tn.ty.isSomeChar)
{
@ -1545,6 +1453,15 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
if (e1.op == EXP.null_ && (e2.op == EXP.int64 || e2.op == EXP.structLiteral))
{
return catNull(e2, t1);
}
else if ((e1.op == EXP.int64 || e1.op == EXP.structLiteral) && e2.op == EXP.null_)
{
return catNull(e1, t2);
}
else if (e1.op == EXP.null_ && e2.op == EXP.null_)
{
if (type == e1.type)

View File

@ -1675,7 +1675,7 @@ final class CParser(AST) : Parser!AST
auto stags = applySpecifier(stag, specifier);
symbols.push(stags);
if (tt.tok == TOK.enum_)
if (0 && tt.tok == TOK.enum_) // C11 proscribes enums with no members, but we allow it
{
if (!tt.members)
error(tt.loc, "`enum %s` has no members", stag.toChars());

View File

@ -1106,9 +1106,14 @@ MATCH implicitConvTo(Expression e, Type t)
MATCH visitCond(CondExp e)
{
auto result = visit(e);
if (result != MATCH.nomatch)
return result;
e.econd = e.econd.optimize(WANTvalue);
const opt = e.econd.toBool();
if (opt.isPresent())
{
auto result = visit(e);
if (result != MATCH.nomatch)
return result;
}
MATCH m1 = e.e1.implicitConvTo(t);
MATCH m2 = e.e2.implicitConvTo(t);
@ -2942,6 +2947,9 @@ Lagain:
t1 = Type.basic[ty1];
t2 = Type.basic[ty2];
if (!(t1 && t2))
return null;
e1 = e1.castTo(sc, t1);
e2 = e2.castTo(sc, t2);
return Lret(Type.basic[ty]);

View File

@ -684,6 +684,7 @@ public:
const char *kind() const override;
bool isUnique();
bool needsClosure();
bool checkClosure();
bool hasNestedFrameRefs();
ParameterList getParameterList();

View File

@ -2352,6 +2352,7 @@ public:
if (ExpInitializer ie = v._init.isExpInitializer())
{
result = interpretRegion(ie.exp, istate, goal);
return;
}
else if (v._init.isVoidInitializer())
{
@ -2359,12 +2360,16 @@ public:
// There is no AssignExp for void initializers,
// so set it here.
setValue(v, result);
return;
}
else
else if (v._init.isArrayInitializer())
{
e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
result = CTFEExp.cantexp;
result = v._init.initializerToExpression(v.type);
if (result !is null)
return;
}
e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
result = CTFEExp.cantexp;
}
else if (v.type.size() == 0)
{

View File

@ -619,7 +619,7 @@ extern (C++) final class Module : Package
else
{
// if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module
bool isPackageMod = (strcmp(toChars(), "package") != 0) && (strcmp(srcfile.name(), package_d) == 0 || (strcmp(srcfile.name(), package_di) == 0));
bool isPackageMod = (strcmp(toChars(), "package") != 0) && isPackageFileName(srcfile);
if (isPackageMod)
.error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'", toChars(), srcfile.toChars());
else
@ -824,8 +824,7 @@ extern (C++) final class Module : Package
const(char)* srcname = srcfile.toChars();
//printf("Module::parse(srcname = '%s')\n", srcname);
isPackageFile = (strcmp(srcfile.name(), package_d) == 0 ||
strcmp(srcfile.name(), package_di) == 0);
isPackageFile = isPackageFileName(srcfile);
const(char)[] buf = cast(const(char)[]) this.src;
bool needsReencoding = true;
@ -1032,8 +1031,7 @@ extern (C++) final class Module : Package
}
assert(dst);
Module m = ppack ? ppack.isModule() : null;
if (m && (strcmp(m.srcfile.name(), package_d) != 0 &&
strcmp(m.srcfile.name(), package_di) != 0))
if (m && !isPackageFileName(m.srcfile))
{
.error(md.loc, "package name '%s' conflicts with usage as a module name in file %s", ppack.toPrettyChars(), m.srcfile.toChars());
}

View File

@ -2441,6 +2441,15 @@ Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
auto sd = s.isScopeDsymbol(); // new declaration
auto sd2 = s2.isScopeDsymbol(); // existing declaration
static if (log) void print(EnumDeclaration sd)
{
printf("members: %p\n", sd.members);
printf("symtab: %p\n", sd.symtab);
printf("endlinnum: %d\n", sd.endlinnum);
printf("type: %s\n", sd.type.toChars());
printf("memtype: %s\n", sd.memtype.toChars());
}
if (!sd2)
{
/* Look in tag table
@ -2473,6 +2482,23 @@ Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
{
sd2.members = sd.members; // transfer definition to sd2
sd.members = null;
if (auto ed2 = sd2.isEnumDeclaration())
{
auto ed = sd.isEnumDeclaration();
if (ed.memtype != ed2.memtype)
return null; // conflict
// transfer ed's members to sd2
ed2.members.foreachDsymbol( (s)
{
if (auto em = s.isEnumMember())
em.ed = ed2;
});
ed2.type = ed.type;
ed2.memtype = ed.memtype;
ed2.added = false;
}
return sd2;
}
else

View File

@ -2023,7 +2023,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(EnumDeclaration ed)
{
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
//printf("EnumDeclaration::semantic() %p %s\n", this, ed.toChars());
//printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
if (ed.semanticRun >= PASS.semanticdone)
return; // semantic() already completed
if (ed.semanticRun == PASS.semantic)
@ -4442,7 +4442,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
invd.semanticRun < PASS.semantic &&
!ad.isUnionDeclaration() // users are on their own with union fields
)
{
invd.fixupInvariantIdent(ad.invs.length);
ad.invs.push(invd);
}
if (!invd.type)
invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);
@ -5713,6 +5716,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
*/
void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
{
//printf("addEnumMembers(ed: %p)\n", ed);
if (ed.added)
return;
ed.added = true;
@ -5736,6 +5740,7 @@ void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
em.ed = ed;
if (isCEnum)
{
//printf("adding EnumMember %s to %p\n", em.toChars(), ed);
em.addMember(sc, ed); // add em to ed's symbol table
em.addMember(sc, sds); // add em to symbol table that ed is in
em.parent = ed; // restore it after previous addMember() changed it

View File

@ -7323,7 +7323,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
errors = true;
}
L1:
//printf("\tnested inside %s\n", enclosing.toChars());
//printf("\tnested inside %s as it references %s\n", enclosing.toChars(), sa.toChars());
nested |= 1;
}
}

View File

@ -17,18 +17,27 @@ import core.stdc.ctype;
nothrow:
public int HtmlNamedEntity(const(char)* p, size_t length)
/**********************************
* See if `name` is an HTML Named Entity
* Params:
* name = name of the entity
* Returns:
* code point corresponding to the named entity
* ~0 for not recognized as a named entity
*/
public uint HtmlNamedEntity(scope const char[] name) pure @nogc @safe
{
int tableIndex = tolower(*p) - 'a';
if (tableIndex >= 0 && tableIndex < 26)
const firstC = tolower(name[0]);
if (firstC >= 'a' && firstC <= 'z')
{
foreach (entity; namesTable[tableIndex])
// Linear search (use hash table instead?)
foreach (entity; namesTable[firstC - 'a'])
{
if (entity.name == p[0 .. length])
if (entity.name == name)
return entity.value;
}
}
return -1;
return ~0;
}
private:

View File

@ -351,7 +351,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC
{
unsafeAssign!"scope variable"(v);
}
else if (v.storage_class & STC.variadic && p == sc.func)
else if (v.isTypesafeVariadicParameter && p == sc.func)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
@ -649,7 +649,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
Dsymbol p = v.toParent2();
if (va && !vaIsRef && !va.isScope() && !v.isScope() &&
(va.storage_class & v.storage_class & (STC.maybescope | STC.variadic)) == STC.maybescope &&
!v.isTypesafeVariadicParameter && !va.isTypesafeVariadicParameter &&
(va.storage_class & v.storage_class & STC.maybescope) &&
p == fd)
{
/* Add v to va's list of dependencies
@ -663,7 +664,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
!(v.storage_class & STC.return_) &&
v.isParameter() &&
fd.flags & FUNCFLAG.returnInprocess &&
p == fd)
p == fd &&
!v.isTypesafeVariadicParameter)
{
if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars());
inferReturn(fd, v, /*returnScope:*/ true); // infer addition of 'return' to make `return scope`
@ -735,7 +737,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1);
}
else if (v.storage_class & STC.variadic && p == fd)
else if (v.isTypesafeVariadicParameter && p == fd)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
@ -1022,7 +1024,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
continue;
}
}
else if (v.storage_class & STC.variadic && p == sc.func)
else if (v.isTypesafeVariadicParameter && p == sc.func)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
@ -1194,7 +1196,8 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
v.isParameter() &&
!v.doNotInferReturn &&
sc.func.flags & FUNCFLAG.returnInprocess &&
p == sc.func)
p == sc.func &&
!v.isTypesafeVariadicParameter)
{
inferReturn(sc.func, v, /*returnScope:*/ true); // infer addition of 'return'
continue;
@ -1250,7 +1253,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
}
}
}
else if (v.storage_class & STC.variadic && p == sc.func)
else if (v.isTypesafeVariadicParameter && p == sc.func)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
@ -1627,7 +1630,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
{
if (tb.ty == Tsarray)
return;
if (v.storage_class & STC.variadic)
if (v.isTypesafeVariadicParameter)
{
er.byvalue.push(v);
return;
@ -1943,7 +1946,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
VarDeclaration v = ve.var.isVarDeclaration();
if (tb.ty == Tarray || tb.ty == Tsarray)
{
if (v && v.storage_class & STC.variadic)
if (v && v.isTypesafeVariadicParameter)
{
er.pushRef(v, retRefTransition);
return;
@ -2586,3 +2589,15 @@ private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool g
return sc.setUnsafeDIP1000(gag, e.loc,
"cannot take address of `scope` variable `%s` since `scope` applies to first indirection only", v);
}
/****************************
* Determine if `v` is a typesafe variadic parameter.
* Params:
* v = variable to check
* Returns:
* true if `v` is a variadic parameter
*/
bool isTypesafeVariadicParameter(VarDeclaration v)
{
return !!(v.storage_class & STC.variadic);
}

View File

@ -3463,8 +3463,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (!exp.arguments && exp.newtype.isTypeSArray())
{
auto ts = exp.newtype.isTypeSArray();
edim = ts.dim;
exp.newtype = ts.next;
// check `new Value[Key]`
ts.dim = ts.dim.expressionSemantic(sc);
if (ts.dim.op == EXP.type)
{
exp.newtype = new TypeAArray(ts.next, ts.dim.isTypeExp().type);
}
else
{
edim = ts.dim;
exp.newtype = ts.next;
}
}
ClassDeclaration cdthis = null;
@ -3518,18 +3527,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
return setError();
}
//https://issues.dlang.org/show_bug.cgi?id=20547
//exp.arguments are the "parameters" to [], not to a real function
//so the errors that come from preFunctionParameters are misleading
if (originalNewtype.ty == Tsarray)
{
if (preFunctionParameters(sc, exp.arguments, false))
{
exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
return setError();
}
}
else if (preFunctionParameters(sc, exp.arguments))
if (preFunctionParameters(sc, exp.arguments))
{
return setError();
}
@ -3885,6 +3883,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.type = exp.type.pointerTo();
}
else if (tb.ty == Taarray)
{
// e.g. `new Alias(args)`
if (nargs)
{
exp.error("`new` cannot take arguments for an associative array");
return setError();
}
}
else
{
exp.error("cannot create a `%s` with `new`", exp.type.toChars());
@ -5019,7 +5026,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
err = true;
}
if (tf.trust <= TRUST.system && sc.setUnsafe())
if (tf.trust <= TRUST.system && sc.setUnsafe(true, exp.loc,
"`@safe` function `%s` cannot call `@system` `%s`", sc.func, exp.e1))
{
exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
@ -7588,11 +7596,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// Check for unsafe casts
if (!isSafeCast(ex, t1b, tob) &&
(!sc.func && sc.stc & STC.safe || sc.setUnsafe()))
if (!isSafeCast(ex, t1b, tob))
{
exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
return setError();
// This is an ad-hoc fix for https://issues.dlang.org/show_bug.cgi?id=19646
// Should be replaced by a more general @system variables implementation
if (!sc.func && sc.stc & STC.safe)
{
exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
return setError();
}
if (sc.setUnsafe(false, exp.loc, "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
{
return setError();
}
}
// `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
@ -8900,6 +8917,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
e2x.checkSharedAccess(sc))
return setError();
if (e2x.type.isTypeNoreturn() && !e2x.isAssertExp() && !e2x.isThrowExp() && !e2x.isCallExp())
{
auto msg = new StringExp(e2x.loc, "Accessed expression of type `noreturn`");
msg.type = Type.tstring;
e2x = new AssertExp(e2x.loc, IntegerExp.literal!0, msg);
e2x.type = Type.tnoreturn;
return setResult(e2x);
}
exp.e2 = e2x;
}
@ -9896,9 +9922,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ae.e2.type.nextOf &&
ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
/* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal,
* then we do want to make a temporary for it and call its destructor.
*/
const isArraySetCtor =
(ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
ae.e2.isLvalue &&
(ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
ae.e1.type.nextOf &&
ae.e1.type.nextOf.equivalent(ae.e2.type);
@ -10302,6 +10330,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// `__appendtmp*` will be destroyed together with the array `exp.e1`.
auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
vd.storage_class |= STC.nodtor;
// Be more explicit that this "declaration" is local to the expression
vd.storage_class |= STC.exptemp;
}
auto ale = new ArrayLengthExp(exp.loc, value1);
@ -11870,6 +11900,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
//printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
// https://issues.dlang.org/show_bug.cgi?id=22390
// Equality comparison between array of noreturns simply lowers to length equality comparison
if (t1.nextOf.isTypeNoreturn() && t2.nextOf.isTypeNoreturn())
{
Expression exp_l1 = new DotIdExp(exp.e1.loc, exp.e1, Id.length);
Expression exp_l2 = new DotIdExp(exp.e2.loc, exp.e2, Id.length);
auto e = new EqualExp(EXP.equal, exp.loc, exp_l1, exp_l2);
result = e.expressionSemantic(sc);
return;
}
if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
return setError();
@ -12638,7 +12679,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
e = new CommaExp(exp.loc, eleft, e);
e.type = Type.tvoid; // ambiguous type?
}
return e;
return e.expressionSemantic(sc);
}
if (auto o = s.isOverloadSet())
{
@ -13131,26 +13172,24 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
{
//printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
if (v)
if (v is null)
return true;
if (!v.canTakeAddressOf())
{
if (!v.canTakeAddressOf())
exp.error("cannot take address of `%s`", exp.toChars());
return false;
}
if (sc.func && !sc.intypeof && !v.isDataseg())
{
v.storage_class &= ~STC.maybescope;
v.doNotInferScope = true;
if (global.params.useDIP1000 != FeatureState.enabled &&
!(v.storage_class & STC.temp) &&
sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func))
{
exp.error("cannot take address of `%s`", exp.toChars());
return false;
}
if (sc.func && !sc.intypeof && !v.isDataseg())
{
const(char)* p = v.isParameter() ? "parameter" : "local";
v.storage_class &= ~STC.maybescope;
v.doNotInferScope = true;
if (global.params.useDIP1000 != FeatureState.enabled &&
!(v.storage_class & STC.temp) &&
sc.setUnsafe())
{
exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
return false;
}
}
}
return true;
}

View File

@ -20,6 +20,12 @@ import dmd.identifier;
enum package_d = "package." ~ mars_ext;
enum package_di = "package." ~ hdr_ext;
/// Returns: whether a file with `name` is a special "package.d" module
bool isPackageFileName(scope FileName fileName) nothrow
{
return FileName.equals(fileName.name, package_d) || FileName.equals(fileName.name, package_di);
}
final class FileManager
{
private StringTable!(const(ubyte)[]) files;

View File

@ -867,6 +867,8 @@ extern (C++) class FuncDeclaration : Declaration
auto f = s.isFuncDeclaration();
if (!f)
return 0;
if (f.storage_class & STC.disable)
return 0;
if (t.equals(f.type))
{
fd = f;
@ -2048,9 +2050,11 @@ extern (C++) class FuncDeclaration : Declaration
}
if (!found)
{
//printf("\tadding sibling %s\n", fdthis.toPrettyChars());
//printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars());
if (!sc.intypeof && !(sc.flags & SCOPE.compile))
{
siblingCallers.push(fdthis);
}
}
}
@ -2164,7 +2168,6 @@ extern (C++) class FuncDeclaration : Declaration
return false;
Lyes:
//printf("\tneeds closure\n");
return true;
}
@ -2176,14 +2179,21 @@ extern (C++) class FuncDeclaration : Declaration
* Returns:
* true if any errors occur.
*/
extern (D) final bool checkClosure()
extern (C++) final bool checkClosure()
{
//printf("checkClosure() %s\n", toChars());
if (!needsClosure())
return false;
if (setGC())
{
error("is `@nogc` yet allocates closures with the GC");
error("is `@nogc` yet allocates closure for `%s()` with the GC", toChars());
if (global.gag) // need not report supplemental errors
return true;
}
else if (global.params.betterC)
{
error("is `-betterC` yet allocates closure for `%s()` with the GC", toChars());
if (global.gag) // need not report supplemental errors
return true;
}
@ -2216,7 +2226,7 @@ extern (C++) class FuncDeclaration : Declaration
break LcheckAncestorsOfANestedRef;
}
a.push(f);
.errorSupplemental(f.loc, "%s closes over variable %s at %s",
.errorSupplemental(f.loc, "`%s` closes over variable `%s` at %s",
f.toPrettyChars(), v.toChars(), v.loc.toChars());
break LcheckAncestorsOfANestedRef;
}
@ -3293,7 +3303,8 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
tiargsBuf.peekChars(), fargsBuf.peekChars());
printCandidates(loc, td, sc.isDeprecated());
if (!global.gag || global.params.showGaggedErrors)
printCandidates(loc, td, sc.isDeprecated());
return null;
}
/* This case used to happen when several ctors are mixed in an agregate.
@ -3331,7 +3342,8 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
{
.error(loc, "none of the overloads of `%s` are callable using a %sobject",
fd.ident.toChars(), thisBuf.peekChars());
printCandidates(loc, fd, sc.isDeprecated());
if (!global.gag || global.params.showGaggedErrors)
printCandidates(loc, fd, sc.isDeprecated());
return null;
}
@ -3361,18 +3373,23 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
{
.error(loc, "none of the overloads of `%s` are callable using argument types `%s`",
fd.toChars(), fargsBuf.peekChars());
printCandidates(loc, fd, sc.isDeprecated());
if (!global.gag || global.params.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
const(char)* failMessage;
functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage);
if (failMessage)
errorSupplemental(loc, failMessage);
if (!global.gag || global.params.showGaggedErrors)
{
const(char)* failMessage;
functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage);
if (failMessage)
errorSupplemental(loc, failMessage);
}
return null;
}
@ -4220,6 +4237,7 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration
{
extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Identifier id, Statement fbody)
{
// Make a unique invariant for now; we'll fix it up as we add it to the aggregate invariant list.
super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
this.fbody = fbody;
}
@ -4256,6 +4274,15 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration
{
v.visit(this);
}
extern (D) void fixupInvariantIdent(size_t offset)
{
OutBuffer idBuf;
idBuf.writestring("__invariant");
idBuf.print(offset);
ident = Identifier.idPool(idBuf[]);
}
}
@ -4447,12 +4474,15 @@ void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth, bool depr
errorFunc(s.loc, s.fmtStr,
s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : "");
}
else if (FuncDeclaration fd2 = cast(FuncDeclaration) s.arg0)
else if (s.arg0.dyncast() == DYNCAST.dsymbol)
{
if (maxDepth > 0)
if (FuncDeclaration fd2 = (cast(Dsymbol) s.arg0).isFuncDeclaration())
{
errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars());
errorSupplementalInferredSafety(fd2, maxDepth - 1, deprecation);
if (maxDepth > 0)
{
errorFunc(s.loc, "which calls `%s`", fd2.toPrettyChars());
errorSupplementalInferredSafety(fd2, maxDepth - 1, deprecation);
}
}
}
}

View File

@ -64,6 +64,57 @@ enum ImpCnvTab impCnvTab = generateImpCnvTab();
ImpCnvTab generateImpCnvTab()
{
TY[TMAX] typeTYs =
[
Tarray,
Tsarray,
Taarray,
Tpointer,
Treference,
Tfunction,
Tident,
Tclass,
Tstruct,
Tenum,
Tdelegate,
Tnone,
Tvoid,
Tint8,
Tuns8,
Tint16,
Tuns16,
Tint32,
Tuns32,
Tint64,
Tuns64,
Tfloat32,
Tfloat64,
Tfloat80,
Timaginary32,
Timaginary64,
Timaginary80,
Tcomplex32,
Tcomplex64,
Tcomplex80,
Tbool,
Tchar,
Twchar,
Tdchar,
Terror,
Tinstance,
Ttypeof,
Ttuple,
Tslice,
Treturn,
Tnull,
Tvector,
Tint128,
Tuns128,
Ttraits,
Tmixin,
Tnoreturn,
Ttag,
];
ImpCnvTab impCnvTab;
// Set conversion tables
@ -375,5 +426,9 @@ ImpCnvTab generateImpCnvTab()
X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80);
// "No type is implicitly convertible to noreturn, but noreturn is implicitly convertible to every other type"
foreach(convertToTy; typeTYs)
X(Tnoreturn, convertToTy, convertToTy, convertToTy, convertToTy);
return impCnvTab;
}

View File

@ -567,18 +567,40 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
i.exp = e.optimize(WANTvalue);
}
}
// Look for the case of statically initializing an array with a single member.
// Recursively strip static array / enum layers until a compatible element is found,
// and return an `ArrayLiteralExp` repeating the initializer, or `null` if no match found
// int[2][3] = 7 => [[7, 7], [7, 7], [7, 7]]
// int[2] = new Object => null
Expression sarrayRepeat(Type tb)
{
// Look for the case of statically initializing an array
// with a single member.
auto tba = tb.isTypeSArray();
if (tba && !tba.next.equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tba.next))
{
/* If the variable is not actually used in compile time, array creation is
* redundant. So delay it until invocation of toExpression() or toDt().
*/
t = tb.nextOf();
auto tsa = tb.isTypeSArray();
if (!tsa)
return null;
// printf("i.exp = %s, tsa = %s\n", i.exp.toChars(), tsa.toChars());
Expression elem = null;
if (i.exp.implicitConvTo(tb.nextOf()))
elem = i.exp.implicitCastTo(sc, tb.nextOf());
else if (auto ae = sarrayRepeat(tb.nextOf().toBasetype()))
elem = ae;
else
return null;
auto arrayElements = new Expressions(cast(size_t) tsa.dim.toInteger());
foreach (ref e; *arrayElements)
e = elem;
return new ArrayLiteralExp(i.exp.loc, tb, elem, arrayElements);
}
if (auto sa = sarrayRepeat(tb))
{
// printf("sa = %s\n", sa.toChars());
i.exp = sa;
}
{
auto tta = t.isTypeSArray();
if (i.exp.implicitConvTo(t))
{
@ -595,6 +617,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
else
{
auto tba = tb.isTypeSArray();
// Look for mismatch of compile-time known length to emit
// better diagnostic message, as same as AssignExp::semantic.
if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch)

View File

@ -1326,7 +1326,7 @@ class Lexer
switch (*p)
{
case ';':
c = HtmlNamedEntity(idstart, p - idstart);
c = HtmlNamedEntity(idstart[0 .. p - idstart]);
if (c == ~0)
{
error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart);

View File

@ -98,7 +98,7 @@ void checkMustUseReserved(Dsymbol sym)
*/
private bool isAssignment(Expression e)
{
if (e.isAssignExp || e.isBinAssignExp)
if (e.isAssignExp || e.isBinAssignExp || e.isConstructExp || e.isBlitExp)
return true;
if (auto ce = e.isCallExp())
{

View File

@ -1120,7 +1120,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
e.e1 = ci;
}
}
if (e.e1.op == EXP.string_ || e.e1.op == EXP.arrayLiteral || e.e1.op == EXP.assocArrayLiteral || e.e1.type.toBasetype().ty == Tsarray)
if (e.e1.op == EXP.string_ || e.e1.op == EXP.arrayLiteral || e.e1.op == EXP.assocArrayLiteral || e.e1.type.toBasetype().ty == Tsarray || e.e1.op == EXP.null_)
{
ret = ArrayLength(e.type, e.e1).copy();
}

View File

@ -2186,7 +2186,13 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.identifier)
s = new AST.DebugSymbol(token.loc, token.ident);
else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
{
// @@@DEPRECATED_2.111@@@
// Deprecated in 2.101, remove in 2.111
deprecation("`debug = <integer>` is deprecated, use debug identifiers instead");
s = new AST.DebugSymbol(token.loc, cast(uint)token.unsvalue);
}
else
{
error("identifier or integer expected, not `%s`", token.toChars());
@ -2215,7 +2221,13 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.identifier)
id = token.ident;
else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
{
// @@@DEPRECATED_2.111@@@
// Deprecated in 2.101, remove in 2.111
deprecation("`debug( <integer> )` is deprecated, use debug identifiers instead");
level = cast(uint)token.unsvalue;
}
else
error("identifier or integer expected inside `debug(...)`, not `%s`", token.toChars());
loc = token.loc;
@ -2235,7 +2247,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.identifier)
s = new AST.VersionSymbol(token.loc, token.ident);
else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
{
// @@@DEPRECATED_2.111@@@
// Deprecated in 2.101, remove in 2.111
deprecation("`version = <integer>` is deprecated, use version identifiers instead");
s = new AST.VersionSymbol(token.loc, cast(uint)token.unsvalue);
}
else
{
error("identifier or integer expected, not `%s`", token.toChars());
@ -2269,7 +2286,13 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.identifier)
id = token.ident;
else if (token.value == TOK.int32Literal || token.value == TOK.int64Literal)
{
// @@@DEPRECATED_2.111@@@
// Deprecated in 2.101, remove in 2.111
deprecation("`version( <integer> )` is deprecated, use version identifiers instead");
level = cast(uint)token.unsvalue;
}
else if (token.value == TOK.unittest_)
id = Identifier.idPool(Token.toString(TOK.unittest_));
else if (token.value == TOK.assert_)
@ -9312,13 +9335,10 @@ LagainStc:
{
AST.TypeAArray taa = cast(AST.TypeAArray)t;
AST.Type index = taa.index;
// `new Type[expr]` is a static array
auto edim = AST.typeToExpression(index);
if (!edim)
{
error("cannot create a `%s` with `new`", t.toChars);
return new AST.NullExp(loc);
}
t = new AST.TypeSArray(taa.next, edim);
if (edim)
t = new AST.TypeSArray(taa.next, edim);
}
else if (token.value == TOK.leftParenthesis && t.ty != Tsarray)
{

View File

@ -470,14 +470,6 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
{
stc |= STC.variadic;
auto vtypeb = vtype.toBasetype();
if (vtypeb.ty == Tarray || vtypeb.ty == Tclass)
{
/* Since it'll be pointing into the stack for the array
* contents, it needs to be `scope`
*/
stc |= STC.scope_;
}
}
if ((funcdecl.flags & FUNCFLAG.inferScope) && !(fparam.storageClass & STC.scope_))
@ -1379,7 +1371,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
if (funcdecl.type.ty == Terror)
funcdecl.errors = true;
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars());
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), sc, funcdecl.loc.toChars());
//fflush(stdout);
}

View File

@ -733,9 +733,26 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
{
assert(oaggr.type);
fs.error("invalid `foreach` aggregate `%s` of type `%s`", oaggr.toChars(), oaggr.type.toPrettyChars());
if (isAggregate(fs.aggr.type))
fs.loc.errorSupplemental("maybe define `opApply()`, range primitives, or use `.tupleof`");
fs.error("invalid `%s` aggregate `%s` of type `%s`",
Token.toChars(fs.op), oaggr.toChars(), oaggr.type.toPrettyChars());
if (auto ad = isAggregate(fs.aggr.type))
{
if (fs.op == TOK.foreach_reverse_)
{
fs.loc.errorSupplemental("`foreach_reverse` works with bidirectional ranges"~
" (implementing `back` and `popBack`), aggregates implementing" ~
" `opApplyReverse`, or the result of an aggregate's `.tupleof` property");
fs.loc.errorSupplemental("https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange");
}
else
{
fs.loc.errorSupplemental("`foreach` works with input ranges"~
" (implementing `front` and `popFront`), aggregates implementing" ~
" `opApply`, or the result of an aggregate's `.tupleof` property");
fs.loc.errorSupplemental("https://dlang.org/phobos/std_range_primitives.html#isInputRange");
}
}
return setError();
}
@ -2828,10 +2845,20 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
rs.error("`return` statements cannot be in contracts");
errors = true;
}
if (sc.os && sc.os.tok != TOK.onScopeFailure)
if (sc.os)
{
rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
errors = true;
// @@@DEPRECATED_2.112@@@
// Deprecated in 2.100, transform into an error in 2.112
if (sc.os.tok == TOK.onScopeFailure)
{
rs.deprecation("`return` statements cannot be in `scope(failure)` bodies.");
deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose");
}
else
{
rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
errors = true;
}
}
if (sc.tf)
{
@ -2913,6 +2940,17 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
rs.exp.type = texp;
}
// @@@DEPRECATED_2.111@@@
const olderrors = global.startGagging();
// uncomment to turn deprecation into an error when
// deprecation cycle is over
if (discardValue(rs.exp))
{
//errors = true;
}
if (global.endGagging(olderrors))
rs.exp.deprecation("`%s` has no effect", rs.exp.toChars());
/* Replace:
* return exp;
* with:

View File

@ -862,6 +862,12 @@ package mixin template ParseVisitMethods(AST)
visitFuncBody(d);
}
override void visit(AST.CtorDeclaration d)
{
//printf("Visiting CtorDeclaration\n");
visitFuncBody(d);
}
override void visit(AST.StaticCtorDeclaration d)
{
//printf("Visiting StaticCtorDeclaration\n");

View File

@ -1272,6 +1272,16 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
errors = true;
}
const bool isTypesafeVariadic = i + 1 == dim &&
tf.parameterList.varargs == VarArg.typesafe &&
(t.isTypeDArray() || t.isTypeClass());
if (isTypesafeVariadic)
{
/* typesafe variadic arguments are constructed on the stack, so must be `scope`
*/
fparam.storageClass |= STC.scope_ | STC.scopeinferred;
}
if (fparam.storageClass & STC.return_)
{
if (fparam.isReference())
@ -1300,8 +1310,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
}
}
if (i + 1 == dim && tf.parameterList.varargs == VarArg.typesafe &&
(t.isTypeDArray() || t.isTypeClass()))
if (isTypesafeVariadic)
{
/* This is because they can be constructed on the stack
* https://dlang.org/spec/function.html#typesafe_variadic_functions

View File

@ -873,6 +873,17 @@ public:
gcc_unreachable ();
}
/* Look for exp = noreturn; */
if (e->e2->type->isTypeNoreturn ())
{
/* If the RHS is a `noreturn' expression, there is no point generating
any code for the assignment, just evaluate side effects. */
tree t1 = build_expr (e->e1);
tree t2 = build_expr (e->e2);
this->result_ = compound_expr (t1, t2);
return;
}
/* Look for array[] = n; */
if (e->e1->op == EXP::slice)
{

View File

@ -249,7 +249,7 @@ Compile in debug code.
fdebug=
D Joined RejectNegative
-fdebug=<level|ident> Compile in debug code, code <= <level>, or code identified by <ident>.
-fdebug=<ident> Compile in debug code identified by <ident>.
fdoc
D
@ -466,7 +466,7 @@ Compile in unittest code.
fversion=
D Joined RejectNegative
-fversion=<level|ident> Compile in version code >= <level> or identified by <ident>.
-fversion=<ident> Compile in version code identified by <ident>.
fweak-templates
D Var(flag_weak_templates) Init(1)

View File

@ -0,0 +1,10 @@
// REQUIRED_ARGS: -O -inline
//https://issues.dlang.org/show_bug.cgi?id=20143
real fun(int x) { return 0.0; }
double bug()
{
// value passed to fun is irrelevant
return 0.0 / fun(420);
}

View File

@ -45,16 +45,12 @@ alias Alias(T) = T;
static assert(is(Alias!(__traits(parent, Foo.bar)) == Foo));
extern(C++, "std"):
debug = 456;
debug = def;
version = 456;
version = def;
extern(C++, "std")
{
debug = 456;
debug = def;
version = 456;
version = def;
}

View File

@ -0,0 +1,16 @@
// https://issues.dlang.org/show_bug.cgi?id=23236
// can't initialize a @mustuse member in constructor
import core.attribute;
@mustuse struct MyError { }
struct S
{
MyError lastError;
this(int x)
{
this.lastError = MyError();
}
}

View File

@ -122,3 +122,31 @@ noreturn testdg(noreturn delegate() dg)
{
dg();
}
noreturn func()
{
while(1)
{
}
}
alias AliasSeq(T...) = T;
alias Types = AliasSeq!(bool, byte, ubyte, short, ushort, int, uint,
long, ulong, char, wchar, dchar, float, double,
real);
void noreturnImplicit()
{
/*
Testing both ways because, although the underlying table
is symmetrical the code that calls into it may be buggy.
*/
{
int x = 2 + func();
int y = func() + 2;
}
foreach(T; Types)
{
T value;
auto x = value + throw new Exception("Hello");
auto y = (throw new Exception("wow")) + value;
}
}

View File

@ -0,0 +1,12 @@
// PERMUTE_ARGS: -preview=dip1000
// https://issues.dlang.org/show_bug.cgi?id=20823
void boo(T)( scope void delegate(T[] data) fun) {}
void goo(T)(/+scope+/ void delegate(T[] data) fun) {}
void main()
{
void Execute(int[] data) {}
goo(&Execute);
boo(&Execute);
}

View File

@ -4,15 +4,19 @@ DISABLED: win
TEST_OUTPUT:
---
compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(111): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(150): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(151): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(152): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(153): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(200): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(203): Deprecation: format specifier `"%m"` is invalid
compilable/test21177.d(204): Deprecation: format specifier `"%m"` is invalid
compilable/test21177.d(205): Deprecation: argument `c` for format specification `"%a"` must be `float*`, not `char*`
compilable/test21177.d(206): Deprecation: argument `c` for format specification `"%a"` must be `float*`, not `char*`
compilable/test21177.d(154): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(155): Deprecation: more format specifiers than 0 arguments
compilable/test21177.d(202): Deprecation: format specifier `"%m"` is invalid
compilable/test21177.d(203): Deprecation: argument `d` for format specification `"%mc"` must be `char**`, not `int`
compilable/test21177.d(204): Deprecation: argument `c` for format specification `"%ms"` must be `char**`, not `char*`
compilable/test21177.d(205): Deprecation: format specifier `"%ml"` is invalid
compilable/test21177.d(206): Deprecation: argument `d` for format specification `"%mlc"` must be `wchar_t**`, not `int`
compilable/test21177.d(207): Deprecation: argument `c` for format specification `"%mls"` must be `wchar_t**`, not `char*`
---
*/
@ -27,50 +31,45 @@ void main()
#line 100
printf("%m this is a string in errno");
printf("%s %m", "str".ptr, 2);
printf("%a", 2.);
printf("%m %a", 2.);
printf("%m %m %s");
printf("%m");
printf("%*m");
pragma(msg, "compilable/test21177.d(111): Deprecation: more format specifiers than 0 arguments");
}
else
{
pragma(msg, "compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments");
printf("%m");
}
{
char* a, b;
sscanf("salut poilu", "%a %m", a, b);
sscanf("salut poilu", "%ms %m[^\n]", &a, &b);
assert(!strcmp(a, b));
free(a);
free(b);
char* t, p;
sscanf("Tomate Patate", "%ms %as", t, p);
char* t; wchar_t* p;
sscanf("Tomate Patate", "%mc %mlc", &t, &p);
free(t);
free(p);
#line 150
sscanf("150", "%m");
sscanf("151", "%ms");
sscanf("152", "%a");
sscanf("153", "%as");
pragma(msg, "compilable/test21177.d(200): Deprecation: more format specifiers than 0 arguments");
pragma(msg, "compilable/test21177.d(203): Deprecation: format specifier `\"%m\"` is invalid");
pragma(msg, "compilable/test21177.d(204): Deprecation: format specifier `\"%m\"` is invalid");
pragma(msg, "compilable/test21177.d(205): Deprecation: argument `c` for format specification `\"%a\"` must be `float*`, not `char*`");
pragma(msg, "compilable/test21177.d(206): Deprecation: argument `c` for format specification `\"%a\"` must be `float*`, not `char*`");
}
else
{
// fake it
pragma(msg, "compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments");
pragma(msg, "compilable/test21177.d(150): Deprecation: more format specifiers than 0 arguments");
pragma(msg, "compilable/test21177.d(151): Deprecation: more format specifiers than 0 arguments");
pragma(msg, "compilable/test21177.d(152): Deprecation: more format specifiers than 0 arguments");
pragma(msg, "compilable/test21177.d(153): Deprecation: more format specifiers than 0 arguments");
sscanf("152", "%mc");
sscanf("153", "%ml");
sscanf("154", "%mls");
sscanf("155", "%mlc");
#line 200
printf("%m");
char* c;
int d;
sscanf("204", "%m", c);
sscanf("205", "%ms", c);
sscanf("206", "%a", c);
sscanf("207", "%as", c);
sscanf("205", "%mc", d);
sscanf("206", "%ms", c);
sscanf("207", "%ml", d);
sscanf("208", "%mlc", d);
sscanf("209", "%mls", c);
}
}

View File

@ -0,0 +1,25 @@
// https://issues.dlang.org/show_bug.cgi?id=21432
auto issue21432()
{
enum int[] a = [];
return a;
}
enum test21432a = issue21432;
///////////////////////
double issue21432b(double r)
{
enum double[4] poly = [
0x1.ffffffffffdbdp-2,
0x1.555555555543cp-3,
0x1.55555cf172b91p-5,
0x1.1111167a4d017p-7,
];
immutable r2 = r * r;
return r + r2 * (poly[0] + r * poly[1]) + r2 * r2 * (poly[2] + r * poly[3]);
}
enum test21432b = issue21432b(-0x1p-1);

View File

@ -0,0 +1,8 @@
// https://issues.dlang.org/show_bug.cgi?id=22390
int main()
{
noreturn[] empty;
assert(empty == empty);
return 0;
}

View File

@ -0,0 +1,17 @@
// https://issues.dlang.org/show_bug.cgi?id=23082
/*
TEST_OUTPUT:
---
bar
---
*/
void foo()() {}
alias bar = foo;
void bar() { }
void main()
{
pragma(msg, __traits(parent, main).bar.stringof);
}

View File

@ -0,0 +1,22 @@
// REQUIRED_ARGS: -inline
// https://issues.dlang.org/show_bug.cgi?id=23166
// seg fault with -inline
bool __equals(scope const char[] lhs, scope const char[] rhs)
{
if (lhs.length != rhs.length)
return false;
{
import core.stdc.string : memcmp;
return lhs.length == 0;
}
return true;
}
int test(string type)
{
return __equals(type, "as-is");
}

View File

@ -0,0 +1,33 @@
// https://issues.dlang.org/show_bug.cgi?id=23172
enum E : ubyte { // `ubyte` is needed to trigger the bug
A,
B,
}
struct S {
E e;
}
void compiles(bool b, S s) {
E e = b ? E.A : s.e;
}
void errors(bool b, const ref S s) {
E e = b ? E.A : s.e;
}
// from https://issues.dlang.org/show_bug.cgi?id=23188
enum Status : byte
{
A, B, C
}
Status foo()
{
Status t = Status.A;
const Status s = t;
return (s == Status.A) ? Status.B : s; // <-- here
}

View File

@ -0,0 +1,20 @@
/* https://issues.dlang.org/show_bug.cgi?id=23235
*/
@safe:
void awkk(string[] ppp...)
{
}
void bark(string[] foo...) {
awkk(foo);
}
void cack(string[] bar...) {
bark(bar);
}
void test() {
cack("abc", "def");
}

View File

@ -0,0 +1,6 @@
/* REQUIRED_ARGS: -os=windows
*/
// https://issues.dlang.org/show_bug.cgi?id=23256
void test23256() { }

View File

@ -0,0 +1,17 @@
/* https://issues.dlang.org/show_bug.cgi?id=23262
*/
struct T()
{
string[] tags;
this(string[] tags...)
{
this.tags = tags; // don't infer `return` attribute for `tags`
}
}
void test()
{
T!() t;
}

View File

@ -0,0 +1,17 @@
/*
Tests to defend against false positives from the goto skips over decl errors
*/
// https://issues.dlang.org/show_bug.cgi?id=23271
class A {
private static A[] active;
private void test() {
foreach(a; active) {
if(a is this)
goto label;
}
// used to say Error: `goto` skips declaration of variable `s.A.test.__appendtmp4` at s.d(...)
active ~= this;
label:
return;
}
}

View File

@ -1,12 +1,20 @@
/*
TEST_OUTPUT:
---
fail_compilation/attributediagnostic.d(16): Error: `@safe` function `attributediagnostic.layer2` cannot call `@system` function `attributediagnostic.layer1`
fail_compilation/attributediagnostic.d(18): which calls `attributediagnostic.layer0`
fail_compilation/attributediagnostic.d(20): which calls `attributediagnostic.system`
fail_compilation/attributediagnostic.d(22): which was inferred `@system` because of:
fail_compilation/attributediagnostic.d(22): `asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not
fail_compilation/attributediagnostic.d(17): `attributediagnostic.layer1` is declared here
fail_compilation/attributediagnostic.d(24): Error: `@safe` function `attributediagnostic.layer2` cannot call `@system` function `attributediagnostic.layer1`
fail_compilation/attributediagnostic.d(26): which calls `attributediagnostic.layer0`
fail_compilation/attributediagnostic.d(28): which calls `attributediagnostic.system`
fail_compilation/attributediagnostic.d(30): which was inferred `@system` because of:
fail_compilation/attributediagnostic.d(30): `asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not
fail_compilation/attributediagnostic.d(25): `attributediagnostic.layer1` is declared here
fail_compilation/attributediagnostic.d(46): Error: `@safe` function `D main` cannot call `@system` function `attributediagnostic.system1`
fail_compilation/attributediagnostic.d(35): which was inferred `@system` because of:
fail_compilation/attributediagnostic.d(35): cast from `uint` to `int*` not allowed in safe code
fail_compilation/attributediagnostic.d(33): `attributediagnostic.system1` is declared here
fail_compilation/attributediagnostic.d(47): Error: `@safe` function `D main` cannot call `@system` function `attributediagnostic.system2`
fail_compilation/attributediagnostic.d(41): which was inferred `@system` because of:
fail_compilation/attributediagnostic.d(41): `@safe` function `system2` cannot call `@system` `fsys`
fail_compilation/attributediagnostic.d(39): `attributediagnostic.system2` is declared here
---
*/
@ -19,5 +27,22 @@ auto layer0() { system(); }
auto system()
{
asm {}
asm {}
}
auto system1()
{
int* x = cast(int*) 0xDEADBEEF;
}
auto fsys = function void() @system {};
auto system2()
{
fsys();
}
void main() @safe
{
system1();
system2();
}

View File

@ -169,3 +169,21 @@ void test409() { char* p; printf("%llu", p); }
void test410() { char* p; printf("%lld", p); }
void test411() { char* p; printf("%ju", p); }
void test412() { char* p; printf("%jd", p); }
/* https://issues.dlang.org/show_bug.cgi?id=23247
TEST_OUTPUT:
---
fail_compilation/chkformat.d(501): Deprecation: argument `p` for format specification `"%a"` must be `double`, not `char*`
fail_compilation/chkformat.d(502): Deprecation: argument `p` for format specification `"%La"` must be `real`, not `char*`
fail_compilation/chkformat.d(503): Deprecation: argument `p` for format specification `"%a"` must be `float*`, not `char*`
fail_compilation/chkformat.d(504): Deprecation: argument `p` for format specification `"%la"` must be `double*`, not `char*`
fail_compilation/chkformat.d(505): Deprecation: argument `p` for format specification `"%La"` must be `real*`, not `char*`
---
*/
#line 500
void test501() { char* p; printf("%a", p); }
void test502() { char* p; printf("%La", p); }
void test503() { char* p; scanf("%a", p); }
void test504() { char* p; scanf("%la", p); }
void test505() { char* p; scanf("%La", p); }

View File

@ -1,15 +1,17 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag10319.d(27): Error: `pure` function `D main` cannot call impure function `diag10319.foo`
fail_compilation/diag10319.d(27): Error: `@safe` function `D main` cannot call `@system` function `diag10319.foo`
fail_compilation/diag10319.d(16): `diag10319.foo` is declared here
fail_compilation/diag10319.d(28): Error: `pure` function `D main` cannot call impure function `diag10319.bar!int.bar`
fail_compilation/diag10319.d(28): Error: `@safe` function `D main` cannot call `@system` function `diag10319.bar!int.bar`
fail_compilation/diag10319.d(18): `diag10319.bar!int.bar` is declared here
fail_compilation/diag10319.d(27): Error: function `diag10319.foo` is not `nothrow`
fail_compilation/diag10319.d(28): Error: function `diag10319.bar!int.bar` is not `nothrow`
fail_compilation/diag10319.d(25): Error: function `D main` may throw but is marked as `nothrow`
fail_compilation/diag10319.d(29): Error: `pure` function `D main` cannot call impure function `diag10319.foo`
fail_compilation/diag10319.d(29): Error: `@safe` function `D main` cannot call `@system` function `diag10319.foo`
fail_compilation/diag10319.d(18): `diag10319.foo` is declared here
fail_compilation/diag10319.d(30): Error: `pure` function `D main` cannot call impure function `diag10319.bar!int.bar`
fail_compilation/diag10319.d(30): Error: `@safe` function `D main` cannot call `@system` function `diag10319.bar!int.bar`
fail_compilation/diag10319.d(23): which was inferred `@system` because of:
fail_compilation/diag10319.d(23): cannot take address of local `x` in `@safe` function `bar`
fail_compilation/diag10319.d(20): `diag10319.bar!int.bar` is declared here
fail_compilation/diag10319.d(29): Error: function `diag10319.foo` is not `nothrow`
fail_compilation/diag10319.d(30): Error: function `diag10319.bar!int.bar` is not `nothrow`
fail_compilation/diag10319.d(27): Error: function `D main` may throw but is marked as `nothrow`
---
*/

View File

@ -1,12 +1,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag11198.d(15): Error: version `blah` declaration must be at module level
fail_compilation/diag11198.d(16): Error: debug `blah` declaration must be at module level
fail_compilation/diag11198.d(17): Error: version `1` level declaration must be at module level
fail_compilation/diag11198.d(18): Error: debug `2` level declaration must be at module level
fail_compilation/diag11198.d(19): Error: identifier or integer expected, not `""`
fail_compilation/diag11198.d(20): Error: identifier or integer expected, not `""`
fail_compilation/diag11198.d(17): Error: version `blah` declaration must be at module level
fail_compilation/diag11198.d(18): Error: debug `blah` declaration must be at module level
fail_compilation/diag11198.d(19): Deprecation: `version = <integer>` is deprecated, use version identifiers instead
fail_compilation/diag11198.d(19): Error: version `1` level declaration must be at module level
fail_compilation/diag11198.d(20): Deprecation: `debug = <integer>` is deprecated, use debug identifiers instead
fail_compilation/diag11198.d(20): Error: debug `2` level declaration must be at module level
fail_compilation/diag11198.d(21): Error: identifier or integer expected, not `""`
fail_compilation/diag11198.d(22): Error: identifier or integer expected, not `""`
---
*/

View File

@ -1,11 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag12829.d(12): Error: function `diag12829.test1` is `@nogc` yet allocates closures with the GC
fail_compilation/diag12829.d(15): diag12829.test1.__lambda2 closes over variable x at fail_compilation/diag12829.d(14)
fail_compilation/diag12829.d(19): diag12829.test1.bar closes over variable x at fail_compilation/diag12829.d(14)
fail_compilation/diag12829.d(26): Error: function `diag12829.test2` is `@nogc` yet allocates closures with the GC
fail_compilation/diag12829.d(31): diag12829.test2.S.foo closes over variable x at fail_compilation/diag12829.d(28)
fail_compilation/diag12829.d(12): Error: function `diag12829.test1` is `@nogc` yet allocates closure for `test1()` with the GC
fail_compilation/diag12829.d(15): `diag12829.test1.__lambda2` closes over variable `x` at fail_compilation/diag12829.d(14)
fail_compilation/diag12829.d(19): `diag12829.test1.bar` closes over variable `x` at fail_compilation/diag12829.d(14)
fail_compilation/diag12829.d(26): Error: function `diag12829.test2` is `@nogc` yet allocates closure for `test2()` with the GC
fail_compilation/diag12829.d(31): `diag12829.test2.S.foo` closes over variable `x` at fail_compilation/diag12829.d(28)
---
*/

View File

@ -1,15 +1,17 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail118.d(43): Error: invalid `foreach` aggregate `Iter` of type `Iter`
fail_compilation/fail118.d(43): maybe define `opApply()`, range primitives, or use `.tupleof`
fail_compilation/fail118.d(44): Error: invalid `foreach` aggregate `Iter` of type `Iter`
fail_compilation/fail118.d(44): maybe define `opApply()`, range primitives, or use `.tupleof`
fail_compilation/fail118.d(47): Error: invalid `foreach` aggregate `s` of type `S*`
fail_compilation/fail118.d(49): Error: undefined identifier `unknown`
fail_compilation/fail118.d(37): Error: undefined identifier `doesNotExist`
fail_compilation/fail118.d(51): Error: template instance `fail118.error!()` error instantiating
fail_compilation/fail118.d(51): Error: invalid `foreach` aggregate `error()` of type `void`
fail_compilation/fail118.d(45): Error: invalid `foreach` aggregate `Iter` of type `Iter`
fail_compilation/fail118.d(45): `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
fail_compilation/fail118.d(45): https://dlang.org/phobos/std_range_primitives.html#isInputRange
fail_compilation/fail118.d(46): Error: invalid `foreach` aggregate `Iter` of type `Iter`
fail_compilation/fail118.d(46): `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
fail_compilation/fail118.d(46): https://dlang.org/phobos/std_range_primitives.html#isInputRange
fail_compilation/fail118.d(49): Error: invalid `foreach` aggregate `s` of type `S*`
fail_compilation/fail118.d(51): Error: undefined identifier `unknown`
fail_compilation/fail118.d(39): Error: undefined identifier `doesNotExist`
fail_compilation/fail118.d(53): Error: template instance `fail118.error!()` error instantiating
fail_compilation/fail118.d(53): Error: invalid `foreach` aggregate `error()` of type `void`
---
*/

View File

@ -1,15 +0,0 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail20547.d(12): Error: cannot create a `string[string]` with `new`
fail_compilation/fail20547.d(14): Error: cannot create a `string[string]` with `new`
---
*/
void main()
{
//https://issues.dlang.org/show_bug.cgi?id=11790
string[string] crash = new string[string];
//https://issues.dlang.org/show_bug.cgi?id=20547
int[string] c = new typeof(crash);
}

View File

@ -0,0 +1,17 @@
// https://issues.dlang.org/show_bug.cgi?id=22134
/* REQUIRED_ARGS: -de
TEST_OUTPUT:
---
fail_compilation/fail22134.d(12): Deprecation: `this.arr[i]` has no effect
---
*/
struct StackBuffer
{
auto opIndex(size_t i)
{
return arr[i];
}
private:
void[] arr;
}

View File

@ -0,0 +1,16 @@
/* https://issues.dlang.org/show_bug.cgi?id=23181
TEST_OUTPUT:
---
$p:druntime/import/core/lifetime.d$($n$): Error: struct `fail23181.fail23181.NoPostblit` is not copyable because it has a disabled postblit
$p:druntime/import/core/internal/array/construction.d$($n$): Error: template instance `core.lifetime.copyEmplace!(NoPostblit, NoPostblit)` error instantiating
fail_compilation/fail23181.d(15): instantiated from here: `_d_arraysetctor!(NoPostblit[], NoPostblit)`
---
*/
void fail23181()
{
struct NoPostblit
{
@disable this(this);
}
NoPostblit[4] noblit23181 = NoPostblit();
}

View File

@ -1,8 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail261.d(19): Error: invalid `foreach` aggregate `range` of type `MyRange`
fail_compilation/fail261.d(19): maybe define `opApply()`, range primitives, or use `.tupleof`
fail_compilation/fail261.d(20): Error: invalid `foreach` aggregate `range` of type `MyRange`
fail_compilation/fail261.d(20): `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
fail_compilation/fail261.d(20): https://dlang.org/phobos/std_range_primitives.html#isInputRange
---
*/

View File

@ -7,7 +7,7 @@ fail_compilation/fail58.d(30): Error: function `fail58.SomeFunc(dchar[] pText, o
fail_compilation/fail58.d(30): cannot pass argument `""` of type `string` to parameter `dchar[] pText`
---
*/
debug(1) import std.stdio;
debug import std.stdio;
const int anything = -1000; // Line #2
dchar[] SomeFunc( dchar[] pText, out int pStopPosn)
{
@ -15,7 +15,7 @@ dchar[] SomeFunc( dchar[] pText, out int pStopPosn)
pStopPosn = 0;
else
pStopPosn = -1;
debug(1) writefln("DEBUG: using '%s' we get %d", pText, pStopPosn);
debug writefln("DEBUG: using '%s' we get %d", pText, pStopPosn);
return pText.dup;
}
@ -24,12 +24,12 @@ int main(char[][] pArgs)
int sp;
SomeFunc("123", sp);
debug(1) writefln("DEBUG: got %d", sp);
debug writefln("DEBUG: got %d", sp);
assert(sp == -1);
SomeFunc("", sp);
// if (sp != 0){} // Line #22
debug(1) writefln("DEBUG: got %d", sp);
debug writefln("DEBUG: got %d", sp);
assert(sp == -1);
return 0;
}

View File

@ -55,7 +55,7 @@ L1:
scope(failure) { L2: goto L1; } // OK
goto L2; // NG
scope(failure) { return; } // OK
foreach (i; 0..1)
{

View File

@ -9,12 +9,12 @@ fail_compilation/fail7848.d(21): `fail7848.func` is declared here
fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow`
fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow`
fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant1` cannot call impure function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant1` cannot call `@system` function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant0` cannot call impure function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant0` cannot call `@system` function `fail7848.func`
fail_compilation/fail7848.d(21): `fail7848.func` is declared here
fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant1` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant0` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow`
fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant1` may throw but is marked as `nothrow`
fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant0` may throw but is marked as `nothrow`
---
*/

View File

@ -1,8 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice11856_1.d(13): Error: none of the overloads of template `ice11856_1.g` are callable using argument types `!()(A)`
fail_compilation/ice11856_1.d(11): Candidate is: `g(T)(T x)`
fail_compilation/ice11856_1.d(16): Error: none of the overloads of template `ice11856_1.g` are callable using argument types `!()(A)`
fail_compilation/ice11856_1.d(14): Candidate is: `g(T)(T x)`
with `T = A`
must satisfy the following constraint:
` is(typeof(x.f()))`
---
*/
struct A {}

View File

@ -10,7 +10,6 @@ fail_compilation/misc_parser_err_cov1.d(31): Error: expression expected, not `)`
fail_compilation/misc_parser_err_cov1.d(32): Error: `type identifier : specialization` expected following `is`
fail_compilation/misc_parser_err_cov1.d(33): Error: semicolon expected following auto declaration, not `auto`
fail_compilation/misc_parser_err_cov1.d(33): Error: found `+` when expecting `(` following `mixin`
fail_compilation/misc_parser_err_cov1.d(34): Error: cannot create a `char[float]` with `new`
fail_compilation/misc_parser_err_cov1.d(35): Error: `key:value` expected for associative array literal
fail_compilation/misc_parser_err_cov1.d(36): Error: basic type expected, not `;`
fail_compilation/misc_parser_err_cov1.d(36): Error: `{ members }` expected for anonymous class
@ -44,7 +43,7 @@ void main()
auto tt = __traits(<o<);
auto b = is ;
auto mx1 = mixin +);
auto aa1 = new char[float];
aa += [key:value, key];
auto anon1 = new class;
auto anon2 = new class {};

View File

@ -0,0 +1,19 @@
/*
TEST_OUTPUT:
---
fail_compilation/newaa.d(14): Error: cannot implicitly convert expression `new string[string]` of type `string[string]` to `int[string]`
fail_compilation/newaa.d(15): Error: function expected before `()`, not `new int[int]` of type `int[int]`
fail_compilation/newaa.d(17): Error: `new` cannot take arguments for an associative array
---
*/
#line 9
void main()
{
//https://issues.dlang.org/show_bug.cgi?id=11790
string[string] crash = new string[string];
//https://issues.dlang.org/show_bug.cgi?id=20547
int[string] c = new typeof(crash);
auto d = new int[int](5);
alias AA = char[string];
auto e = new AA(5);
}

View File

@ -43,10 +43,10 @@ fail_compilation/nogc3.d(35): Error: `@nogc` function `nogc3.testCall` cannot ca
/*
TEST_OUTPUT:
---
fail_compilation/nogc3.d(52): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closures with the GC
fail_compilation/nogc3.d(55): nogc3.testClosure1.bar closes over variable x at fail_compilation/nogc3.d(54)
fail_compilation/nogc3.d(64): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closures with the GC
fail_compilation/nogc3.d(67): nogc3.testClosure3.bar closes over variable x at fail_compilation/nogc3.d(66)
fail_compilation/nogc3.d(52): Error: function `nogc3.testClosure1` is `@nogc` yet allocates closure for `testClosure1()` with the GC
fail_compilation/nogc3.d(55): `nogc3.testClosure1.bar` closes over variable `x` at fail_compilation/nogc3.d(54)
fail_compilation/nogc3.d(64): Error: function `nogc3.testClosure3` is `@nogc` yet allocates closure for `testClosure3()` with the GC
fail_compilation/nogc3.d(67): `nogc3.testClosure3.bar` closes over variable `x` at fail_compilation/nogc3.d(66)
---
*/
@nogc auto testClosure1()

View File

@ -54,8 +54,8 @@ void test2(scope int* p, int[] a ...) @safe
/*
TEST_OUTPUT:
---
fail_compilation/retscope.d(75): Error: function `retscope.HTTP.Impl.onReceive` is `@nogc` yet allocates closures with the GC
fail_compilation/retscope.d(77): retscope.HTTP.Impl.onReceive.__lambda1 closes over variable this at fail_compilation/retscope.d(75)
fail_compilation/retscope.d(75): Error: function `retscope.HTTP.Impl.onReceive` is `@nogc` yet allocates closure for `onReceive()` with the GC
fail_compilation/retscope.d(77): `retscope.HTTP.Impl.onReceive.__lambda1` closes over variable `this` at fail_compilation/retscope.d(75)
---
*/

View File

@ -1,11 +1,13 @@
/*
TEST_OUTPUT:
---
fail_compilation/test13786.d(14): Error: debug `123` level declaration must be at module level
fail_compilation/test13786.d(15): Error: debug `abc` declaration must be at module level
fail_compilation/test13786.d(16): Error: version `123` level declaration must be at module level
fail_compilation/test13786.d(17): Error: version `abc` declaration must be at module level
fail_compilation/test13786.d(20): Error: template instance `test13786.T!()` error instantiating
fail_compilation/test13786.d(16): Deprecation: `debug = <integer>` is deprecated, use debug identifiers instead
fail_compilation/test13786.d(18): Deprecation: `version = <integer>` is deprecated, use version identifiers instead
fail_compilation/test13786.d(16): Error: debug `123` level declaration must be at module level
fail_compilation/test13786.d(17): Error: debug `abc` declaration must be at module level
fail_compilation/test13786.d(18): Error: version `123` level declaration must be at module level
fail_compilation/test13786.d(19): Error: version `abc` declaration must be at module level
fail_compilation/test13786.d(22): Error: template instance `test13786.T!()` error instantiating
---
*/

View File

@ -2,8 +2,8 @@
REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/test16193.d(38): Error: function `test16193.abc` is `@nogc` yet allocates closures with the GC
fail_compilation/test16193.d(40): test16193.abc.__foreachbody2 closes over variable x at fail_compilation/test16193.d(39)
fail_compilation/test16193.d(38): Error: function `test16193.abc` is `@nogc` yet allocates closure for `abc()` with the GC
fail_compilation/test16193.d(40): `test16193.abc.__foreachbody2` closes over variable `x` at fail_compilation/test16193.d(39)
---
*/
//fail_compilation/test16193.d(22): To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`

View File

@ -0,0 +1,21 @@
// https://issues.dlang.org/show_bug.cgi?id=21443
// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
fail_compilation/test21443.d(14): Deprecation: `return` statements cannot be in `scope(failure)` bodies.
fail_compilation/test21443.d(14): Use try-catch blocks for this purpose
---
*/
ulong get () @safe nothrow
{
scope (failure) return 10;
throw new Error("");
}
void main () @safe
{
assert(get() == 10); // passes
}

View File

@ -2,14 +2,14 @@
PERMUTE_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closures with the GC
fail_compilation/test21912.d(26): test21912.escapeParam.__lambda2 closes over variable i at fail_compilation/test21912.d(24)
fail_compilation/test21912.d(29): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closures with the GC
fail_compilation/test21912.d(31): test21912.escapeAssign.__lambda3 closes over variable i at fail_compilation/test21912.d(29)
fail_compilation/test21912.d(40): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closures with the GC
fail_compilation/test21912.d(42): test21912.escapeAssignRef.__lambda3 closes over variable i at fail_compilation/test21912.d(40)
fail_compilation/test21912.d(51): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closures with the GC
fail_compilation/test21912.d(53): test21912.escapeParamInferred.__lambda2 closes over variable i at fail_compilation/test21912.d(51)
fail_compilation/test21912.d(24): Error: function `test21912.escapeParam` is `@nogc` yet allocates closure for `escapeParam()` with the GC
fail_compilation/test21912.d(26): `test21912.escapeParam.__lambda2` closes over variable `i` at fail_compilation/test21912.d(24)
fail_compilation/test21912.d(29): Error: function `test21912.escapeAssign` is `@nogc` yet allocates closure for `escapeAssign()` with the GC
fail_compilation/test21912.d(31): `test21912.escapeAssign.__lambda3` closes over variable `i` at fail_compilation/test21912.d(29)
fail_compilation/test21912.d(40): Error: function `test21912.escapeAssignRef` is `@nogc` yet allocates closure for `escapeAssignRef()` with the GC
fail_compilation/test21912.d(42): `test21912.escapeAssignRef.__lambda3` closes over variable `i` at fail_compilation/test21912.d(40)
fail_compilation/test21912.d(51): Error: function `test21912.escapeParamInferred` is `@nogc` yet allocates closure for `escapeParamInferred()` with the GC
fail_compilation/test21912.d(53): `test21912.escapeParamInferred.__lambda2` closes over variable `i` at fail_compilation/test21912.d(51)
---
*/
@nogc:

View File

@ -2,8 +2,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/test21939.d(10): Error: invalid `foreach` aggregate `Object` of type `Object`
fail_compilation/test21939.d(10): maybe define `opApply()`, range primitives, or use `.tupleof`
fail_compilation/test21939.d(11): Error: invalid `foreach` aggregate `Object` of type `Object`
fail_compilation/test21939.d(11): `foreach` works with input ranges (implementing `front` and `popFront`), aggregates implementing `opApply`, or the result of an aggregate's `.tupleof` property
fail_compilation/test21939.d(11): https://dlang.org/phobos/std_range_primitives.html#isInputRange
---
*/

View File

@ -0,0 +1,15 @@
/*
REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/test23022.d(14): Error: scope parameter `p` may not be returned
---
*/
// https://issues.dlang.org/show_bug.cgi?id=23022
// Typesafe variadic parameter should not infer return
auto ir(string[] p...)
{
return p;
}

View File

@ -0,0 +1,30 @@
/* REQUIRED_ARGS: -betterC
TEST_OUTPUT:
---
fail_compilation/test23112.d(106): Error: function `test23112.bar` is `@nogc` yet allocates closure for `bar()` with the GC
fail_compilation/test23112.d(108): `test23112.bar.f` closes over variable `a` at fail_compilation/test23112.d(106)
---
*/
// https://issues.dlang.org/show_bug.cgi?id=23112
#line 100
struct Forward(alias F)
{
auto call()() { return F(); }
}
auto bar(int a) nothrow @safe
{
auto f()
{
return a;
}
return Forward!f();
}
extern(C) void main()
{
assert(bar(3).call() == 3);
}

View File

@ -0,0 +1,12 @@
/*
TEST_OUTPUT:
---
fail_compilation/test23170.d(10): Error: array literal in `@nogc` delegate `test23170.__lambda5` may cause a GC allocation
---
*/
// https://issues.dlang.org/show_bug.cgi?id=23170
@nogc:
enum lambda = () => badAlias([1, 2, 3]);
alias badAlias = (int[] array) => id(array);
int[] id(int[] array) { return array; }

View File

@ -0,0 +1,24 @@
/*
TEST_OUTPUT:
---
fail_compilation/test23216.d(23): Error: invalid `foreach_reverse` aggregate `r` of type `Range`
fail_compilation/test23216.d(23): `foreach_reverse` works with bidirectional ranges (implementing `back` and `popBack`), aggregates implementing `opApplyReverse`, or the result of an aggregate's `.tupleof` property
fail_compilation/test23216.d(23): https://dlang.org/phobos/std_range_primitives.html#isBidirectionalRange
---
*/
// https://issues.dlang.org/show_bug.cgi?id=23216
// Better Error Message For foreach_reverse Without Bidirectional Range
struct Range
{
bool empty = true;
int front = 0;
void popFront() { }
}
void main()
{
Range r;
foreach_reverse (word; r) { }
}

View File

@ -922,7 +922,10 @@ void test14730()
// This is questionable case. Currently it works without any errors,
// but not sure it's really intentional
// It showed up again in https://issues.dlang.org/show_bug.cgi?id=23112
// where it's an @safe issue so it's a bug.
static if (0)
{
struct S14730x(alias f)
{
auto foo()() { return f(0); }
@ -947,6 +950,7 @@ void test14730x()
// *after* the semantic3 completion of makeS() function.
assert(s.foo() == 10);
}
}
/************************************/
@ -981,7 +985,7 @@ int main()
test9685b();
test12406();
test14730();
test14730x();
//test14730x();
printf("Success\n");
return 0;

View File

@ -46,6 +46,12 @@ int mul11ret3(T)(ref T s)
return 3;
}
auto cat11ret3(T)(ref T s)
{
s ~= 11;
return [3];
}
void add()
{
static int test1(int val) { val += add8ret3(val); return val; }
@ -147,6 +153,25 @@ void shr()
static assert(test(0x80) == 0x40);
}
void cat()
{
static auto test1(int[] val) { val ~= cat11ret3(val); return val; }
assert(test1([1]) == [1, 11, 3]);
static assert(test1([1]) == [1, 11, 3]);
static auto test2(int[] val) { val = val ~ cat11ret3(val); return val; }
// FIXME: assert(test2([1]) == [1, 3]);
static assert(test2([1]) == [1, 3]);
static auto test3(int[] val) { (val ~= 7) ~= cat11ret3(val); return val; }
assert(test3([2]) == [2, 7, 11, 3]);
static assert(test3([2]) == [2, 7, 11, 3]);
static auto test4(int[] val) { (val ~= cat11ret3(val)) ~= 7; return val; }
assert(test4([2]) == [2, 11, 3, 7]);
static assert(test4([2]) == [2, 11, 3, 7]);
}
void ldc_github_1617()
{
add();
@ -156,6 +181,7 @@ void ldc_github_1617()
addptr();
lhsCast();
shr();
cat();
}
/******************************************/

View File

@ -1,5 +1,11 @@
// REQUIRED_ARGS:
/*
TEST_OUTPUT:
---
runnable/lexer.d(81): Deprecation: `version( <integer> )` is deprecated, use version identifiers instead
runnable/lexer.d(82): Deprecation: `debug( <integer> )` is deprecated, use debug identifiers instead
---
*/
/*********************************************************/

View File

@ -261,6 +261,37 @@ void testThrowDtor()
/*****************************************/
noreturn func()
{
throw new Exception("B");
}
// https://issues.dlang.org/show_bug.cgi?id=23120
void test23120()
{
string a;
try
{
noreturn q = throw new Exception ("A");
}
catch(Exception e)
{
a ~= e.msg;
}
try
{
noreturn z = func();
}
catch(Exception e)
{
a ~= e.msg;
}
assert(a == "AB");
}
/*****************************************/
int main()
{
test1();
@ -269,5 +300,6 @@ int main()
testThrowExpression();
testThrowSideEffect();
testThrowDtor();
test23120();
return 0;
}

View File

@ -1193,41 +1193,6 @@ void test63()
printf("%.*s\n", cast(int)s.length, s.ptr);
}
/**************************************/
debug = 3;
void test64()
{
debug(5)
{
assert(0);
}
debug(3)
{
int x = 3;
}
assert(x == 3);
}
/**************************************/
version = 3;
void test65()
{
version(5)
{
assert(0);
}
version(3)
{
int x = 3;
}
assert(x == 3);
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=8809
@ -1381,8 +1346,6 @@ int main(string[] argv)
test61();
test62();
test63();
test64();
test65();
test8809();
test9734();

View File

@ -0,0 +1,25 @@
// This is a runnable test as we are testing a linker error
// https://issues.dlang.org/show_bug.cgi?id=18973
struct X {
@disable size_t toHash() const;
@disable string toString() const;
@disable bool opEquals(const ref X) const;
@disable int opCmp(const ref X) const;
}
// https://issues.dlang.org/show_bug.cgi?id=9161
public struct dummy
{
static auto opCall(C)(in C[] name)
{
return name;
}
@disable ~this(); //comment this out to avoid error
}
void main()
{
assert(dummy("ABCDE") == "ABCDE");
}

View File

@ -59,22 +59,7 @@ void test2()
void test3()
{
debug printf("debug\n");
debug(1) printf("debug(1)\n");
debug(2) printf("debug(2)\n");
debug(3) printf("debug(3)\n");
debug(bar) printf("debug(bar)\n");
debug(10) assert(0);
debug(1)
{
int d1 = 3;
printf("debug(1) { }\n");
}
debug(2)
{
printf("debug(2): d1 = %d\n", d1);
}
}
/* ================================ */

View File

@ -16,6 +16,7 @@ extern(C) int main() nothrow @nogc @safe
{
takeScopeSlice([ S(1), S(2) ]); // @nogc => no GC allocation
(() @trusted { assert(numDtor == 2); })(); // stack-allocated array literal properly destructed
assert23100([]);
return 0;
}
@ -26,3 +27,9 @@ void test23098() @safe
{
f23098([10, 20]);
}
// https://issues.dlang.org/show_bug.cgi?id=23100
void assert23100(scope int[] d) @safe nothrow @nogc
{
assert(!d);
}

View File

@ -0,0 +1,27 @@
// https://issues.dlang.org/show_bug.cgi?id=23181
void main()
{
int count;
struct HasDtor
{
~this() { ++count; }
}
// array[] = elem()
// -> creates temporary to construct array and calls destructor.
{
count = 0;
HasDtor[4] dtor1 = HasDtor();
assert(count == 1);
}
assert(count == 5);
// array[] = array[elem()]
// -> constructs array using direct emplacement.
{
count = 0;
HasDtor[2] dtor2 = [HasDtor(), HasDtor()];
assert(count == 0);
}
assert(count == 2);
}

View File

@ -591,6 +591,44 @@ void test34()
assert(b[i][j] == 16);
}
/***********************************/
// https://issues.dlang.org/show_bug.cgi?id=19178
float[3][4] arr2f = 10;
Int3_4[1] arr3i = 20;
short[3][4][1][1] arr4s = 30;
enum Int3 : int[3] {
a = [0, 1, 2],
}
enum Int3_4 : Int3[4] {
b = Int3[4].init,
}
struct S35
{
int[3][3] arr = [2, 1];
}
void test35()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
// printf("[%d %d]: %f %d %d\n", i, j, arr2f[i][j], arr3i[0][i][j], arr4s[0][0][i][j]);
assert(arr2f[i][j] == 10);
assert(arr3i[0][i][j] == 20);
assert(arr4s[0][0][i][j] == 30);
}
}
S35 t = S35.init;
assert(t.arr[0] == [2, 2, 2]);
assert(t.arr[1] == [1, 1, 1]);
assert(t.arr[2] == [0, 0, 0]);
}
/***********************************/
string itoa(int i)
@ -868,6 +906,7 @@ int main()
test32();
test33();
test34();
test35();
test36();
test37();
test38();

View File

@ -1,10 +1,9 @@
/*
PERMUTE_ARGS:
REQUIRED_ARGS: -version=3 -version=foo
REQUIRED_ARGS: -version=foo
RUN_OUTPUT:
---
i = 2
i = 2
---
*/
@ -15,20 +14,6 @@ extern(C) int printf(const char*, ...);
void test1()
{
int i = 3;
version(2)
{
i = 2;
}
else
{
i = 0;
}
printf("i = %d\n", i);
assert(i == 2);
i = 3;
version(foo)
{
i = 2;
@ -47,10 +32,6 @@ version(foo)
{
version = bar;
}
else
{
version = 4;
}
void test2()
{
@ -59,8 +40,6 @@ void test2()
}
else
assert(0);
version(4) assert(0);
}
/*******************************************/

View File

@ -133,15 +133,6 @@ void test6518()
}
}
/******************************************/
// https://issues.dlang.org/show_bug.cgi?id=7232
bool test7232()
{
scope(failure) return false;
return true;
}
/***************************************************/
struct S9332

2
libphobos/configure vendored
View File

@ -15554,7 +15554,7 @@ SPEC_PHOBOS_DEPS="$LIBS"
# Libdruntime / phobos soname version
libtool_VERSION=3:0:0
libtool_VERSION=4:0:0
# Set default flags (after DRUNTIME_WERROR!)

View File

@ -253,7 +253,7 @@ SPEC_PHOBOS_DEPS="$LIBS"
AC_SUBST(SPEC_PHOBOS_DEPS)
# Libdruntime / phobos soname version
libtool_VERSION=3:0:0
libtool_VERSION=4:0:0
AC_SUBST(libtool_VERSION)
# Set default flags (after DRUNTIME_WERROR!)

View File

@ -1,4 +1,4 @@
651389b52243dcadb338dd0c14dd27e7850cda8d
d7772a236983ec37b92d21b28bad3cd2de57b945
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
merge done from the dlang/dmd repository.

View File

@ -174,14 +174,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/internal/array/appending.d core/internal/array/capacity.d \
core/internal/array/casting.d core/internal/array/comparison.d \
core/internal/array/concatenation.d core/internal/array/construction.d \
core/internal/array/equality.d core/internal/array/operations.d \
core/internal/array/utils.d core/internal/atomic.d \
core/internal/attributes.d core/internal/container/array.d \
core/internal/container/common.d core/internal/container/hashtab.d \
core/internal/container/treap.d core/internal/convert.d \
core/internal/dassert.d core/internal/destruction.d \
core/internal/entrypoint.d core/internal/gc/bits.d \
core/internal/gc/impl/conservative/gc.d \
core/internal/array/duplication.d core/internal/array/equality.d \
core/internal/array/operations.d core/internal/array/utils.d \
core/internal/atomic.d core/internal/attributes.d \
core/internal/container/array.d core/internal/container/common.d \
core/internal/container/hashtab.d core/internal/container/treap.d \
core/internal/convert.d core/internal/dassert.d \
core/internal/destruction.d core/internal/entrypoint.d \
core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
core/internal/gc/os.d core/internal/gc/pooltable.d \
core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \

View File

@ -196,6 +196,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
core/internal/array/comparison.lo \
core/internal/array/concatenation.lo \
core/internal/array/construction.lo \
core/internal/array/duplication.lo \
core/internal/array/equality.lo \
core/internal/array/operations.lo core/internal/array/utils.lo \
core/internal/atomic.lo core/internal/attributes.lo \
@ -841,14 +842,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/internal/array/appending.d core/internal/array/capacity.d \
core/internal/array/casting.d core/internal/array/comparison.d \
core/internal/array/concatenation.d core/internal/array/construction.d \
core/internal/array/equality.d core/internal/array/operations.d \
core/internal/array/utils.d core/internal/atomic.d \
core/internal/attributes.d core/internal/container/array.d \
core/internal/container/common.d core/internal/container/hashtab.d \
core/internal/container/treap.d core/internal/convert.d \
core/internal/dassert.d core/internal/destruction.d \
core/internal/entrypoint.d core/internal/gc/bits.d \
core/internal/gc/impl/conservative/gc.d \
core/internal/array/duplication.d core/internal/array/equality.d \
core/internal/array/operations.d core/internal/array/utils.d \
core/internal/atomic.d core/internal/attributes.d \
core/internal/container/array.d core/internal/container/common.d \
core/internal/container/hashtab.d core/internal/container/treap.d \
core/internal/convert.d core/internal/dassert.d \
core/internal/destruction.d core/internal/entrypoint.d \
core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
core/internal/gc/os.d core/internal/gc/pooltable.d \
core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
@ -1208,6 +1209,8 @@ core/internal/array/concatenation.lo: \
core/internal/array/$(am__dirstamp)
core/internal/array/construction.lo: \
core/internal/array/$(am__dirstamp)
core/internal/array/duplication.lo: \
core/internal/array/$(am__dirstamp)
core/internal/array/equality.lo: core/internal/array/$(am__dirstamp)
core/internal/array/operations.lo: \
core/internal/array/$(am__dirstamp)

View File

@ -170,6 +170,8 @@ public:
bool hle() {return _hle;}
/// Is RTM (restricted transactional memory) supported
bool rtm() {return _rtm;}
/// Is AVX512F supported
bool avx512f() {return _avx512f;}
/// Is rdseed supported
bool hasRdseed() {return _hasRdseed;}
/// Is SHA supported
@ -279,6 +281,7 @@ private immutable
bool _avx2;
bool _hle;
bool _rtm;
bool _avx512f;
bool _hasRdseed;
bool _hasSha;
bool _amd3dnow;
@ -389,6 +392,7 @@ CpuFeatures* getCpuFeatures() @nogc nothrow
enum : uint
{
FSGSBASE_BIT = 1 << 0,
SGX_BIT = 1 << 2,
BMI1_BIT = 1 << 3,
HLE_BIT = 1 << 4,
AVX2_BIT = 1 << 5,
@ -397,8 +401,19 @@ CpuFeatures* getCpuFeatures() @nogc nothrow
ERMS_BIT = 1 << 9,
INVPCID_BIT = 1 << 10,
RTM_BIT = 1 << 11,
AVX512F_BIT = 1 << 16,
AVX512DQ_BIT = 1 << 17,
RDSEED_BIT = 1 << 18,
ADX_BIT = 1 << 19,
AVX512IFMA_BIT = 1 << 21,
CLFLUSHOPT_BIT = 1 << 23,
CLWB_BIT = 1 << 24,
AVX512PF_BIT = 1 << 26,
AVX512ER_BIT = 1 << 27,
AVX512CD_BIT = 1 << 28,
SHA_BIT = 1 << 29,
AVX512BW_BIT = 1 << 30,
AVX512VL_BIT = 1 << 31,
}
// feature flags XFEATURES_ENABLED_MASK
enum : ulong
@ -1122,6 +1137,7 @@ shared static this()
_avx2 = avx && (cf.extfeatures & AVX2_BIT) != 0;
_hle = (cf.extfeatures & HLE_BIT) != 0;
_rtm = (cf.extfeatures & RTM_BIT) != 0;
_avx512f = (cf.extfeatures & AVX512F_BIT) != 0;
_hasRdseed = (cf.extfeatures&RDSEED_BIT)!=0;
_hasSha = (cf.extfeatures&SHA_BIT)!=0;
_amd3dnow = (cf.amdfeatures&AMD_3DNOW_BIT)!=0;

View File

@ -943,5 +943,3 @@ unittest
assert(rol(C7_9, 1) == rol1(C7_9));
assert(ror(C7_9, 1) == ror1(C7_9));
}

View File

@ -30,26 +30,14 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
* Returns:
* The new value of `px`
* Bugs:
* This function template was ported from a much older runtime hook that bypassed safety,
* purity, and throwabilty checks. To prevent breaking existing code, this function template
* is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
* This function template was ported from a much older runtime hook that bypassed safety,
* purity, and throwabilty checks. To prevent breaking existing code, this function template
* is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
*/
static if (isCopyingNothrow!T) // `nothrow` deduction doesn't work, so this is needed
ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
{
pragma(inline, false);
mixin(_d_arrayappendcTXBody);
}
else
ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
{
pragma(inline, false);
mixin(_d_arrayappendcTXBody);
}
private enum _d_arrayappendcTXBody = q{
ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
{
// needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718
pragma(inline, false);
version (D_TypeInfo)
{
auto ti = typeid(Tarr);
@ -64,7 +52,7 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
}
else
assert(0, "Cannot append arrays if compiling without support for runtime type information!");
};
}
/**
* TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl).

View File

@ -0,0 +1,346 @@
/**
The `.dup` and `.idup` properties for Associative Arrays and Dynamic Arrays
Copyright: Copyright Digital Mars 2000 - 2022.
License: Distributed under the $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
(See accompanying file LICENSE)
Source: $(DRUNTIMESRC core/internal/_array/_duplication.d)
*/
module core.internal.array.duplication;
private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
{
if (__ctfe)
return _dupCtfe!(T, U)(a);
import core.stdc.string : memcpy;
auto arr = _d_newarrayU(typeid(T[]), a.length);
memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
return *cast(U[]*) &arr;
}
U[] _dupCtfe(T, U)(scope T[] a)
{
static if (is(T : void))
assert(0, "Cannot dup a void[] array at compile time.");
else
{
U[] res;
foreach (ref e; a)
res ~= e;
return res;
}
}
U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
{
// note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
// has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
if (__ctfe)
return _dupCtfe!(T, U)(a);
import core.lifetime: copyEmplace;
U[] res = () @trusted {
auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
size_t i;
scope (failure)
{
import core.internal.lifetime: emplaceInitializer;
// Initialize all remaining elements to not destruct garbage
foreach (j; i .. a.length)
emplaceInitializer(cast() arr[j]);
}
for (; i < a.length; i++)
{
copyEmplace(a.ptr[i], arr[i]);
}
return cast(U[])(arr[0..a.length]);
} ();
return res;
}
// https://issues.dlang.org/show_bug.cgi?id=22107
@safe unittest
{
static int i;
@safe struct S
{
this(this) { i++; }
}
void fun(scope S[] values...) @safe
{
values.dup;
}
}
@safe unittest
{
static struct S1 { int* p; }
static struct S2 { @disable this(); }
static struct S3 { @disable this(this); }
int dg1() pure nothrow @safe
{
{
char[] m;
string i;
m = m.dup;
i = i.idup;
m = i.dup;
i = m.idup;
}
{
S1[] m;
immutable(S1)[] i;
m = m.dup;
i = i.idup;
static assert(!is(typeof(m.idup)));
static assert(!is(typeof(i.dup)));
}
{
S3[] m;
immutable(S3)[] i;
static assert(!is(typeof(m.dup)));
static assert(!is(typeof(i.idup)));
}
{
shared(S1)[] m;
m = m.dup;
static assert(!is(typeof(m.idup)));
}
{
int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
}
return 1;
}
int dg2() pure nothrow @safe
{
{
S2[] m = [S2.init, S2.init];
immutable(S2)[] i = [S2.init, S2.init];
m = m.dup;
m = i.dup;
i = m.idup;
i = i.idup;
}
return 2;
}
enum a = dg1();
enum b = dg2();
assert(dg1() == a);
assert(dg2() == b);
}
@system unittest
{
static struct Sunpure { this(this) @safe nothrow {} }
static struct Sthrow { this(this) @safe pure {} }
static struct Sunsafe { this(this) @system pure nothrow {} }
static struct Snocopy { @disable this(this); }
[].dup!Sunpure;
[].dup!Sthrow;
cast(void) [].dup!Sunsafe;
static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
static assert(!__traits(compiles, () { [].dup!Snocopy; }));
[].idup!Sunpure;
[].idup!Sthrow;
[].idup!Sunsafe;
static assert(!__traits(compiles, () pure { [].idup!Sunpure; }));
static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
static assert(!__traits(compiles, () @safe { [].idup!Sunsafe; }));
static assert(!__traits(compiles, () { [].idup!Snocopy; }));
}
@safe unittest
{
// test that the copy-constructor is called with .dup
static struct ArrElem
{
int a;
this(int a)
{
this.a = a;
}
this(ref const ArrElem)
{
a = 2;
}
this(ref ArrElem) immutable
{
a = 3;
}
}
auto arr = [ArrElem(1), ArrElem(1)];
ArrElem[] b = arr.dup;
assert(b[0].a == 2 && b[1].a == 2);
immutable ArrElem[] c = arr.idup;
assert(c[0].a == 3 && c[1].a == 3);
}
@system unittest
{
static struct Sunpure { this(ref const typeof(this)) @safe nothrow {} }
static struct Sthrow { this(ref const typeof(this)) @safe pure {} }
static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
[].dup!Sunpure;
[].dup!Sthrow;
cast(void) [].dup!Sunsafe;
static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
// for idup to work on structs that have copy constructors, it is necessary
// that the struct defines a copy constructor that creates immutable objects
static struct ISunpure { this(ref const typeof(this)) immutable @safe nothrow {} }
static struct ISthrow { this(ref const typeof(this)) immutable @safe pure {} }
static struct ISunsafe { this(ref const typeof(this)) immutable @system pure nothrow {} }
[].idup!ISunpure;
[].idup!ISthrow;
[].idup!ISunsafe;
static assert(!__traits(compiles, () pure { [].idup!ISunpure; }));
static assert(!__traits(compiles, () nothrow { [].idup!ISthrow; }));
static assert(!__traits(compiles, () @safe { [].idup!ISunsafe; }));
}
@safe unittest
{
static int*[] pureFoo() pure { return null; }
{ char[] s; immutable x = s.dup; }
{ immutable x = (cast(int*[])null).dup; }
{ immutable x = pureFoo(); }
{ immutable x = pureFoo().dup; }
}
@safe unittest
{
auto a = [1, 2, 3];
auto b = a.dup;
debug(SENTINEL) {} else
assert(b.capacity >= 3);
}
@system unittest
{
// Bugzilla 12580
void[] m = [0];
shared(void)[] s = [cast(shared)1];
immutable(void)[] i = [cast(immutable)2];
s = s.dup;
static assert(is(typeof(s.dup) == shared(void)[]));
m = i.dup;
i = m.dup;
i = i.idup;
i = m.idup;
i = s.idup;
i = s.dup;
static assert(!__traits(compiles, m = s.dup));
}
@safe unittest
{
// Bugzilla 13809
static struct S
{
this(this) {}
~this() {}
}
S[] arr;
auto a = arr.dup;
}
@system unittest
{
// Bugzilla 16504
static struct S
{
__gshared int* gp;
int* p;
// postblit and hence .dup could escape
this(this) { gp = p; }
}
int p;
scope S[1] arr = [S(&p)];
auto a = arr.dup; // dup does escape
}
// https://issues.dlang.org/show_bug.cgi?id=21983
// dup/idup destroys partially constructed arrays on failure
@safe unittest
{
static struct SImpl(bool postblit)
{
int num;
long l = 0xDEADBEEF;
static if (postblit)
{
this(this)
{
if (this.num == 3)
throw new Exception("");
}
}
else
{
this(scope ref const SImpl other)
{
if (other.num == 3)
throw new Exception("");
this.num = other.num;
this.l = other.l;
}
}
~this() @trusted
{
if (l != 0xDEADBEEF)
{
import core.stdc.stdio;
printf("Unexpected value: %lld\n", l);
fflush(stdout);
assert(false);
}
}
}
alias Postblit = SImpl!true;
alias Copy = SImpl!false;
static int test(S)()
{
S[4] arr = [ S(1), S(2), S(3), S(4) ];
try
{
arr.dup();
assert(false);
}
catch (Exception)
{
return 1;
}
}
static assert(test!Postblit());
assert(test!Postblit());
static assert(test!Copy());
assert(test!Copy());
}

View File

@ -14,7 +14,7 @@
*
* Copyright: D Language Foundation 2018 - 2020
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/internal/dassert.d, _dassert.d)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/internal/dassert.d, _dassert.d)
* Documentation: https://dlang.org/phobos/core_internal_dassert.html
*/
module core.internal.dassert;

View File

@ -4,7 +4,7 @@
* Copyright: Copyright Sean Kelly 2005 - 2009.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Sean Kelly
* Source: $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/runtime.d, _runtime.d)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/runtime.d, _runtime.d)
* Documentation: https://dlang.org/phobos/core_runtime.html
*/

View File

@ -8,7 +8,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Alex Rønne Petersen
* Source: https://github.com/dlang/druntime/blob/master/src/core/stdc/errno.d
* Source: https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/errno.d
* Standards: ISO/IEC 9899:1999 (E)
*/

Some files were not shown because too many files have changed in this diff Show More