mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-26 02:30:30 +08:00
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:
parent
64ce76d940
commit
b6df113247
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -1 +1 @@
|
||||
v2.100.0
|
||||
v2.100.1
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
|
@ -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]);
|
||||
|
@ -684,6 +684,7 @@ public:
|
||||
const char *kind() const override;
|
||||
bool isUnique();
|
||||
bool needsClosure();
|
||||
bool checkClosure();
|
||||
bool hasNestedFrameRefs();
|
||||
ParameterList getParameterList();
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
10
gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
Normal file
10
gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
16
gcc/testsuite/gdc.test/compilable/must_use_initialize.d
Normal file
16
gcc/testsuite/gdc.test/compilable/must_use_initialize.d
Normal 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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
12
gcc/testsuite/gdc.test/compilable/test20832.d
Normal file
12
gcc/testsuite/gdc.test/compilable/test20832.d
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
25
gcc/testsuite/gdc.test/compilable/test21432.d
Normal file
25
gcc/testsuite/gdc.test/compilable/test21432.d
Normal 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);
|
8
gcc/testsuite/gdc.test/compilable/test22390.d
Normal file
8
gcc/testsuite/gdc.test/compilable/test22390.d
Normal file
@ -0,0 +1,8 @@
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22390
|
||||
|
||||
int main()
|
||||
{
|
||||
noreturn[] empty;
|
||||
assert(empty == empty);
|
||||
return 0;
|
||||
}
|
17
gcc/testsuite/gdc.test/compilable/test23082.d
Normal file
17
gcc/testsuite/gdc.test/compilable/test23082.d
Normal 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);
|
||||
}
|
22
gcc/testsuite/gdc.test/compilable/test23166.d
Normal file
22
gcc/testsuite/gdc.test/compilable/test23166.d
Normal 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");
|
||||
}
|
33
gcc/testsuite/gdc.test/compilable/test23172.d
Normal file
33
gcc/testsuite/gdc.test/compilable/test23172.d
Normal 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
|
||||
}
|
20
gcc/testsuite/gdc.test/compilable/test23235.d
Normal file
20
gcc/testsuite/gdc.test/compilable/test23235.d
Normal 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");
|
||||
}
|
6
gcc/testsuite/gdc.test/compilable/test23256.d
Normal file
6
gcc/testsuite/gdc.test/compilable/test23256.d
Normal file
@ -0,0 +1,6 @@
|
||||
/* REQUIRED_ARGS: -os=windows
|
||||
*/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23256
|
||||
|
||||
void test23256() { }
|
17
gcc/testsuite/gdc.test/compilable/test23262.d
Normal file
17
gcc/testsuite/gdc.test/compilable/test23262.d
Normal 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;
|
||||
}
|
17
gcc/testsuite/gdc.test/compilable/testgotoskips.d
Normal file
17
gcc/testsuite/gdc.test/compilable/testgotoskips.d
Normal 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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); }
|
||||
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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 `""`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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)
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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);
|
||||
}
|
17
gcc/testsuite/gdc.test/fail_compilation/fail22134.d
Normal file
17
gcc/testsuite/gdc.test/fail_compilation/fail22134.d
Normal 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;
|
||||
}
|
16
gcc/testsuite/gdc.test/fail_compilation/fail23181.d
Normal file
16
gcc/testsuite/gdc.test/fail_compilation/fail23181.d
Normal 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();
|
||||
}
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ L1:
|
||||
scope(failure) { L2: goto L1; } // OK
|
||||
goto L2; // NG
|
||||
|
||||
scope(failure) { return; } // OK
|
||||
|
||||
|
||||
foreach (i; 0..1)
|
||||
{
|
||||
|
@ -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`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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 {}
|
||||
|
@ -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 {};
|
||||
|
19
gcc/testsuite/gdc.test/fail_compilation/newaa.d
Normal file
19
gcc/testsuite/gdc.test/fail_compilation/newaa.d
Normal 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);
|
||||
}
|
@ -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()
|
||||
|
@ -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)
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -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`
|
||||
|
21
gcc/testsuite/gdc.test/fail_compilation/test21443.d
Normal file
21
gcc/testsuite/gdc.test/fail_compilation/test21443.d
Normal 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
|
||||
}
|
@ -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:
|
||||
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
|
15
gcc/testsuite/gdc.test/fail_compilation/test23022.d
Normal file
15
gcc/testsuite/gdc.test/fail_compilation/test23022.d
Normal 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;
|
||||
}
|
30
gcc/testsuite/gdc.test/fail_compilation/test23112.d
Normal file
30
gcc/testsuite/gdc.test/fail_compilation/test23112.d
Normal 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);
|
||||
}
|
12
gcc/testsuite/gdc.test/fail_compilation/test23170.d
Normal file
12
gcc/testsuite/gdc.test/fail_compilation/test23170.d
Normal 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; }
|
24
gcc/testsuite/gdc.test/fail_compilation/test23216.d
Normal file
24
gcc/testsuite/gdc.test/fail_compilation/test23216.d
Normal 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) { }
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/******************************************/
|
||||
|
@ -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
|
||||
---
|
||||
*/
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
25
gcc/testsuite/gdc.test/runnable/test18973.d
Normal file
25
gcc/testsuite/gdc.test/runnable/test18973.d
Normal 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");
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
27
gcc/testsuite/gdc.test/runnable/test23181.d
Normal file
27
gcc/testsuite/gdc.test/runnable/test23181.d
Normal 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);
|
||||
}
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
@ -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
2
libphobos/configure
vendored
@ -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!)
|
||||
|
@ -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!)
|
||||
|
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -943,5 +943,3 @@ unittest
|
||||
assert(rol(C7_9, 1) == rol1(C7_9));
|
||||
assert(ror(C7_9, 1) == ror1(C7_9));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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).
|
||||
|
346
libphobos/libdruntime/core/internal/array/duplication.d
Normal file
346
libphobos/libdruntime/core/internal/array/duplication.d
Normal 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());
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user