mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-26 02:05:29 +08:00
d: Merge upstream dmd, druntime d115713410, phobos 1b242048c.
D front-end changes: - Import latest fixes from dmd v2.110.0-rc.1. - Integers in debug or version statements have been removed from the language. D runtime changes: - Import latest fixes from druntime v2.110.0-rc.1. Phobos changes: - Import latest fixes from phobos v2.110.0-rc.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd d115713410. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime d115713410. * src/MERGE: Merge upstream phobos 1b242048c. gcc/testsuite/ChangeLog: * gdc.dg/asm3.d: Adjust test.
This commit is contained in:
parent
20a4306793
commit
2ead01297c
@ -1,4 +1,4 @@
|
||||
d6f693b46a1565172cac7a1438905141783a164f
|
||||
d1157134103a209d36d6ee9c1df1d61d5929ec6d
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
@ -478,7 +478,7 @@ int blockExit(Statement s, FuncDeclaration func, ErrorSink eSink)
|
||||
if (!(s.stc & STC.nothrow_))
|
||||
{
|
||||
if(func)
|
||||
func.setThrow(s.loc, "`asm` statement is assumed to throw - mark it with `nothrow` if it does not");
|
||||
func.setThrow(s.loc, "executing an `asm` statement without a `nothrow` annotation");
|
||||
if (eSink)
|
||||
eSink.error(s.loc, "`asm` statement is assumed to throw - mark it with `nothrow` if it does not"); // TODO
|
||||
else
|
||||
@ -523,7 +523,7 @@ BE checkThrow(ref const Loc loc, Expression exp, FuncDeclaration func, ErrorSink
|
||||
if (eSink)
|
||||
eSink.error(loc, "`%s` is thrown but not caught", exp.type.toChars());
|
||||
else if (func)
|
||||
func.setThrow(loc, "`%s` is thrown but not caught", exp.type);
|
||||
func.setThrow(loc, "`%s` being thrown but not caught", exp.type);
|
||||
|
||||
return BE.throw_;
|
||||
}
|
||||
|
@ -2922,7 +2922,10 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
||||
{
|
||||
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
|
||||
}
|
||||
static immutable msg = "cannot form delegate due to covariant return type";
|
||||
void errorCovariantReturnType()
|
||||
{
|
||||
error(e.loc, "cannot form delegate due to covariant return type");
|
||||
}
|
||||
|
||||
Type tb = t.toBasetype();
|
||||
Type typeb = e.type.toBasetype();
|
||||
@ -2932,7 +2935,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
||||
int offset;
|
||||
e.func.tookAddressOf++;
|
||||
if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
|
||||
error(e.loc, "%s", msg.ptr);
|
||||
errorCovariantReturnType();
|
||||
auto result = e.copy();
|
||||
result.type = t;
|
||||
return result;
|
||||
@ -2947,7 +2950,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
||||
{
|
||||
int offset;
|
||||
if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
|
||||
error(e.loc, "%s", msg.ptr);
|
||||
errorCovariantReturnType();
|
||||
if (f != e.func) // if address not already marked as taken
|
||||
f.tookAddressOf++;
|
||||
auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
|
||||
@ -2955,7 +2958,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
||||
return result;
|
||||
}
|
||||
if (e.func.tintro)
|
||||
error(e.loc, "%s", msg.ptr);
|
||||
errorCovariantReturnType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ private struct Previews
|
||||
bool dip1008;
|
||||
bool dip1021;
|
||||
bool dip25;
|
||||
bool fieldwise;
|
||||
bool fixAliasThis;
|
||||
bool fixImmutableConv;
|
||||
bool in_;
|
||||
@ -116,6 +117,7 @@ private struct Previews
|
||||
this.rvalueRefParam = params.rvalueRefParam == FeatureState.enabled;
|
||||
this.safer = params.safer == FeatureState.enabled;
|
||||
this.systemVariables = params.systemVariables;
|
||||
this.fieldwise = params.fieldwise == FeatureState.enabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,12 +59,9 @@ extern (C++) final class DebugSymbol : Dsymbol
|
||||
{
|
||||
if (ident)
|
||||
return ident.toChars();
|
||||
else
|
||||
{
|
||||
OutBuffer buf;
|
||||
buf.print(level);
|
||||
return buf.extractChars();
|
||||
}
|
||||
OutBuffer buf;
|
||||
buf.print(level);
|
||||
return buf.extractChars();
|
||||
}
|
||||
|
||||
override const(char)* kind() const nothrow
|
||||
@ -116,12 +113,9 @@ extern (C++) final class VersionSymbol : Dsymbol
|
||||
{
|
||||
if (ident)
|
||||
return ident.toChars();
|
||||
else
|
||||
{
|
||||
OutBuffer buf;
|
||||
buf.print(level);
|
||||
return buf.extractChars();
|
||||
}
|
||||
OutBuffer buf;
|
||||
buf.print(level);
|
||||
return buf.extractChars();
|
||||
}
|
||||
|
||||
override const(char)* kind() const nothrow
|
||||
|
@ -2191,9 +2191,9 @@ private EnclosedBy enclosesLifetimeOf(VarDeclaration va, VarDeclaration v)
|
||||
// `setUnsafePreview` partially evaluated for dip1000
|
||||
public
|
||||
bool setUnsafeDIP1000(ref Scope sc, bool gag, Loc loc, const(char)* msg,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
RootObject[] args...)
|
||||
{
|
||||
return setUnsafePreview(&sc, sc.useDIP1000, gag, loc, msg, arg0, arg1, arg2);
|
||||
return setUnsafePreview(&sc, sc.useDIP1000, gag, loc, msg, args);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
|
@ -1074,7 +1074,7 @@ extern (C++) final class ErrorExp : Expression
|
||||
* and we need to set the error count to prevent bogus code
|
||||
* generation. At least give a message.
|
||||
*/
|
||||
.error(Loc.initial, "unknown, please file report on issues.dlang.org");
|
||||
.error(Loc.initial, "unknown, please file report at https://github.com/dlang/dmd/issues/new");
|
||||
}
|
||||
|
||||
return errorexp;
|
||||
|
@ -2073,7 +2073,7 @@ public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool
|
||||
auto errorFunc = deprecation ? &eSink.deprecationSupplemental : &eSink.errorSupplemental;
|
||||
|
||||
AttributeViolation* s;
|
||||
const(char)* attr;
|
||||
string attr;
|
||||
if (stc & STC.safe)
|
||||
{
|
||||
s = fd.safetyViolation;
|
||||
@ -2098,21 +2098,9 @@ public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
if (s.format)
|
||||
if (s.action.length > 0)
|
||||
{
|
||||
errorFunc(s.loc, deprecation ?
|
||||
"which wouldn't be `%s` because of:" :
|
||||
"which wasn't inferred `%s` because of:", attr);
|
||||
if (stc == STC.nogc || stc == STC.pure_)
|
||||
{
|
||||
auto f = (cast(Dsymbol) s.arg0).isFuncDeclaration();
|
||||
errorFunc(s.loc, s.format, f.kind(), f.toPrettyChars(), s.arg1 ? s.arg1.toChars() : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
errorFunc(s.loc, s.format,
|
||||
s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : "");
|
||||
}
|
||||
errorFunc(s.loc, "and %.*s makes it fail to infer `%.*s`", s.action.fTuple.expand, attr.fTuple.expand);
|
||||
}
|
||||
else if (s.fd)
|
||||
{
|
||||
@ -2176,7 +2164,7 @@ private bool checkPurity(VarDeclaration v, const ref Loc loc, Scope* sc)
|
||||
if (v.ident == Id.gate)
|
||||
return false;
|
||||
|
||||
if (checkImpure(sc, loc, "`pure` %s `%s` cannot access mutable static data `%s`", v))
|
||||
if (checkImpure(sc, loc, "accessing mutable static data `%s`", v))
|
||||
{
|
||||
error(loc, "`pure` %s `%s` cannot access mutable static data `%s`",
|
||||
sc.func.kind(), sc.func.toPrettyChars(), v.toChars());
|
||||
@ -6710,20 +6698,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
||||
else if (sc.func && sc.intypeof != 1 && !(sc.ctfe || sc.debug_))
|
||||
{
|
||||
bool err = false;
|
||||
if (!tf.purity && sc.func.setImpure(exp.loc, "`pure` %s `%s` cannot call impure `%s`", exp.e1))
|
||||
if (!tf.purity && sc.func.setImpure(exp.loc, "calling impure `%s`", exp.e1))
|
||||
{
|
||||
error(exp.loc, "`pure` %s `%s` cannot call impure %s `%s`",
|
||||
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
|
||||
err = true;
|
||||
}
|
||||
if (!tf.isNogc && sc.func.setGC(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc `%s`", exp.e1))
|
||||
if (!tf.isNogc && sc.func.setGC(exp.loc, "calling non-@nogc `%s`", exp.e1))
|
||||
{
|
||||
error(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
|
||||
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
|
||||
err = true;
|
||||
}
|
||||
if (tf.trust <= TRUST.system && sc.setUnsafe(true, exp.loc,
|
||||
"`@safe` function `%s` cannot call `@system` `%s`", sc.func, exp.e1))
|
||||
"calling `@system` `%s`", exp.e1))
|
||||
{
|
||||
error(exp.loc, "`@safe` %s `%s` cannot call `@system` %s `%s`",
|
||||
sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
|
||||
|
@ -691,14 +691,13 @@ extern (C++) class FuncDeclaration : Declaration
|
||||
* Params:
|
||||
* loc = location of action
|
||||
* format = format string for error message
|
||||
* arg0 = (optional) argument to format string
|
||||
* args = arguments to format string
|
||||
*/
|
||||
extern (D) final void setThrow(Loc loc, const(char)* format, RootObject arg0 = null)
|
||||
extern (D) final void setThrow(Loc loc, const(char)* format, RootObject[] args...)
|
||||
{
|
||||
if (nothrowInprocess && !nothrowViolation)
|
||||
{
|
||||
assert(format);
|
||||
nothrowViolation = new AttributeViolation(loc, format, arg0); // action that requires GC
|
||||
nothrowViolation = new AttributeViolation(loc, format, args); // action that requires GC
|
||||
}
|
||||
}
|
||||
|
||||
@ -1873,11 +1872,10 @@ extern (C++) final class NewDeclaration : FuncDeclaration
|
||||
/// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure`
|
||||
///
|
||||
/// Has two modes:
|
||||
/// - a regular safety error, stored in (fmtStr, arg0, arg1)
|
||||
/// - a regular safety error, stored in `action`
|
||||
/// - a call to a function without the attribute, which is a special case, because in that case,
|
||||
/// that function might recursively also have a `AttributeViolation`. This way, in case
|
||||
/// of a big call stack, the error can go down all the way to the root cause.
|
||||
/// The `FunctionDeclaration` is then stored in `arg0` and `fmtStr` must be `null`.
|
||||
struct AttributeViolation
|
||||
{
|
||||
Loc loc; /// location of error
|
||||
@ -1886,20 +1884,21 @@ struct AttributeViolation
|
||||
|
||||
// -- OR --
|
||||
|
||||
const(char)* format; /// printf-style format string
|
||||
RootObject arg0; /// Arguments for up to two `%s` format specifiers in format string
|
||||
RootObject arg1; /// ditto
|
||||
RootObject arg2; /// ditto
|
||||
string action; /// Action that made the attribute fail to get inferred
|
||||
|
||||
this(ref Loc loc, FuncDeclaration fd) { this.loc = loc; this.fd = fd; }
|
||||
|
||||
this(ref Loc loc, const(char)* format, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
this(ref Loc loc, const(char)* fmt, RootObject[] args)
|
||||
{
|
||||
assert(format);
|
||||
this.loc = loc;
|
||||
this.format = format;
|
||||
this.arg0 = arg0;
|
||||
this.arg1 = arg1;
|
||||
this.arg2 = arg2;
|
||||
assert(args.length <= 4); // expand if necessary
|
||||
OutBuffer buf;
|
||||
buf.printf(fmt,
|
||||
args.length > 0 && args[0] ? args[0].toChars() : "",
|
||||
args.length > 1 && args[1] ? args[1].toChars() : "",
|
||||
args.length > 2 && args[2] ? args[2].toChars() : "",
|
||||
args.length > 3 && args[3] ? args[3].toChars() : "",
|
||||
);
|
||||
this.action = buf.extractSlice();
|
||||
}
|
||||
}
|
||||
|
@ -3032,21 +3032,21 @@ extern (D) bool checkNRVO(FuncDeclaration fd)
|
||||
* Params:
|
||||
* fd = function declaration to mark
|
||||
* loc = location of impure action
|
||||
* fmt = format string for error message. Must include "%s `%s`" for the function kind and name.
|
||||
* arg0 = (optional) argument to format string
|
||||
* fmt = format string for error message
|
||||
* args = argument to format string
|
||||
*
|
||||
* Returns: `true` if there's a purity error
|
||||
*/
|
||||
extern (D) bool setImpure(FuncDeclaration fd, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null)
|
||||
extern (D) bool setImpure(FuncDeclaration fd, Loc loc, const(char)* fmt, RootObject[] args...)
|
||||
{
|
||||
if (fd.purityInprocess)
|
||||
{
|
||||
fd.purityInprocess = false;
|
||||
if (fmt)
|
||||
fd.pureViolation = new AttributeViolation(loc, fmt, fd, arg0); // impure action
|
||||
else if (arg0)
|
||||
fd.pureViolation = new AttributeViolation(loc, fmt, args); // impure action
|
||||
else if (args.length > 0)
|
||||
{
|
||||
if (auto sa = arg0.isDsymbol())
|
||||
if (auto sa = args[0].isDsymbol())
|
||||
{
|
||||
if (FuncDeclaration fd2 = sa.isFuncDeclaration())
|
||||
{
|
||||
@ -3056,7 +3056,7 @@ extern (D) bool setImpure(FuncDeclaration fd, Loc loc = Loc.init, const(char)* f
|
||||
}
|
||||
|
||||
if (fd.fes)
|
||||
fd.fes.func.setImpure(loc, fmt, arg0);
|
||||
fd.fes.func.setImpure(loc, fmt, args);
|
||||
}
|
||||
else if (fd.isPure())
|
||||
return true;
|
||||
@ -3070,7 +3070,7 @@ PURE isPure(FuncDeclaration fd)
|
||||
|
||||
TypeFunction tf = fd.type.toTypeFunction();
|
||||
if (fd.purityInprocess)
|
||||
fd.setImpure();
|
||||
fd.setImpure(Loc.initial, null);
|
||||
if (tf.purity == PURE.fwdref)
|
||||
tf.purityLevel();
|
||||
PURE purity = tf.purity;
|
||||
|
@ -2571,19 +2571,19 @@ class Lexer
|
||||
Ldone:
|
||||
if (errorDigit)
|
||||
{
|
||||
error(token.loc, "%s digit expected, not `%c`", base == 2 ? "binary".ptr :
|
||||
error(scanloc, "%s digit expected, not `%c`", base == 2 ? "binary".ptr :
|
||||
base == 8 ? "octal".ptr :
|
||||
"decimal".ptr, errorDigit);
|
||||
err = true;
|
||||
}
|
||||
if (overflow && !err)
|
||||
{
|
||||
error("integer overflow");
|
||||
error(scanloc, "integer overflow");
|
||||
err = true;
|
||||
}
|
||||
if ((base == 2 && !anyBinaryDigitsNoSingleUS) ||
|
||||
(base == 16 && !anyHexDigitsNoSingleUS))
|
||||
error(token.loc, "`%.*s` isn't a valid integer literal, use `%.*s0` instead", cast(int)(p - start), start, 2, start);
|
||||
error(scanloc, "`%.*s` isn't a valid integer literal, use `%.*s0` instead", cast(int)(p - start), start, 2, start);
|
||||
|
||||
t.unsvalue = n;
|
||||
|
||||
@ -2612,7 +2612,7 @@ class Lexer
|
||||
goto L1;
|
||||
case 'l':
|
||||
f = FLAGS.long_;
|
||||
error("lower case integer suffix 'l' is not allowed. Please use 'L' instead");
|
||||
error(scanloc, "lower case integer suffix 'l' is not allowed. Please use 'L' instead");
|
||||
goto L1;
|
||||
case 'L':
|
||||
f = FLAGS.long_;
|
||||
@ -2620,7 +2620,7 @@ class Lexer
|
||||
p++;
|
||||
if ((flags & f) && !err)
|
||||
{
|
||||
error("repeated integer suffix `%c`", p[-1]);
|
||||
error(scanloc, "repeated integer suffix `%c`", p[-1]);
|
||||
err = true;
|
||||
}
|
||||
flags = cast(FLAGS)(flags | f);
|
||||
@ -2634,9 +2634,9 @@ class Lexer
|
||||
{
|
||||
if (err)
|
||||
// can't translate invalid octal value, just show a generic message
|
||||
error("octal literals larger than 7 are no longer supported");
|
||||
error(scanloc, "octal literals larger than 7 are no longer supported");
|
||||
else
|
||||
error(token.loc, "octal literals `0%llo%.*s` are no longer supported, use `std.conv.octal!\"%llo%.*s\"` instead",
|
||||
error(scanloc, "octal literals `0%llo%.*s` are no longer supported, use `std.conv.octal!\"%llo%.*s\"` instead",
|
||||
n, cast(int)(p - psuffix), psuffix, n, cast(int)(p - psuffix), psuffix);
|
||||
}
|
||||
TOK result;
|
||||
|
@ -529,12 +529,9 @@ extern (C++) abstract class Type : ASTNode
|
||||
auto sv = t.stringtable.update(buf[]);
|
||||
if (sv.value)
|
||||
return sv.value;
|
||||
else
|
||||
{
|
||||
t.deco = cast(char*)sv.toDchars();
|
||||
sv.value = t;
|
||||
return t;
|
||||
}
|
||||
t.deco = cast(char*)sv.toDchars();
|
||||
sv.value = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
for (size_t i = 0; basetab[i] != Terror; i++)
|
||||
|
@ -18,6 +18,7 @@ import core.stdc.stdio;
|
||||
import dmd.aggregate;
|
||||
import dmd.astenums;
|
||||
import dmd.declaration;
|
||||
import dmd.common.outbuffer;
|
||||
import dmd.dmodule;
|
||||
import dmd.dscope;
|
||||
import dmd.dtemplate : isDsymbol;
|
||||
@ -80,20 +81,19 @@ public:
|
||||
* Register that expression `e` requires the GC
|
||||
* Params:
|
||||
* e = expression that uses GC
|
||||
* format = error message when `e` is used in a `@nogc` function.
|
||||
* Must contain format strings "`@nogc` %s `%s`" referring to the function.
|
||||
* msg = error message when `e` is used in a `@nogc` function.
|
||||
* Returns: `true` if `err` was set, `false` if it's not in a `@nogc` and not checkonly (-betterC)
|
||||
*/
|
||||
private bool setGC(Expression e, const(char)* format)
|
||||
private bool setGC(Expression e, const(char)* msg)
|
||||
{
|
||||
if (checkOnly)
|
||||
{
|
||||
err = true;
|
||||
return true;
|
||||
}
|
||||
if (f.setGC(e.loc, format))
|
||||
if (f.setGC(e.loc, msg))
|
||||
{
|
||||
error(e.loc, format, f.kind(), f.toPrettyChars());
|
||||
error(e.loc, "%s causes a GC allocation in `@nogc` %s `%s`", msg, f.kind(), f.toChars());
|
||||
err = true;
|
||||
return true;
|
||||
}
|
||||
@ -111,7 +111,7 @@ public:
|
||||
auto fd = stripHookTraceImpl(e.f);
|
||||
if (fd.ident == Id._d_arraysetlengthT)
|
||||
{
|
||||
if (setGC(e, "setting `length` in `@nogc` %s `%s` may cause a GC allocation"))
|
||||
if (setGC(e, "setting this array's `length`"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
|
||||
}
|
||||
@ -121,7 +121,7 @@ public:
|
||||
{
|
||||
if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack)
|
||||
return;
|
||||
if (setGC(e, "array literal in `@nogc` %s `%s` may cause a GC allocation"))
|
||||
if (setGC(e, "this array literal"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "array literal may cause a GC allocation");
|
||||
}
|
||||
@ -130,7 +130,7 @@ public:
|
||||
{
|
||||
if (!e.keys.length)
|
||||
return;
|
||||
if (setGC(e, "associative array literal in `@nogc` %s `%s` may cause a GC allocation"))
|
||||
if (setGC(e, "this associative array literal"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "associative array literal may cause a GC allocation");
|
||||
}
|
||||
@ -147,7 +147,7 @@ public:
|
||||
if (nogcExceptions && e.thrownew)
|
||||
return; // separate allocator is called for this, not the GC
|
||||
|
||||
if (setGC(e, "cannot use `new` in `@nogc` %s `%s`"))
|
||||
if (setGC(e, "allocating with `new`"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "`new` causes a GC allocation");
|
||||
}
|
||||
@ -170,7 +170,7 @@ public:
|
||||
Type t1b = e.e1.type.toBasetype();
|
||||
if (e.modifiable && t1b.ty == Taarray)
|
||||
{
|
||||
if (setGC(e, "assigning an associative array element in `@nogc` %s `%s` may cause a GC allocation"))
|
||||
if (setGC(e, "assigning this associative array element"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "assigning an associative array element may cause a GC allocation");
|
||||
}
|
||||
@ -180,7 +180,7 @@ public:
|
||||
{
|
||||
if (e.e1.op == EXP.arrayLength)
|
||||
{
|
||||
if (setGC(e, "setting `length` in `@nogc` %s `%s` may cause a GC allocation"))
|
||||
if (setGC(e, "setting this array's `length`"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
|
||||
}
|
||||
@ -193,14 +193,14 @@ public:
|
||||
err = true;
|
||||
return;
|
||||
}
|
||||
if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`"))
|
||||
if (setGC(e, "appending to this array with operator `~=`"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
|
||||
}
|
||||
|
||||
override void visit(CatExp e)
|
||||
{
|
||||
if (setGC(e, "cannot use operator `~` in `@nogc` %s `%s`"))
|
||||
if (setGC(e, "concatenating with operator `~`"))
|
||||
return;
|
||||
f.printGCUsage(e.loc, "operator `~` may cause a GC allocation");
|
||||
}
|
||||
@ -284,12 +284,12 @@ private FuncDeclaration stripHookTraceImpl(FuncDeclaration fd)
|
||||
* fd = function
|
||||
* loc = location of GC action
|
||||
* fmt = format string for error message. Must include "%s `%s`" for the function kind and name.
|
||||
* arg0 = (optional) argument to format string
|
||||
* args = arguments to format string
|
||||
*
|
||||
* Returns:
|
||||
* true if function is marked as @nogc, meaning a user error occurred
|
||||
*/
|
||||
extern (D) bool setGC(FuncDeclaration fd, Loc loc, const(char)* fmt, RootObject arg0 = null)
|
||||
extern (D) bool setGC(FuncDeclaration fd, Loc loc, const(char)* fmt, RootObject[] args...)
|
||||
{
|
||||
//printf("setGC() %s\n", toChars());
|
||||
if (fd.nogcInprocess && fd.semanticRun < PASS.semantic3 && fd._scope)
|
||||
@ -302,10 +302,10 @@ extern (D) bool setGC(FuncDeclaration fd, Loc loc, const(char)* fmt, RootObject
|
||||
{
|
||||
fd.nogcInprocess = false;
|
||||
if (fmt)
|
||||
fd.nogcViolation = new AttributeViolation(loc, fmt, fd, arg0); // action that requires GC
|
||||
else if (arg0)
|
||||
fd.nogcViolation = new AttributeViolation(loc, fmt, args); // action that requires GC
|
||||
else if (args.length > 0)
|
||||
{
|
||||
if (auto sa = arg0.isDsymbol())
|
||||
if (auto sa = args[0].isDsymbol())
|
||||
{
|
||||
if (FuncDeclaration fd2 = sa.isFuncDeclaration())
|
||||
{
|
||||
|
@ -379,7 +379,7 @@ void toObNodes(ref ObNodes obnodes, Statement s)
|
||||
return ob;
|
||||
}
|
||||
|
||||
// block_goto(blx, BCgoto, null)
|
||||
// block_goto(blx, BC.goto_, null)
|
||||
ObNode* gotoNextNode()
|
||||
{
|
||||
return gotoNextNodeIs(newNode());
|
||||
|
@ -1009,7 +1009,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
|
||||
return null;
|
||||
|
||||
import dmd.clone : needOpEquals;
|
||||
if (global.params.fieldwise != FeatureState.enabled && !needOpEquals(sd))
|
||||
if (!sc.previews.fieldwise && !needOpEquals(sd))
|
||||
{
|
||||
// Use bitwise equality.
|
||||
auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity;
|
||||
|
@ -2257,17 +2257,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||
nextToken();
|
||||
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());
|
||||
error("identifier expected, not `%s`", token.toChars());
|
||||
s = null;
|
||||
}
|
||||
nextToken();
|
||||
@ -2292,16 +2284,8 @@ 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());
|
||||
error("identifier expected inside `debug(...)`, not `%s`", token.toChars());
|
||||
loc = token.loc;
|
||||
nextToken();
|
||||
check(TOK.rightParenthesis);
|
||||
@ -2318,16 +2302,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||
nextToken();
|
||||
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());
|
||||
error("identifier expected, not `%s`", token.toChars());
|
||||
s = null;
|
||||
}
|
||||
nextToken();
|
||||
@ -2357,20 +2334,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
||||
loc = token.loc;
|
||||
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_)
|
||||
id = Identifier.idPool(Token.toString(TOK.assert_));
|
||||
else
|
||||
error("identifier or integer expected inside `version(...)`, not `%s`", token.toChars());
|
||||
error("identifier expected inside `version(...)`, not `%s`", token.toChars());
|
||||
nextToken();
|
||||
check(TOK.rightParenthesis);
|
||||
}
|
||||
|
@ -877,10 +877,9 @@ nothrow:
|
||||
const dw = GetFileAttributesW(&wname[0]);
|
||||
if (dw == -1)
|
||||
return 0;
|
||||
else if (dw & FILE_ATTRIBUTE_DIRECTORY)
|
||||
if (dw & FILE_ATTRIBUTE_DIRECTORY)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -34,6 +34,7 @@ import dmd.identifier;
|
||||
import dmd.location;
|
||||
import dmd.mtype;
|
||||
import dmd.rootobject;
|
||||
import dmd.root.string : fTuple;
|
||||
import dmd.target;
|
||||
import dmd.tokens;
|
||||
import dmd.typesem : hasPointers, arrayOf, size;
|
||||
@ -315,8 +316,7 @@ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag)
|
||||
{
|
||||
if (id == Id.ptr)
|
||||
return sc.setUnsafe(false, e.loc, "using `%s.ptr` (instead of `&%s[0])`", e, e);
|
||||
else
|
||||
return sc.setUnsafe(false, e.loc, "using `%s.%s`", e, id);
|
||||
return sc.setUnsafe(false, e.loc, "using `%s.%s`", e, id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -359,20 +359,20 @@ bool isTrusted(FuncDeclaration fd)
|
||||
* gag = suppress error message (used in escape.d)
|
||||
* loc = location of error
|
||||
* format = printf-style format string
|
||||
* arg0 = (optional) argument for first %s format specifier
|
||||
* arg1 = (optional) argument for second %s format specifier
|
||||
* arg2 = (optional) argument for third %s format specifier
|
||||
* args = arguments for %s format specifier
|
||||
*/
|
||||
extern (D) void reportSafeError(FuncDeclaration fd, bool gag, Loc loc,
|
||||
const(char)* format = null, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
const(char)* format, RootObject[] args...)
|
||||
{
|
||||
if (fd.type.toTypeFunction().trust == TRUST.system) // function was just inferred to be @system
|
||||
{
|
||||
if (format)
|
||||
fd.safetyViolation = new AttributeViolation(loc, format, arg0, arg1, arg2);
|
||||
else if (arg0)
|
||||
{
|
||||
if (FuncDeclaration fd2 = (cast(Dsymbol) arg0).isFuncDeclaration())
|
||||
fd.safetyViolation = new AttributeViolation(loc, format, args);
|
||||
}
|
||||
else if (args.length > 0)
|
||||
{
|
||||
if (FuncDeclaration fd2 = (cast(Dsymbol) args[0]).isFuncDeclaration())
|
||||
{
|
||||
fd.safetyViolation = new AttributeViolation(loc, fd2); // call to non-@nogc function
|
||||
}
|
||||
@ -383,12 +383,17 @@ extern (D) void reportSafeError(FuncDeclaration fd, bool gag, Loc loc,
|
||||
if (!gag && format)
|
||||
{
|
||||
OutBuffer buf;
|
||||
buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
|
||||
buf.writestring(AttributeViolation(loc, format, args).action);
|
||||
if (fd.isSafe())
|
||||
buf.writestring(" is not allowed in a `@safe` function");
|
||||
else
|
||||
buf.writestring(" is not allowed in a function with default safety with `-preview=safer`");
|
||||
.error(loc, buf.extractChars());
|
||||
{
|
||||
version (IN_GCC)
|
||||
buf.writestring(" is not allowed in a function with default safety with `-fpreview=safer`");
|
||||
else
|
||||
buf.writestring(" is not allowed in a function with default safety with `-preview=safer`");
|
||||
}
|
||||
.error(loc, "%s", buf.extractChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -447,14 +452,10 @@ extern (D) bool setUnsafeCall(FuncDeclaration fd, FuncDeclaration f)
|
||||
* gag = surpress error message (used in escape.d)
|
||||
* loc = location of error
|
||||
* format = printf-style format string
|
||||
* arg0 = (optional) argument for first %s format specifier
|
||||
* arg1 = (optional) argument for second %s format specifier
|
||||
* arg2 = (optional) argument for third %s format specifier
|
||||
* args = arguments for format string
|
||||
* Returns: whether there is a safe error
|
||||
*/
|
||||
bool setUnsafe(Scope* sc,
|
||||
bool gag = false, Loc loc = Loc.init, const(char)* format = null,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
bool setUnsafe(Scope* sc, bool gag, Loc loc, const(char)* format, RootObject[] args...)
|
||||
{
|
||||
if (sc.intypeof)
|
||||
return false; // typeof(cast(int*)0) is safe
|
||||
@ -468,11 +469,8 @@ bool setUnsafe(Scope* sc,
|
||||
{
|
||||
if (sc.varDecl.storage_class & STC.safe)
|
||||
{
|
||||
OutBuffer buf;
|
||||
buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
|
||||
buf.printf(" can't initialize `@safe` variable `%s`", sc.varDecl.toChars());
|
||||
.error(loc, buf.extractChars());
|
||||
|
||||
string action = AttributeViolation(loc, format, args).action;
|
||||
.error(loc, "%.*s can't initialize `@safe` variable `%s`", action.fTuple.expand, sc.varDecl.toChars());
|
||||
return true;
|
||||
}
|
||||
else if (!(sc.varDecl.storage_class & STC.trusted))
|
||||
@ -491,10 +489,8 @@ bool setUnsafe(Scope* sc,
|
||||
{
|
||||
// Message wil be gagged, but still call error() to update global.errors and for
|
||||
// -verrors=spec
|
||||
OutBuffer buf;
|
||||
buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
|
||||
buf.writestring(" is not allowed in a `@safe` function");
|
||||
.error(loc, buf.extractChars());
|
||||
string action = AttributeViolation(loc, format, args).action;
|
||||
.error(loc, "%.*s is not allowed in a `@safe` function", action.fTuple.expand);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -502,9 +498,9 @@ bool setUnsafe(Scope* sc,
|
||||
|
||||
if (setFunctionToUnsafe(sc.func))
|
||||
{
|
||||
if (format || arg0)
|
||||
if (format || args.length > 0)
|
||||
{
|
||||
reportSafeError(sc.func, gag, loc, format, arg0, arg1, arg2);
|
||||
reportSafeError(sc.func, gag, loc, format, args);
|
||||
}
|
||||
return sc.func.isSafe(); // it is only an error if in an @safe function
|
||||
}
|
||||
@ -527,13 +523,10 @@ bool setUnsafe(Scope* sc,
|
||||
* gag = surpress error message
|
||||
* loc = location of error
|
||||
* format = printf-style format string
|
||||
* arg0 = (optional) argument for first %s format specifier
|
||||
* arg1 = (optional) argument for second %s format specifier
|
||||
* arg2 = (optional) argument for third %s format specifier
|
||||
* args = arguments for format string
|
||||
* Returns: whether an actual safe error (not deprecation) occured
|
||||
*/
|
||||
bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* format,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* format, RootObject[] args...)
|
||||
{
|
||||
//printf("setUnsafePreview() fs:%d %s\n", fs, fmt);
|
||||
assert(format);
|
||||
@ -543,7 +536,7 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)
|
||||
return false;
|
||||
|
||||
case enabled:
|
||||
return sc.setUnsafe(gag, loc, format, arg0, arg1, arg2);
|
||||
return sc.setUnsafe(gag, loc, format, args);
|
||||
|
||||
case default_:
|
||||
if (!sc.func)
|
||||
@ -552,16 +545,14 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)
|
||||
{
|
||||
if (!gag && !sc.isDeprecated())
|
||||
{
|
||||
OutBuffer buf;
|
||||
buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
|
||||
buf.writestring(" will become `@system` in a future release");
|
||||
deprecation(loc, buf.extractChars());
|
||||
string action = AttributeViolation(loc, format, args).action;
|
||||
deprecation(loc, "%.*s will become `@system` in a future release", action.fTuple.expand);
|
||||
}
|
||||
}
|
||||
else if (!sc.func.safetyViolation)
|
||||
{
|
||||
import dmd.func : AttributeViolation;
|
||||
sc.func.safetyViolation = new AttributeViolation(loc, format, arg0, arg1, arg2);
|
||||
sc.func.safetyViolation = new AttributeViolation(loc, format, args);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1699,7 +1699,7 @@ extern (D) bool checkClosure(FuncDeclaration fd)
|
||||
if (!fd.needsClosure())
|
||||
return false;
|
||||
|
||||
if (fd.setGC(fd.loc, "%s `%s` is `@nogc` yet allocates closure for `%s()` with the GC", fd))
|
||||
if (fd.setGC(fd.loc, "allocating a closure for `%s()`", fd))
|
||||
{
|
||||
.error(fd.loc, "%s `%s` is `@nogc` yet allocates closure for `%s()` with the GC", fd.kind, fd.toPrettyChars(), fd.toChars());
|
||||
if (global.gag) // need not report supplemental errors
|
||||
|
@ -3623,9 +3623,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
||||
}
|
||||
|
||||
assert(sc.func);
|
||||
if (!(cas.stc & STC.pure_) && sc.func.setImpure(cas.loc, "`asm` statement is assumed to be impure - mark it with `pure` if it is not"))
|
||||
if (!(cas.stc & STC.pure_) && sc.func.setImpure(cas.loc, "executing an `asm` statement without `pure` annotation"))
|
||||
error(cas.loc, "`asm` statement is assumed to be impure - mark it with `pure` if it is not");
|
||||
if (!(cas.stc & STC.nogc) && sc.func.setGC(cas.loc, "`asm` statement in %s `%s` is assumed to use the GC - mark it with `@nogc` if it does not"))
|
||||
if (!(cas.stc & STC.nogc) && sc.func.setGC(cas.loc, "executing an `asm` statement without `@nogc` annotation"))
|
||||
error(cas.loc, "`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
|
||||
// @@@DEPRECATED_2.114@@@
|
||||
// change deprecation() to error(), add `else` and remove `| STC.safe`
|
||||
@ -3634,7 +3634,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
|
||||
deprecation(cas.loc, "`asm` statement cannot be marked `@safe`, use `@system` or `@trusted` instead");
|
||||
if (!(cas.stc & (STC.trusted | STC.safe)))
|
||||
{
|
||||
sc.setUnsafe(false, cas.loc, "`asm` statement without `@trusted` annotation");
|
||||
sc.setUnsafe(false, cas.loc, "executing an `asm` statement without `@trusted` annotation");
|
||||
}
|
||||
|
||||
sc.pop();
|
||||
|
@ -944,8 +944,8 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bpure = !f.isPure && sc.func.setImpure();
|
||||
bool bsafe = !f.isSafe() && !f.isTrusted() && sc.setUnsafe();
|
||||
bool bpure = !f.isPure && sc.func.setImpure(arg.loc, null);
|
||||
bool bsafe = !f.isSafe() && !f.isTrusted() && sc.setUnsafe(false, arg.loc, null);
|
||||
bool bnogc = !f.isNogc && sc.func.setGC(arg.loc, null);
|
||||
if (bpure | bsafe | bnogc)
|
||||
{
|
||||
|
@ -19,6 +19,6 @@ void test3() @nogc
|
||||
|
||||
void test4() @safe
|
||||
{
|
||||
asm { } // { dg-error "'asm' statement without '@trusted' annotation is not allowed in a '@safe' function" }
|
||||
asm { } // { dg-error ".asm. statement without .@trusted. annotation is not allowed in a .@safe. function" }
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,17 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
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 wasn't inferred `@safe` because of:
|
||||
fail_compilation/attributediagnostic.d(30): `asm` statement without `@trusted` annotation
|
||||
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 wasn't inferred `@safe` because of:
|
||||
fail_compilation/attributediagnostic.d(35): cast from `uint` to `int*`
|
||||
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 wasn't inferred `@safe` because of:
|
||||
fail_compilation/attributediagnostic.d(41): `@safe` function `system2` cannot call `@system` `fsys`
|
||||
fail_compilation/attributediagnostic.d(39): `attributediagnostic.system2` is declared here
|
||||
fail_compilation/attributediagnostic.d(21): Error: `@safe` function `attributediagnostic.layer2` cannot call `@system` function `attributediagnostic.layer1`
|
||||
fail_compilation/attributediagnostic.d(23): which calls `attributediagnostic.layer0`
|
||||
fail_compilation/attributediagnostic.d(25): which calls `attributediagnostic.system`
|
||||
fail_compilation/attributediagnostic.d(27): and executing an `asm` statement without `@trusted` annotation makes it fail to infer `@safe`
|
||||
fail_compilation/attributediagnostic.d(22): `attributediagnostic.layer1` is declared here
|
||||
fail_compilation/attributediagnostic.d(43): Error: `@safe` function `D main` cannot call `@system` function `attributediagnostic.system1`
|
||||
fail_compilation/attributediagnostic.d(32): and cast from `uint` to `int*` makes it fail to infer `@safe`
|
||||
fail_compilation/attributediagnostic.d(30): `attributediagnostic.system1` is declared here
|
||||
fail_compilation/attributediagnostic.d(44): Error: `@safe` function `D main` cannot call `@system` function `attributediagnostic.system2`
|
||||
fail_compilation/attributediagnostic.d(38): and calling `@system` `fsys` makes it fail to infer `@safe`
|
||||
fail_compilation/attributediagnostic.d(36): `attributediagnostic.system2` is declared here
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -4,17 +4,13 @@ TEST_OUTPUT:
|
||||
fail_compilation/attributediagnostic_nogc.d(21): Error: `@nogc` function `attributediagnostic_nogc.layer2` cannot call non-@nogc function `attributediagnostic_nogc.layer1`
|
||||
fail_compilation/attributediagnostic_nogc.d(22): which calls `attributediagnostic_nogc.layer0`
|
||||
fail_compilation/attributediagnostic_nogc.d(23): which calls `attributediagnostic_nogc.gc`
|
||||
fail_compilation/attributediagnostic_nogc.d(27): which wasn't inferred `@nogc` because of:
|
||||
fail_compilation/attributediagnostic_nogc.d(27): `asm` statement in function `attributediagnostic_nogc.gc` is assumed to use the GC - mark it with `@nogc` if it does not
|
||||
fail_compilation/attributediagnostic_nogc.d(27): and executing an `asm` statement without `@nogc` annotation makes it fail to infer `@nogc`
|
||||
fail_compilation/attributediagnostic_nogc.d(43): Error: `@nogc` function `D main` cannot call non-@nogc function `attributediagnostic_nogc.gc1`
|
||||
fail_compilation/attributediagnostic_nogc.d(32): which wasn't inferred `@nogc` because of:
|
||||
fail_compilation/attributediagnostic_nogc.d(32): cannot use `new` in `@nogc` function `attributediagnostic_nogc.gc1`
|
||||
fail_compilation/attributediagnostic_nogc.d(32): and allocating with `new` makes it fail to infer `@nogc`
|
||||
fail_compilation/attributediagnostic_nogc.d(44): Error: `@nogc` function `D main` cannot call non-@nogc function `attributediagnostic_nogc.gc2`
|
||||
fail_compilation/attributediagnostic_nogc.d(38): which wasn't inferred `@nogc` because of:
|
||||
fail_compilation/attributediagnostic_nogc.d(38): `@nogc` function `attributediagnostic_nogc.gc2` cannot call non-@nogc `fgc`
|
||||
fail_compilation/attributediagnostic_nogc.d(38): and calling non-@nogc `fgc` makes it fail to infer `@nogc`
|
||||
fail_compilation/attributediagnostic_nogc.d(45): Error: `@nogc` function `D main` cannot call non-@nogc function `attributediagnostic_nogc.gcClosure`
|
||||
fail_compilation/attributediagnostic_nogc.d(48): which wasn't inferred `@nogc` because of:
|
||||
fail_compilation/attributediagnostic_nogc.d(48): function `attributediagnostic_nogc.gcClosure` is `@nogc` yet allocates closure for `gcClosure()` with the GC
|
||||
fail_compilation/attributediagnostic_nogc.d(48): and allocating a closure for `gcClosure()` makes it fail to infer `@nogc`
|
||||
---
|
||||
*/
|
||||
#line 18
|
||||
|
@ -1,17 +1,15 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/attributediagnostic_nothrow.d(21): Error: function `attributediagnostic_nothrow.layer1` is not `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(22): which calls `attributediagnostic_nothrow.layer0`
|
||||
fail_compilation/attributediagnostic_nothrow.d(23): which calls `attributediagnostic_nothrow.gc`
|
||||
fail_compilation/attributediagnostic_nothrow.d(27): which wasn't inferred `nothrow` because of:
|
||||
fail_compilation/attributediagnostic_nothrow.d(27): `asm` statement is assumed to throw - mark it with `nothrow` if it does not
|
||||
fail_compilation/attributediagnostic_nothrow.d(21): Error: function `attributediagnostic_nothrow.layer2` may throw but is marked as `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(43): Error: function `attributediagnostic_nothrow.gc1` is not `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(32): which wasn't inferred `nothrow` because of:
|
||||
fail_compilation/attributediagnostic_nothrow.d(32): `object.Exception` is thrown but not caught
|
||||
fail_compilation/attributediagnostic_nothrow.d(44): Error: function `attributediagnostic_nothrow.gc2` is not `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(41): Error: function `D main` may throw but is marked as `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(19): Error: function `attributediagnostic_nothrow.layer1` is not `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(20): which calls `attributediagnostic_nothrow.layer0`
|
||||
fail_compilation/attributediagnostic_nothrow.d(21): which calls `attributediagnostic_nothrow.gc`
|
||||
fail_compilation/attributediagnostic_nothrow.d(25): and executing an `asm` statement without a `nothrow` annotation makes it fail to infer `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(19): Error: function `attributediagnostic_nothrow.layer2` may throw but is marked as `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(41): Error: function `attributediagnostic_nothrow.gc1` is not `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(30): and `object.Exception` being thrown but not caught makes it fail to infer `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(42): Error: function `attributediagnostic_nothrow.gc2` is not `nothrow`
|
||||
fail_compilation/attributediagnostic_nothrow.d(39): Error: function `D main` may throw but is marked as `nothrow`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/attributediagnostic_pure.d(20): Error: `pure` function `D main` cannot call impure function `attributediagnostic_pure.gc`
|
||||
fail_compilation/attributediagnostic_pure.d(15): which wasn't inferred `pure` because of:
|
||||
fail_compilation/attributediagnostic_pure.d(15): `asm` statement is assumed to be impure - mark it with `pure` if it is not
|
||||
fail_compilation/attributediagnostic_pure.d(19): Error: `pure` function `D main` cannot call impure function `attributediagnostic_pure.gc`
|
||||
fail_compilation/attributediagnostic_pure.d(14): and executing an `asm` statement without `pure` annotation makes it fail to infer `pure`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,21 +1,18 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag10319.d(33): Error: `pure` function `D main` cannot call impure function `diag10319.foo`
|
||||
fail_compilation/diag10319.d(33): Error: `@safe` function `D main` cannot call `@system` function `diag10319.foo`
|
||||
fail_compilation/diag10319.d(22): `diag10319.foo` is declared here
|
||||
fail_compilation/diag10319.d(34): Error: `pure` function `D main` cannot call impure function `diag10319.bar!int.bar`
|
||||
fail_compilation/diag10319.d(26): which wasn't inferred `pure` because of:
|
||||
fail_compilation/diag10319.d(26): `pure` function `diag10319.bar!int.bar` cannot access mutable static data `g`
|
||||
fail_compilation/diag10319.d(34): Error: `@safe` function `D main` cannot call `@system` function `diag10319.bar!int.bar`
|
||||
fail_compilation/diag10319.d(27): which wasn't inferred `@safe` because of:
|
||||
fail_compilation/diag10319.d(27): taking the address of stack-allocated local variable `x`
|
||||
fail_compilation/diag10319.d(24): `diag10319.bar!int.bar` is declared here
|
||||
fail_compilation/diag10319.d(33): Error: function `diag10319.foo` is not `nothrow`
|
||||
fail_compilation/diag10319.d(34): Error: function `diag10319.bar!int.bar` is not `nothrow`
|
||||
fail_compilation/diag10319.d(28): which wasn't inferred `nothrow` because of:
|
||||
fail_compilation/diag10319.d(28): `object.Exception` is thrown but not caught
|
||||
fail_compilation/diag10319.d(31): Error: function `D main` may throw but is marked as `nothrow`
|
||||
fail_compilation/diag10319.d(30): Error: `pure` function `D main` cannot call impure function `diag10319.foo`
|
||||
fail_compilation/diag10319.d(30): Error: `@safe` function `D main` cannot call `@system` function `diag10319.foo`
|
||||
fail_compilation/diag10319.d(19): `diag10319.foo` is declared here
|
||||
fail_compilation/diag10319.d(31): Error: `pure` function `D main` cannot call impure function `diag10319.bar!int.bar`
|
||||
fail_compilation/diag10319.d(23): and accessing mutable static data `g` makes it fail to infer `pure`
|
||||
fail_compilation/diag10319.d(31): Error: `@safe` function `D main` cannot call `@system` function `diag10319.bar!int.bar`
|
||||
fail_compilation/diag10319.d(24): and taking the address of stack-allocated local variable `x` makes it fail to infer `@safe`
|
||||
fail_compilation/diag10319.d(21): `diag10319.bar!int.bar` is declared here
|
||||
fail_compilation/diag10319.d(30): Error: function `diag10319.foo` is not `nothrow`
|
||||
fail_compilation/diag10319.d(31): Error: function `diag10319.bar!int.bar` is not `nothrow`
|
||||
fail_compilation/diag10319.d(25): and `object.Exception` being thrown but not caught makes it fail to infer `nothrow`
|
||||
fail_compilation/diag10319.d(28): Error: function `D main` may throw but is marked as `nothrow`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,14 +1,10 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
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 `""`
|
||||
fail_compilation/diag11198.d(13): Error: version `blah` declaration must be at module level
|
||||
fail_compilation/diag11198.d(14): Error: debug `blah` declaration must be at module level
|
||||
fail_compilation/diag11198.d(15): Error: identifier expected, not `""`
|
||||
fail_compilation/diag11198.d(16): Error: identifier expected, not `""`
|
||||
---
|
||||
*/
|
||||
|
||||
@ -16,8 +12,6 @@ void main()
|
||||
{
|
||||
version = blah;
|
||||
debug = blah;
|
||||
version = 1;
|
||||
debug = 2;
|
||||
version = "";
|
||||
debug = "";
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag9620.d(20): Error: `pure` function `diag9620.main.bar` cannot call impure function `diag9620.foo1`
|
||||
fail_compilation/diag9620.d(21): Error: `pure` function `diag9620.main.bar` cannot call impure function `diag9620.foo2!().foo2`
|
||||
fail_compilation/diag9620.d(14): which wasn't inferred `pure` because of:
|
||||
fail_compilation/diag9620.d(14): `pure` function `diag9620.foo2!().foo2` cannot access mutable static data `x`
|
||||
fail_compilation/diag9620.d(19): Error: `pure` function `diag9620.main.bar` cannot call impure function `diag9620.foo1`
|
||||
fail_compilation/diag9620.d(20): Error: `pure` function `diag9620.main.bar` cannot call impure function `diag9620.foo2!().foo2`
|
||||
fail_compilation/diag9620.d(13): and accessing mutable static data `x` makes it fail to infer `pure`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag_debug_conditional.d(1): Error: identifier or integer expected inside `debug(...)`, not `alias`
|
||||
fail_compilation/diag_debug_conditional.d(2): Error: identifier or integer expected inside `version(...)`, not `alias`
|
||||
fail_compilation/diag_debug_conditional.d(1): Error: identifier expected inside `debug(...)`, not `alias`
|
||||
fail_compilation/diag_debug_conditional.d(2): Error: identifier expected inside `version(...)`, not `alias`
|
||||
fail_compilation/diag_debug_conditional.d(3): Error: declaration expected following attribute, not end of file
|
||||
---
|
||||
*/
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail12932.d(11): Error: array literal in `@nogc` function `fail12932.foo` may cause a GC allocation
|
||||
fail_compilation/fail12932.d(15): Error: array literal in `@nogc` function `fail12932.foo` may cause a GC allocation
|
||||
fail_compilation/fail12932.d(11): Error: this array literal causes a GC allocation in `@nogc` function `foo`
|
||||
fail_compilation/fail12932.d(15): Error: this array literal causes a GC allocation in `@nogc` function `foo`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail21928.d(18): Error: array literal in `@nogc` function `D main` may cause a GC allocation
|
||||
fail_compilation/fail21928.d(18): Error: this array literal causes a GC allocation in `@nogc` function `main`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail21928b.d(18): Error: array literal in `@nogc` function `D main` may cause a GC allocation
|
||||
fail_compilation/fail21928b.d(18): Error: this array literal causes a GC allocation in `@nogc` function `main`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/lexer23465.d(19): Error: character 0x1f37a is not allowed as a continue character in an identifier
|
||||
fail_compilation/lexer23465.d(19): Error: character 0x1f37a is not a valid token
|
||||
fail_compilation/lexer23465.d(20): Error: character '\' is not a valid token
|
||||
fail_compilation/lexer23465.d(21): Error: unterminated /+ +/ comment
|
||||
fail_compilation/lexer23465.d(22): Error: found `End of File` instead of array initializer
|
||||
fail_compilation/lexer23465.d(22): Error: semicolon needed to end declaration of `arr`, instead of `End of File`
|
||||
fail_compilation/lexer23465.d(17): `arr` declared here
|
||||
fail_compilation/lexer23465.d(22): Error: character 0x1f37a is not allowed as a continue character in an identifier
|
||||
fail_compilation/lexer23465.d(22): Error: character 0x1f37a is not a valid token
|
||||
fail_compilation/lexer23465.d(23): Error: character '\' is not a valid token
|
||||
fail_compilation/lexer23465.d(24): Error: octal digit expected, not `9`
|
||||
fail_compilation/lexer23465.d(24): Error: octal literals larger than 7 are no longer supported
|
||||
fail_compilation/lexer23465.d(25): Error: integer overflow
|
||||
fail_compilation/lexer23465.d(26): Error: unterminated /+ +/ comment
|
||||
fail_compilation/lexer23465.d(27): Error: found `End of File` instead of array initializer
|
||||
fail_compilation/lexer23465.d(27): Error: semicolon needed to end declaration of `arr`, instead of `End of File`
|
||||
fail_compilation/lexer23465.d(20): `arr` declared here
|
||||
---
|
||||
*/
|
||||
|
||||
@ -18,4 +21,6 @@ int[] arr = [
|
||||
0,
|
||||
x🍺,
|
||||
3\,
|
||||
09,
|
||||
9999999999999999999999,
|
||||
5, /+
|
||||
|
@ -9,13 +9,13 @@ struct S3 { this(int) @nogc; }
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc1.d(23): Error: cannot use `new` in `@nogc` function `nogc1.testNew`
|
||||
fail_compilation/nogc1.d(25): Error: cannot use `new` in `@nogc` function `nogc1.testNew`
|
||||
fail_compilation/nogc1.d(26): Error: cannot use `new` in `@nogc` function `nogc1.testNew`
|
||||
fail_compilation/nogc1.d(28): Error: cannot use `new` in `@nogc` function `nogc1.testNew`
|
||||
fail_compilation/nogc1.d(23): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNew`
|
||||
fail_compilation/nogc1.d(25): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNew`
|
||||
fail_compilation/nogc1.d(26): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNew`
|
||||
fail_compilation/nogc1.d(28): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNew`
|
||||
fail_compilation/nogc1.d(29): Error: `@nogc` function `nogc1.testNew` cannot call non-@nogc constructor `nogc1.S2.this`
|
||||
fail_compilation/nogc1.d(30): Error: cannot use `new` in `@nogc` function `nogc1.testNew`
|
||||
fail_compilation/nogc1.d(32): Error: cannot use `new` in `@nogc` function `nogc1.testNew`
|
||||
fail_compilation/nogc1.d(30): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNew`
|
||||
fail_compilation/nogc1.d(32): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNew`
|
||||
---
|
||||
*/
|
||||
@nogc void testNew()
|
||||
@ -35,12 +35,12 @@ fail_compilation/nogc1.d(32): Error: cannot use `new` in `@nogc` function `nogc1
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc1.d(48): Error: cannot use `new` in `@nogc` function `nogc1.testNewScope`
|
||||
fail_compilation/nogc1.d(50): Error: cannot use `new` in `@nogc` function `nogc1.testNewScope`
|
||||
fail_compilation/nogc1.d(51): Error: cannot use `new` in `@nogc` function `nogc1.testNewScope`
|
||||
fail_compilation/nogc1.d(53): Error: cannot use `new` in `@nogc` function `nogc1.testNewScope`
|
||||
fail_compilation/nogc1.d(48): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNewScope`
|
||||
fail_compilation/nogc1.d(50): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNewScope`
|
||||
fail_compilation/nogc1.d(51): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNewScope`
|
||||
fail_compilation/nogc1.d(53): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNewScope`
|
||||
fail_compilation/nogc1.d(54): Error: `@nogc` function `nogc1.testNewScope` cannot call non-@nogc constructor `nogc1.S2.this`
|
||||
fail_compilation/nogc1.d(55): Error: cannot use `new` in `@nogc` function `nogc1.testNewScope`
|
||||
fail_compilation/nogc1.d(55): Error: allocating with `new` causes a GC allocation in `@nogc` function `testNewScope`
|
||||
---
|
||||
*/
|
||||
@nogc void testNewScope()
|
||||
|
@ -5,14 +5,14 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc2.d(20): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(21): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(22): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(24): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(25): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(26): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(27): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(28): Error: cannot use operator `~` in `@nogc` function `nogc2.testCat`
|
||||
fail_compilation/nogc2.d(20): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(21): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(22): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(24): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(25): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(26): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(27): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
fail_compilation/nogc2.d(28): Error: concatenating with operator `~` causes a GC allocation in `@nogc` function `testCat`
|
||||
---
|
||||
*/
|
||||
@nogc void testCat(int[] a, string s)
|
||||
@ -37,9 +37,9 @@ fail_compilation/nogc2.d(28): Error: cannot use operator `~` in `@nogc` function
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc2.d(47): Error: cannot use operator `~=` in `@nogc` function `nogc2.testCatAssign`
|
||||
fail_compilation/nogc2.d(49): Error: cannot use operator `~=` in `@nogc` function `nogc2.testCatAssign`
|
||||
fail_compilation/nogc2.d(50): Error: cannot use operator `~=` in `@nogc` function `nogc2.testCatAssign`
|
||||
fail_compilation/nogc2.d(47): Error: appending to this array with operator `~=` causes a GC allocation in `@nogc` function `testCatAssign`
|
||||
fail_compilation/nogc2.d(49): Error: appending to this array with operator `~=` causes a GC allocation in `@nogc` function `testCatAssign`
|
||||
fail_compilation/nogc2.d(50): Error: appending to this array with operator `~=` causes a GC allocation in `@nogc` function `testCatAssign`
|
||||
---
|
||||
*/
|
||||
@nogc void testCatAssign(int[] a, string s)
|
||||
@ -57,8 +57,8 @@ fail_compilation/nogc2.d(50): Error: cannot use operator `~=` in `@nogc` functio
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc2.d(69): Error: array literal in `@nogc` function `nogc2.testArray` may cause a GC allocation
|
||||
fail_compilation/nogc2.d(70): Error: array literal in `@nogc` function `nogc2.testArray` may cause a GC allocation
|
||||
fail_compilation/nogc2.d(69): Error: this array literal causes a GC allocation in `@nogc` function `testArray`
|
||||
fail_compilation/nogc2.d(70): Error: this array literal causes a GC allocation in `@nogc` function `testArray`
|
||||
---
|
||||
*/
|
||||
@nogc void testArray()
|
||||
@ -75,8 +75,8 @@ fail_compilation/nogc2.d(70): Error: array literal in `@nogc` function `nogc2.te
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc2.d(86): Error: associative array literal in `@nogc` function `nogc2.testAssocArray` may cause a GC allocation
|
||||
fail_compilation/nogc2.d(87): Error: associative array literal in `@nogc` function `nogc2.testAssocArray` may cause a GC allocation
|
||||
fail_compilation/nogc2.d(86): Error: this associative array literal causes a GC allocation in `@nogc` function `testAssocArray`
|
||||
fail_compilation/nogc2.d(87): Error: this associative array literal causes a GC allocation in `@nogc` function `testAssocArray`
|
||||
---
|
||||
*/
|
||||
@nogc void testAssocArray()
|
||||
@ -92,7 +92,7 @@ fail_compilation/nogc2.d(87): Error: associative array literal in `@nogc` functi
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc2.d(100): Error: assigning an associative array element in `@nogc` function `nogc2.testIndex` may cause a GC allocation
|
||||
fail_compilation/nogc2.d(100): Error: assigning this associative array element causes a GC allocation in `@nogc` function `testIndex`
|
||||
---
|
||||
*/
|
||||
@nogc void testIndex(int[int] aa)
|
||||
|
@ -5,9 +5,9 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc3.d(15): Error: setting `length` in `@nogc` function `nogc3.testArrayLength` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(16): Error: setting `length` in `@nogc` function `nogc3.testArrayLength` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(17): Error: setting `length` in `@nogc` function `nogc3.testArrayLength` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(15): Error: setting this array's `length` causes a GC allocation in `@nogc` function `testArrayLength`
|
||||
fail_compilation/nogc3.d(16): Error: setting this array's `length` causes a GC allocation in `@nogc` function `testArrayLength`
|
||||
fail_compilation/nogc3.d(17): Error: setting this array's `length` causes a GC allocation in `@nogc` function `testArrayLength`
|
||||
---
|
||||
*/
|
||||
@nogc void testArrayLength(int[] a)
|
||||
@ -75,10 +75,10 @@ fail_compilation/nogc3.d(68): `x` declared here
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/nogc3.d(87): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(88): Error: array literal in `@nogc` function `nogc3.foo13702` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(94): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(93): Error: array literal in `@nogc` function `nogc3.bar13702` may cause a GC allocation
|
||||
fail_compilation/nogc3.d(87): Error: this array literal causes a GC allocation in `@nogc` function `foo13702`
|
||||
fail_compilation/nogc3.d(88): Error: this array literal causes a GC allocation in `@nogc` function `foo13702`
|
||||
fail_compilation/nogc3.d(94): Error: this array literal causes a GC allocation in `@nogc` function `bar13702`
|
||||
fail_compilation/nogc3.d(93): Error: this array literal causes a GC allocation in `@nogc` function `bar13702`
|
||||
---
|
||||
*/
|
||||
int[] foo13702(bool b) @nogc
|
||||
|
@ -2,10 +2,9 @@
|
||||
REQUIRED_ARGS: -de
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/systemvariables_deprecation.d(16): Deprecation: `@safe` function `main` calling `middle`
|
||||
fail_compilation/systemvariables_deprecation.d(21): which calls `systemvariables_deprecation.inferred`
|
||||
fail_compilation/systemvariables_deprecation.d(27): which wouldn't be `@safe` because of:
|
||||
fail_compilation/systemvariables_deprecation.d(27): access `@system` variable `x0`
|
||||
fail_compilation/systemvariables_deprecation.d(15): Deprecation: `@safe` function `main` calling `middle`
|
||||
fail_compilation/systemvariables_deprecation.d(20): which calls `systemvariables_deprecation.inferred`
|
||||
fail_compilation/systemvariables_deprecation.d(26): and access `@system` variable `x0` makes it fail to infer `@safe`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,21 +1,15 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
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
|
||||
fail_compilation/test13786.d(12): Error: debug `abc` declaration must be at module level
|
||||
fail_compilation/test13786.d(13): Error: version `abc` declaration must be at module level
|
||||
fail_compilation/test13786.d(16): Error: template instance `test13786.T!()` error instantiating
|
||||
---
|
||||
*/
|
||||
|
||||
template T()
|
||||
{
|
||||
debug = 123;
|
||||
debug = abc;
|
||||
version = 123;
|
||||
version = abc;
|
||||
}
|
||||
|
||||
|
@ -2,15 +2,12 @@
|
||||
REQUIRED_ARGS: -de
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test20655.d(29): Deprecation: `@safe` function `g` calling `f1`
|
||||
fail_compilation/test20655.d(24): which wouldn't be `@safe` because of:
|
||||
fail_compilation/test20655.d(24): accessing overlapped field `U.s` with pointers
|
||||
fail_compilation/test20655.d(30): Deprecation: `@safe` function `g` calling `f2`
|
||||
fail_compilation/test20655.d(25): which wouldn't be `@safe` because of:
|
||||
fail_compilation/test20655.d(25): accessing overlapped field `U.s` with pointers
|
||||
fail_compilation/test20655.d(31): Deprecation: `@safe` function `g` calling `f3`
|
||||
fail_compilation/test20655.d(28): which wouldn't be `@safe` because of:
|
||||
fail_compilation/test20655.d(28): accessing overlapped field `U.s` with pointers
|
||||
fail_compilation/test20655.d(26): Deprecation: `@safe` function `g` calling `f1`
|
||||
fail_compilation/test20655.d(21): and accessing overlapped field `U.s` with pointers makes it fail to infer `@safe`
|
||||
fail_compilation/test20655.d(27): Deprecation: `@safe` function `g` calling `f2`
|
||||
fail_compilation/test20655.d(22): and accessing overlapped field `U.s` with pointers makes it fail to infer `@safe`
|
||||
fail_compilation/test20655.d(28): Deprecation: `@safe` function `g` calling `f3`
|
||||
fail_compilation/test20655.d(25): and accessing overlapped field `U.s` with pointers makes it fail to infer `@safe`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test23170.d(10): Error: array literal in `@nogc` delegate `test23170.__lambda_L10_C15` may cause a GC allocation
|
||||
fail_compilation/test23170.d(10): Error: this array literal causes a GC allocation in `@nogc` delegate `__lambda_L10_C15`
|
||||
---
|
||||
*/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23170
|
||||
|
@ -140,8 +140,7 @@ TEST_OUTPUT:
|
||||
fail_compilation/testInference.d(154): Error: `pure` function `testInference.bar14049` cannot call impure function `testInference.foo14049!int.foo14049`
|
||||
fail_compilation/testInference.d(149): which calls `testInference.foo14049!int.foo14049.__lambda_L147_C14`
|
||||
fail_compilation/testInference.d(148): which calls `testInference.impure14049`
|
||||
fail_compilation/testInference.d(143): which wasn't inferred `pure` because of:
|
||||
fail_compilation/testInference.d(143): `pure` function `testInference.impure14049` cannot access mutable static data `i`
|
||||
fail_compilation/testInference.d(143): and accessing mutable static data `i` makes it fail to infer `pure`
|
||||
---
|
||||
*/
|
||||
#line 143
|
||||
@ -191,11 +190,9 @@ void test12422() pure
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/testInference.d(198): Error: `pure` function `testInference.test13729a` cannot call impure function `testInference.test13729a.foo`
|
||||
fail_compilation/testInference.d(196): which wasn't inferred `pure` because of:
|
||||
fail_compilation/testInference.d(196): `pure` function `testInference.test13729a.foo` cannot access mutable static data `g13729`
|
||||
fail_compilation/testInference.d(196): and accessing mutable static data `g13729` makes it fail to infer `pure`
|
||||
fail_compilation/testInference.d(206): Error: `pure` function `testInference.test13729b` cannot call impure function `testInference.test13729b.foo!().foo`
|
||||
fail_compilation/testInference.d(204): which wasn't inferred `pure` because of:
|
||||
fail_compilation/testInference.d(204): `pure` function `testInference.test13729b.foo!().foo` cannot access mutable static data `g13729`
|
||||
fail_compilation/testInference.d(204): and accessing mutable static data `g13729` makes it fail to infer `pure`
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -1,14 +1,3 @@
|
||||
// REQUIRED_ARGS: -verrors=simple
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
runnable/lexer.d(86): Deprecation: `version( <integer> )` is deprecated, use version identifiers instead
|
||||
runnable/lexer.d(87): Deprecation: `debug( <integer> )` is deprecated, use debug identifiers instead
|
||||
---
|
||||
*/
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
void test6()
|
||||
{
|
||||
string s = q"(foo(xxx))";
|
||||
@ -82,12 +71,6 @@ void test8()
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=6584
|
||||
version(9223372036854775807){}
|
||||
debug(9223372036854775807){}
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
enum e13102=184467440737095516153.6L;
|
||||
|
||||
/*********************************************************/
|
||||
|
@ -4330,28 +4330,28 @@ void test14696(int len = 2)
|
||||
check({ foo(len > 2 ? null : (len != 2 ? null : makeS(1).get() ) ); }, "makeS(1).get(1).foo.dtor(1).");
|
||||
|
||||
// temporary in condition and throwing callee
|
||||
// check({ fooThrow(len == 2 ? makeS(1).get() : null); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
// check({ fooThrow(len == 2 ? null : makeS(1).get() ); }, "fooThrow.");
|
||||
// check({ fooThrow(len != 2 ? makeS(1).get() : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len != 2 ? null : makeS(1).get() ); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
check({ fooThrow(len == 2 ? makeS(1).get() : null); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
check({ fooThrow(len == 2 ? null : makeS(1).get() ); }, "fooThrow.");
|
||||
check({ fooThrow(len != 2 ? makeS(1).get() : null); }, "fooThrow.");
|
||||
check({ fooThrow(len != 2 ? null : makeS(1).get() ); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
|
||||
// temporary in nesting condititions and throwing callee
|
||||
// check({ fooThrow(len >= 2 ? (len == 2 ? makeS(1).get() : null) : null); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
// check({ fooThrow(len >= 2 ? (len == 2 ? null : makeS(1).get() ) : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len >= 2 ? (len != 2 ? makeS(1).get() : null) : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len >= 2 ? (len != 2 ? null : makeS(1).get() ) : null); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
// check({ fooThrow(len >= 2 ? null : (len == 2 ? makeS(1).get() : null) ); }, "fooThrow.");
|
||||
// check({ fooThrow(len >= 2 ? null : (len == 2 ? null : makeS(1).get() ) ); }, "fooThrow.");
|
||||
// check({ fooThrow(len >= 2 ? null : (len != 2 ? makeS(1).get() : null) ); }, "fooThrow.");
|
||||
// check({ fooThrow(len >= 2 ? null : (len != 2 ? null : makeS(1).get() ) ); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? (len == 2 ? makeS(1).get() : null) : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? (len == 2 ? null : makeS(1).get() ) : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? (len != 2 ? makeS(1).get() : null) : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? (len != 2 ? null : makeS(1).get() ) : null); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? null : (len == 2 ? makeS(1).get() : null) ); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
// check({ fooThrow(len > 2 ? null : (len == 2 ? null : makeS(1).get() ) ); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? null : (len != 2 ? makeS(1).get() : null) ); }, "fooThrow.");
|
||||
// check({ fooThrow(len > 2 ? null : (len != 2 ? null : makeS(1).get() ) ); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
check({ fooThrow(len >= 2 ? (len == 2 ? makeS(1).get() : null) : null); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
check({ fooThrow(len >= 2 ? (len == 2 ? null : makeS(1).get() ) : null); }, "fooThrow.");
|
||||
check({ fooThrow(len >= 2 ? (len != 2 ? makeS(1).get() : null) : null); }, "fooThrow.");
|
||||
check({ fooThrow(len >= 2 ? (len != 2 ? null : makeS(1).get() ) : null); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
check({ fooThrow(len >= 2 ? null : (len == 2 ? makeS(1).get() : null) ); }, "fooThrow.");
|
||||
check({ fooThrow(len >= 2 ? null : (len == 2 ? null : makeS(1).get() ) ); }, "fooThrow.");
|
||||
check({ fooThrow(len >= 2 ? null : (len != 2 ? makeS(1).get() : null) ); }, "fooThrow.");
|
||||
check({ fooThrow(len >= 2 ? null : (len != 2 ? null : makeS(1).get() ) ); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? (len == 2 ? makeS(1).get() : null) : null); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? (len == 2 ? null : makeS(1).get() ) : null); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? (len != 2 ? makeS(1).get() : null) : null); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? (len != 2 ? null : makeS(1).get() ) : null); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? null : (len == 2 ? makeS(1).get() : null) ); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
check({ fooThrow(len > 2 ? null : (len == 2 ? null : makeS(1).get() ) ); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? null : (len != 2 ? makeS(1).get() : null) ); }, "fooThrow.");
|
||||
check({ fooThrow(len > 2 ? null : (len != 2 ? null : makeS(1).get() ) ); }, "makeS(1).get(1).fooThrow.dtor(1).");
|
||||
|
||||
// temporaries in each conditions
|
||||
check({ foo(len == 2 ? makeS(1).get() : null, len == 2 ? makeS(2).get() : null); }, "makeS(1).get(1).makeS(2).get(2).foo.dtor(2).dtor(1).");
|
||||
|
@ -1,4 +1,4 @@
|
||||
d6f693b46a1565172cac7a1438905141783a164f
|
||||
d1157134103a209d36d6ee9c1df1d61d5929ec6d
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
module core.gc.config;
|
||||
|
||||
import core.stdc.stdio;
|
||||
import core.internal.parseoptions;
|
||||
import core.stdc.stdio : printf;
|
||||
|
||||
__gshared Config config;
|
||||
|
||||
|
@ -794,7 +794,7 @@ version (unittest)
|
||||
{
|
||||
version (none)
|
||||
{
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.stdio : printf;
|
||||
|
||||
@trusted
|
||||
void print(Cent c)
|
||||
|
@ -349,7 +349,7 @@ T[] _d_newarrayU(T)(size_t length, bool isShared=false) @trusted
|
||||
{
|
||||
import core.exception : onOutOfMemoryError;
|
||||
import core.internal.traits : Unqual;
|
||||
import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc;
|
||||
import core.internal.array.utils : __arrayAlloc;
|
||||
|
||||
alias UnqT = Unqual!T;
|
||||
|
||||
@ -395,16 +395,11 @@ Loverflow:
|
||||
assert(0);
|
||||
|
||||
Lcontinue:
|
||||
auto info = __arrayAlloc!UnqT(arraySize);
|
||||
if (!info.base)
|
||||
auto arr = __arrayAlloc!UnqT(arraySize);
|
||||
if (!arr.ptr)
|
||||
goto Loverflow;
|
||||
debug(PRINTF) printf("p = %p\n", info.base);
|
||||
|
||||
auto arrstart = __arrayStart(info);
|
||||
|
||||
__setArrayAllocLength!UnqT(info, arraySize, isShared);
|
||||
|
||||
return (cast(T*) arrstart)[0 .. length];
|
||||
debug(PRINTF) printf("p = %p\n", arr.ptr);
|
||||
return (cast(T*) arr.ptr)[0 .. length];
|
||||
}
|
||||
|
||||
/// ditto
|
||||
@ -522,7 +517,7 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust
|
||||
|
||||
void[] __allocateInnerArray(size_t[] dims)
|
||||
{
|
||||
import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc;
|
||||
import core.internal.array.utils : __arrayAlloc;
|
||||
|
||||
auto dim = dims[0];
|
||||
|
||||
@ -535,15 +530,13 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust
|
||||
|
||||
auto allocSize = (void[]).sizeof * dim;
|
||||
// the array-of-arrays holds pointers! Don't use UnqT here!
|
||||
auto info = __arrayAlloc!(void[])(allocSize);
|
||||
__setArrayAllocLength!(void[])(info, allocSize, isShared);
|
||||
auto p = __arrayStart(info)[0 .. dim];
|
||||
auto arr = __arrayAlloc!(void[])(allocSize);
|
||||
|
||||
foreach (i; 0..dim)
|
||||
{
|
||||
(cast(void[]*)p.ptr)[i] = __allocateInnerArray(dims[1..$]);
|
||||
(cast(void[]*)arr.ptr)[i] = __allocateInnerArray(dims[1..$]);
|
||||
}
|
||||
return p;
|
||||
return arr.ptr[0 .. dim];
|
||||
}
|
||||
|
||||
auto result = __allocateInnerArray(dims);
|
||||
@ -580,6 +573,21 @@ unittest
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3-level array allocation (this uses different code paths).
|
||||
unittest
|
||||
{
|
||||
int[][][] a = _d_newarraymTX!(int[][][], int)([3, 4, 5]);
|
||||
int[5] zeros = 0;
|
||||
|
||||
assert(a.length == 3);
|
||||
foreach(l2; a)
|
||||
{
|
||||
assert(l2.length == 4);
|
||||
foreach(l3; l2)
|
||||
assert(l3 == zeros[]);
|
||||
}
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=24436
|
||||
@system unittest
|
||||
{
|
||||
|
@ -12,24 +12,8 @@ module core.internal.array.utils;
|
||||
import core.internal.traits : Parameters;
|
||||
import core.memory : GC;
|
||||
|
||||
alias BlkInfo = GC.BlkInfo;
|
||||
alias BlkAttr = GC.BlkAttr;
|
||||
|
||||
private
|
||||
{
|
||||
enum : size_t
|
||||
{
|
||||
PAGESIZE = 4096,
|
||||
BIGLENGTHMASK = ~(PAGESIZE - 1),
|
||||
SMALLPAD = 1,
|
||||
MEDPAD = ushort.sizeof,
|
||||
LARGEPREFIX = 16, // 16 bytes padding at the front of the array
|
||||
LARGEPAD = LARGEPREFIX + 1,
|
||||
MAXSMALLSIZE = 256-SMALLPAD,
|
||||
MAXMEDSIZE = (PAGESIZE / 2) - MEDPAD
|
||||
}
|
||||
}
|
||||
|
||||
auto gcStatsPure() nothrow pure
|
||||
{
|
||||
import core.memory : GC;
|
||||
@ -156,55 +140,21 @@ template isPostblitNoThrow(T) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear padding that might not be zeroed by the GC (it assumes it is within the
|
||||
* requested size from the start, but it is actually at the end of the allocated
|
||||
* block).
|
||||
*
|
||||
* Params:
|
||||
* info = array allocation data
|
||||
* arrSize = size of the array in bytes
|
||||
* padSize = size of the padding in bytes
|
||||
*/
|
||||
void __arrayClearPad()(ref BlkInfo info, size_t arrSize, size_t padSize) nothrow pure
|
||||
{
|
||||
import core.stdc.string;
|
||||
if (padSize > MEDPAD && !(info.attr & BlkAttr.NO_SCAN) && info.base)
|
||||
{
|
||||
if (info.size < PAGESIZE)
|
||||
memset(info.base + arrSize, 0, padSize);
|
||||
else
|
||||
memset(info.base, 0, LARGEPREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate an array memory block by applying the proper padding and assigning
|
||||
* block attributes if not inherited from the existing block.
|
||||
* Allocate a memory block with appendable capabilities for array usage.
|
||||
*
|
||||
* Params:
|
||||
* arrSize = size of the allocated array in bytes
|
||||
* Returns:
|
||||
* `BlkInfo` with allocation metadata
|
||||
* `void[]` matching requested size on success, `null` on failure.
|
||||
*/
|
||||
BlkInfo __arrayAlloc(T)(size_t arrSize) @trusted
|
||||
void[] __arrayAlloc(T)(size_t arrSize) @trusted
|
||||
{
|
||||
import core.checkedint;
|
||||
import core.lifetime : TypeInfoSize;
|
||||
import core.internal.traits : hasIndirections;
|
||||
|
||||
enum typeInfoSize = TypeInfoSize!T;
|
||||
BlkAttr attr = BlkAttr.APPENDABLE;
|
||||
|
||||
size_t padSize = arrSize > MAXMEDSIZE ?
|
||||
LARGEPAD :
|
||||
((arrSize > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + typeInfoSize);
|
||||
|
||||
bool overflow;
|
||||
auto paddedSize = addu(arrSize, padSize, overflow);
|
||||
|
||||
if (overflow)
|
||||
return BlkInfo();
|
||||
|
||||
/* `extern(C++)` classes don't have a classinfo pointer in their vtable,
|
||||
* so the GC can't finalize them.
|
||||
*/
|
||||
@ -213,59 +163,8 @@ BlkInfo __arrayAlloc(T)(size_t arrSize) @trusted
|
||||
static if (!hasIndirections!T)
|
||||
attr |= BlkAttr.NO_SCAN;
|
||||
|
||||
auto bi = GC.qalloc(paddedSize, attr, typeid(T));
|
||||
__arrayClearPad(bi, arrSize, padSize);
|
||||
return bi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start of the array for the given block.
|
||||
*
|
||||
* Params:
|
||||
* info = array metadata
|
||||
* Returns:
|
||||
* pointer to the start of the array
|
||||
*/
|
||||
void *__arrayStart()(return scope BlkInfo info) nothrow pure
|
||||
{
|
||||
return info.base + ((info.size & BIGLENGTHMASK) ? LARGEPREFIX : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the allocated length of the array block. This is called when an array
|
||||
* is appended to or its length is set.
|
||||
*
|
||||
* The allocated block looks like this for blocks < PAGESIZE:
|
||||
* `|elem0|elem1|elem2|...|elemN-1|emptyspace|N*elemsize|`
|
||||
*
|
||||
* The size of the allocated length at the end depends on the block size:
|
||||
* a block of 16 to 256 bytes has an 8-bit length.
|
||||
* a block with 512 to pagesize/2 bytes has a 16-bit length.
|
||||
*
|
||||
* For blocks >= pagesize, the length is a size_t and is at the beginning of the
|
||||
* block. The reason we have to do this is because the block can extend into
|
||||
* more pages, so we cannot trust the block length if it sits at the end of the
|
||||
* block, because it might have just been extended. If we can prove in the
|
||||
* future that the block is unshared, we may be able to change this, but I'm not
|
||||
* sure it's important.
|
||||
*
|
||||
* In order to do put the length at the front, we have to provide 16 bytes
|
||||
* buffer space in case the block has to be aligned properly. In x86, certain
|
||||
* SSE instructions will only work if the data is 16-byte aligned. In addition,
|
||||
* we need the sentinel byte to prevent accidental pointers to the next block.
|
||||
* Because of the extra overhead, we only do this for page size and above, where
|
||||
* the overhead is minimal compared to the block size.
|
||||
*
|
||||
* So for those blocks, it looks like:
|
||||
* `|N*elemsize|padding|elem0|elem1|...|elemN-1|emptyspace|sentinelbyte|``
|
||||
*
|
||||
* where `elem0` starts 16 bytes after the first byte.
|
||||
*/
|
||||
bool __setArrayAllocLength(T)(ref BlkInfo info, size_t newLength, bool isShared, size_t oldLength = ~0)
|
||||
{
|
||||
import core.lifetime : TypeInfoSize;
|
||||
import core.internal.gc.blockmeta : __setArrayAllocLengthImpl, __setBlockFinalizerInfo;
|
||||
static if (TypeInfoSize!T)
|
||||
__setBlockFinalizerInfo(info, typeid(T));
|
||||
return __setArrayAllocLengthImpl(info, newLength, isShared, oldLength, TypeInfoSize!T);
|
||||
auto ptr = GC.malloc(arrSize, attr, typeid(T));
|
||||
if (ptr)
|
||||
return ptr[0 .. arrSize];
|
||||
return null;
|
||||
}
|
||||
|
@ -69,12 +69,11 @@ size_t structTypeInfoSize(const TypeInfo ti) pure nothrow @nogc
|
||||
|
||||
where elem0 starts 16 bytes after the first byte.
|
||||
*/
|
||||
bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, const TypeInfo tinext, size_t oldlength = ~0) pure nothrow
|
||||
bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, const TypeInfo tinext, size_t oldlength = size_t.max) pure nothrow
|
||||
{
|
||||
size_t typeInfoSize = (info.attr & BlkAttr.STRUCTFINAL) ? size_t.sizeof : 0;
|
||||
if (typeInfoSize)
|
||||
__setBlockFinalizerInfo(info, tinext);
|
||||
__setBlockFinalizerInfo(info, tinext);
|
||||
|
||||
size_t typeInfoSize = (info.attr & BlkAttr.STRUCTFINAL) ? size_t.sizeof : 0;
|
||||
return __setArrayAllocLengthImpl(info, newlength, isshared, oldlength, typeInfoSize);
|
||||
}
|
||||
|
||||
@ -97,7 +96,7 @@ bool __setArrayAllocLengthImpl(ref BlkInfo info, size_t newlength, bool isshared
|
||||
return false;
|
||||
|
||||
auto length = cast(ubyte *)(info.base + info.size - typeInfoSize - SMALLPAD);
|
||||
if (oldlength != ~0)
|
||||
if (oldlength != size_t.max)
|
||||
{
|
||||
if (isshared)
|
||||
{
|
||||
@ -123,7 +122,7 @@ bool __setArrayAllocLengthImpl(ref BlkInfo info, size_t newlength, bool isshared
|
||||
// new size does not fit inside block
|
||||
return false;
|
||||
auto length = cast(ushort *)(info.base + info.size - typeInfoSize - MEDPAD);
|
||||
if (oldlength != ~0)
|
||||
if (oldlength != size_t.max)
|
||||
{
|
||||
if (isshared)
|
||||
{
|
||||
@ -149,7 +148,7 @@ bool __setArrayAllocLengthImpl(ref BlkInfo info, size_t newlength, bool isshared
|
||||
// new size does not fit inside block
|
||||
return false;
|
||||
auto length = cast(size_t *)(info.base);
|
||||
if (oldlength != ~0)
|
||||
if (oldlength != size_t.max)
|
||||
{
|
||||
if (isshared)
|
||||
{
|
||||
@ -176,24 +175,49 @@ bool __setArrayAllocLengthImpl(ref BlkInfo info, size_t newlength, bool isshared
|
||||
The block finalizer info is set separately from the array length, as that is
|
||||
only needed on the initial setup of the block. No shared is needed, since
|
||||
this should only happen when the block is new.
|
||||
If the STRUCTFINAL bit is not set, no finalizer is stored (but if needed the
|
||||
slot is zeroed)
|
||||
*/
|
||||
void __setBlockFinalizerInfo(ref BlkInfo info, const TypeInfo ti) pure nothrow
|
||||
{
|
||||
if ((info.attr & BlkAttr.APPENDABLE) && info.size >= PAGESIZE)
|
||||
{
|
||||
// if the structfinal bit is not set, we don't have a finalizer. But we
|
||||
// should still zero out the finalizer slot.
|
||||
auto context = (info.attr & BlkAttr.STRUCTFINAL) ? cast(void*)ti : null;
|
||||
|
||||
// array used size goes at the beginning. We can stuff the typeinfo
|
||||
// right after it, as we need to use 16 bytes anyway.
|
||||
auto typeInfo = cast(TypeInfo*)(info.base + size_t.sizeof);
|
||||
*typeInfo = cast() ti;
|
||||
//
|
||||
auto typeInfo = cast(void**)info.base + 1;
|
||||
*typeInfo = context;
|
||||
version (D_LP64) {} else
|
||||
{
|
||||
// zero out the extra padding
|
||||
(cast(size_t*)info.base)[2 .. 4] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(info.attr & BlkAttr.STRUCTFINAL)
|
||||
{
|
||||
// all other cases the typeinfo gets put at the end of the block
|
||||
auto typeInfo = cast(TypeInfo*)(info.base + info.size - size_t.sizeof);
|
||||
*typeInfo = cast() ti;
|
||||
auto typeInfo = cast(void**)(info.base + info.size) - 1;
|
||||
*typeInfo = cast(void*) ti;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the finalizer info from the block (typeinfo).
|
||||
Must be called on a block with STRUCTFINAL set.
|
||||
*/
|
||||
const(TypeInfo) __getBlockFinalizerInfo(ref BlkInfo info) pure nothrow
|
||||
{
|
||||
bool isLargeArray = (info.attr & BlkAttr.APPENDABLE) && info.size >= PAGESIZE;
|
||||
auto typeInfo = isLargeArray ?
|
||||
info.base + size_t.sizeof :
|
||||
info.base + info.size - size_t.sizeof;
|
||||
return *cast(TypeInfo*)typeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
get the used size of the array for the given block
|
||||
*/
|
||||
@ -251,3 +275,34 @@ size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted
|
||||
{
|
||||
return size > MAXMEDSIZE ? LARGEPAD : ((size > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + structTypeInfoSize(tinext));
|
||||
}
|
||||
|
||||
/**
|
||||
get the padding required to allocate size bytes, use the bits to determine
|
||||
which metadata must be stored.
|
||||
*/
|
||||
size_t __allocPad(size_t size, uint bits) nothrow pure @trusted
|
||||
{
|
||||
auto finalizerSize = (bits & BlkAttr.STRUCTFINAL) ? (void*).sizeof : 0;
|
||||
if (bits & BlkAttr.APPENDABLE)
|
||||
{
|
||||
if (size > MAXMEDSIZE - finalizerSize)
|
||||
return LARGEPAD;
|
||||
auto pad = (size > MAXSMALLSIZE - finalizerSize) ? MEDPAD : SMALLPAD;
|
||||
return pad + finalizerSize;
|
||||
}
|
||||
|
||||
return finalizerSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start of the array for the given block.
|
||||
*
|
||||
* Params:
|
||||
* info = array metadata
|
||||
* Returns:
|
||||
* pointer to the start of the array
|
||||
*/
|
||||
void *__arrayStart()(return scope BlkInfo info) nothrow pure
|
||||
{
|
||||
return info.base + ((info.size & BIGLENGTHMASK) ? LARGEPREFIX : 0);
|
||||
}
|
||||
|
@ -475,23 +475,39 @@ class ConservativeGC : GC
|
||||
*/
|
||||
void *malloc(size_t size, uint bits = 0, const TypeInfo ti = null) nothrow
|
||||
{
|
||||
if (!size)
|
||||
import core.internal.gc.blockmeta;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
adjustAttrs(bits, ti);
|
||||
|
||||
immutable padding = __allocPad(size, bits);
|
||||
|
||||
bool overflow;
|
||||
import core.checkedint : addu;
|
||||
immutable needed = addu(size, padding, overflow);
|
||||
if (overflow)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
size_t localAllocSize = void;
|
||||
|
||||
auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, localAllocSize, ti);
|
||||
auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(needed, bits, localAllocSize, ti);
|
||||
|
||||
invalidate(p[0 .. localAllocSize], 0xF0, true);
|
||||
|
||||
auto ret = setupMetadata(p[0 .. localAllocSize], bits, padding, size, ti);
|
||||
|
||||
if (!(bits & BlkAttr.NO_SCAN))
|
||||
{
|
||||
memset(p + size, 0, localAllocSize - size);
|
||||
memset(ret.ptr + size, 0, ret.length - size);
|
||||
}
|
||||
|
||||
return p;
|
||||
return ret.ptr;
|
||||
}
|
||||
|
||||
|
||||
@ -527,6 +543,8 @@ class ConservativeGC : GC
|
||||
|
||||
BlkInfo qalloc( size_t size, uint bits, const scope TypeInfo ti) nothrow
|
||||
{
|
||||
// qalloc should not be used for building metadata-containing blocks,
|
||||
// so avoid all the checking for bits and array padding.
|
||||
|
||||
if (!size)
|
||||
{
|
||||
@ -564,25 +582,45 @@ class ConservativeGC : GC
|
||||
*/
|
||||
void *calloc(size_t size, uint bits = 0, const TypeInfo ti = null) nothrow
|
||||
{
|
||||
import core.internal.gc.blockmeta;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
size_t localAllocSize = void;
|
||||
adjustAttrs(bits, ti);
|
||||
|
||||
auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, localAllocSize, ti);
|
||||
|
||||
debug (VALGRIND) makeMemUndefined(p[0..size]);
|
||||
invalidate((p + size)[0 .. localAllocSize - size], 0xF0, true);
|
||||
|
||||
memset(p, 0, size);
|
||||
if (!(bits & BlkAttr.NO_SCAN))
|
||||
immutable padding = __allocPad(size, bits);
|
||||
bool overflow;
|
||||
import core.checkedint : addu;
|
||||
immutable needed = addu(size, padding, overflow);
|
||||
if (overflow)
|
||||
{
|
||||
memset(p + size, 0, localAllocSize - size);
|
||||
return null;
|
||||
}
|
||||
|
||||
return p;
|
||||
|
||||
size_t localAllocSize = void;
|
||||
|
||||
auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(needed, bits, localAllocSize, ti);
|
||||
|
||||
debug (VALGRIND) makeMemUndefined(p[0..size]);
|
||||
|
||||
auto ret = setupMetadata(p[0 .. localAllocSize], bits, padding, size, ti);
|
||||
|
||||
invalidate((ret.ptr + size)[0 .. ret.length - size], 0xF0, true);
|
||||
|
||||
if (bits & BlkAttr.NO_SCAN)
|
||||
{
|
||||
memset(ret.ptr, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(ret.ptr, 0, ret.length);
|
||||
}
|
||||
|
||||
return ret.ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -595,7 +633,8 @@ class ConservativeGC : GC
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* size = The desired allocation size in bytes.
|
||||
* bits = A bitmask of the attributes to set on this block.
|
||||
* bits = A bitmask of the attributes to set on this block. APPENDABLE and
|
||||
* FINALIZE are not allowed for realloc.
|
||||
* ti = TypeInfo to describe the memory.
|
||||
*
|
||||
* Returns:
|
||||
@ -607,14 +646,28 @@ class ConservativeGC : GC
|
||||
*/
|
||||
void *realloc(void *p, size_t size, uint bits = 0, const TypeInfo ti = null) nothrow
|
||||
{
|
||||
if (bits & (BlkAttr.APPENDABLE | BlkAttr.FINALIZE))
|
||||
// these bits are not allowed. We can't properly manage
|
||||
// reallocation of such blocks.
|
||||
onInvalidMemoryOperationError();
|
||||
|
||||
size_t localAllocSize = void;
|
||||
auto oldp = p;
|
||||
|
||||
p = runLocked!(reallocNoSync, mallocTime, numMallocs)(p, size, bits, localAllocSize, ti);
|
||||
|
||||
if (p && !(bits & BlkAttr.NO_SCAN))
|
||||
if (p)
|
||||
{
|
||||
memset(p + size, 0, localAllocSize - size);
|
||||
// invalidate any block info cache we have for the old allocation.
|
||||
import core.internal.gc.blkcache;
|
||||
if (auto bic = __getBlkInfo(oldp)) {
|
||||
*bic = BlkInfo.init;
|
||||
}
|
||||
|
||||
if (!(bits & BlkAttr.NO_SCAN))
|
||||
{
|
||||
memset(p + size, 0, localAllocSize - size);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -662,7 +715,8 @@ class ConservativeGC : GC
|
||||
void* doMalloc()
|
||||
{
|
||||
if (!bits)
|
||||
bits = pool.getBits(biti);
|
||||
bits = pool.getBits(biti) &
|
||||
~(BlkAttr.APPENDABLE | BlkAttr.FINALIZE | BlkAttr.STRUCTFINAL);
|
||||
|
||||
void* p2 = mallocNoSync(size, bits, alloc_size, ti);
|
||||
debug (SENTINEL)
|
||||
@ -759,7 +813,16 @@ class ConservativeGC : GC
|
||||
|
||||
size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow
|
||||
{
|
||||
return runLocked!(extendNoSync, extendTime, numExtends)(p, minsize, maxsize, ti);
|
||||
auto result = runLocked!(extendNoSync, extendTime, numExtends)(p, minsize, maxsize, ti);
|
||||
if (result != 0) {
|
||||
// invalidate any block info cache we have for the old allocation.
|
||||
import core.internal.gc.blkcache;
|
||||
if (auto bic = __getBlkInfo(p)) {
|
||||
*bic = BlkInfo.init;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -867,14 +930,22 @@ class ConservativeGC : GC
|
||||
return;
|
||||
}
|
||||
|
||||
return runLocked!(freeNoSync, freeTime, numFrees)(p);
|
||||
auto didFree = runLocked!(freeNoSync, freeTime, numFrees)(p);
|
||||
|
||||
if (didFree) {
|
||||
// invalidate any block info cache we have for the old allocation.
|
||||
import core.internal.gc.blkcache;
|
||||
if (auto bic = __getBlkInfo(p)) {
|
||||
*bic = BlkInfo.init;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implementation of free.
|
||||
//
|
||||
private void freeNoSync(void *p) nothrow @nogc
|
||||
private bool freeNoSync(void *p) nothrow @nogc
|
||||
{
|
||||
debug(PRINTF) printf("Freeing %#zx\n", cast(size_t) p);
|
||||
assert (p);
|
||||
@ -887,7 +958,7 @@ class ConservativeGC : GC
|
||||
// Find which page it is in
|
||||
pool = gcx.findPool(p);
|
||||
if (!pool) // if not one of ours
|
||||
return; // ignore
|
||||
return false; // ignore
|
||||
|
||||
pagenum = pool.pagenumOf(p);
|
||||
|
||||
@ -899,11 +970,11 @@ class ConservativeGC : GC
|
||||
// Verify that the pointer is at the beginning of a block,
|
||||
// no action should be taken if p is an interior pointer
|
||||
if (bin > Bins.B_PAGE) // B_PAGEPLUS or B_FREE
|
||||
return;
|
||||
return false;
|
||||
size_t off = (sentinel_sub(p) - pool.baseAddr);
|
||||
size_t base = baseOffset(off, bin);
|
||||
if (off != base)
|
||||
return;
|
||||
return false;
|
||||
|
||||
sentinel_Invariant(p);
|
||||
auto q = p;
|
||||
@ -928,7 +999,7 @@ class ConservativeGC : GC
|
||||
{
|
||||
biti = cast(size_t)(p - pool.baseAddr) >> pool.ShiftBy.Small;
|
||||
if (pool.freebits.test (biti))
|
||||
return;
|
||||
return false;
|
||||
// Add to free list
|
||||
List *list = cast(List*)p;
|
||||
|
||||
@ -948,6 +1019,8 @@ class ConservativeGC : GC
|
||||
pool.clrBits(biti, ~BlkAttr.NONE);
|
||||
|
||||
gcx.leakDetector.log_free(sentinel_add(p), ssize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -5325,3 +5398,42 @@ void undefinedWrite(T)(ref T var, T value) nothrow
|
||||
else
|
||||
var = value;
|
||||
}
|
||||
|
||||
private void adjustAttrs(ref uint attrs, const TypeInfo ti) nothrow
|
||||
{
|
||||
bool hasContext = ti !is null;
|
||||
if((attrs & BlkAttr.FINALIZE) && hasContext && typeid(ti) is typeid(TypeInfo_Struct))
|
||||
attrs |= BlkAttr.STRUCTFINAL;
|
||||
else
|
||||
// STRUCTFINAL now just means "has a context pointer added to the block"
|
||||
attrs &= ~BlkAttr.STRUCTFINAL;
|
||||
}
|
||||
|
||||
// sets up the array/context pointer metadata based on the block allocated.
|
||||
// This is called on any block *creation*, and not on updating the array
|
||||
// metadata.
|
||||
//
|
||||
// The return value is the true data that the user can use.
|
||||
private void[] setupMetadata(void[] block, uint bits, size_t padding, size_t used, const TypeInfo ti) nothrow
|
||||
{
|
||||
import core.internal.gc.blockmeta;
|
||||
import core.internal.array.utils;
|
||||
|
||||
BlkInfo info = BlkInfo(
|
||||
base: block.ptr,
|
||||
attr: bits,
|
||||
size: block.length
|
||||
);
|
||||
|
||||
|
||||
__setBlockFinalizerInfo(info, ti);
|
||||
|
||||
if (bits & BlkAttr.APPENDABLE) {
|
||||
auto typeInfoSize = (bits & BlkAttr.STRUCTFINAL) ? (void*).sizeof : 0;
|
||||
auto success = __setArrayAllocLengthImpl(info, used, false, size_t.max, typeInfoSize);
|
||||
assert(success);
|
||||
return __arrayStart(info)[0 .. block.length - padding];
|
||||
}
|
||||
|
||||
return block.ptr[0 .. block.length - padding];
|
||||
}
|
||||
|
@ -2348,7 +2348,7 @@ pure nothrow @nogc @system unittest
|
||||
|
||||
debug(PRINTF)
|
||||
{
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.stdio : printf;
|
||||
}
|
||||
|
||||
/// Implementation of `_d_delstruct` and `_d_delstructTrace`
|
||||
|
@ -1167,7 +1167,7 @@ extern (C) private @system @nogc nothrow
|
||||
{
|
||||
ref int fakePureErrnoImpl()
|
||||
{
|
||||
import core.stdc.errno;
|
||||
import core.stdc.errno : errno;
|
||||
return errno();
|
||||
}
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ extern (C) UnitTestResult runModuleUnitTests()
|
||||
if (moduleName.length && e.file.length > moduleName.length
|
||||
&& e.file[0 .. moduleName.length] == moduleName)
|
||||
{
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.stdio : printf;
|
||||
printf("%.*s(%llu): [unittest] %.*s\n",
|
||||
cast(int) e.file.length, e.file.ptr, cast(ulong) e.line,
|
||||
cast(int) e.message.length, e.message.ptr);
|
||||
@ -798,7 +798,7 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null ) // @nogc
|
||||
unittest
|
||||
{
|
||||
import core.runtime;
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.stdio : printf;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ version (Windows)
|
||||
}
|
||||
else version (Posix)
|
||||
{
|
||||
import core.stdc.errno;
|
||||
import core.stdc.errno : EAGAIN, ETIMEDOUT;
|
||||
import core.sync.config;
|
||||
import core.sys.posix.pthread : pthread_cond_broadcast, pthread_cond_destroy, pthread_cond_init,
|
||||
pthread_cond_signal, pthread_cond_t, pthread_cond_timedwait, pthread_cond_wait;
|
||||
|
@ -37,7 +37,7 @@ version (Windows)
|
||||
}
|
||||
else version (Darwin)
|
||||
{
|
||||
import core.stdc.errno;
|
||||
import core.stdc.errno : EINTR, errno;
|
||||
import core.sync.config;
|
||||
import core.sys.darwin.mach.kern_return : KERN_ABORTED, KERN_OPERATION_TIMED_OUT;
|
||||
import core.sys.darwin.mach.semaphore : mach_task_self, mach_timespec_t, semaphore_create, semaphore_destroy,
|
||||
@ -45,7 +45,7 @@ else version (Darwin)
|
||||
}
|
||||
else version (Posix)
|
||||
{
|
||||
import core.stdc.errno;
|
||||
import core.stdc.errno : EAGAIN, EINTR, errno, ETIMEDOUT;
|
||||
import core.sync.config;
|
||||
import core.sys.posix.semaphore : sem_destroy, sem_init, sem_post, sem_t, sem_timedwait, sem_trywait, sem_wait;
|
||||
import core.sys.posix.time : clock_gettime, CLOCK_REALTIME, timespec;
|
||||
|
@ -516,8 +516,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 0U) & 1U));
|
||||
}
|
||||
|
||||
enum ulong disabled_min = cast(ulong) 0U;
|
||||
enum ulong disabled_max = cast(ulong) 1U;
|
||||
enum ulong disabled_min = 0UL;
|
||||
enum ulong disabled_max = 1UL;
|
||||
///
|
||||
@property ulong inherit() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -536,8 +536,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 1U) & 2U));
|
||||
}
|
||||
|
||||
enum ulong inherit_min = cast(ulong) 0U;
|
||||
enum ulong inherit_max = cast(ulong) 1U;
|
||||
enum ulong inherit_min = 0UL;
|
||||
enum ulong inherit_max = 1UL;
|
||||
///
|
||||
@property ulong pinned() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -556,8 +556,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 2U) & 4U));
|
||||
}
|
||||
|
||||
enum ulong pinned_min = cast(ulong) 0U;
|
||||
enum ulong pinned_max = cast(ulong) 1U;
|
||||
enum ulong pinned_min = 0UL;
|
||||
enum ulong pinned_max = 1UL;
|
||||
///
|
||||
@property ulong exclusive() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -576,8 +576,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 3U) & 8U));
|
||||
}
|
||||
|
||||
enum ulong exclusive_min = cast(ulong) 0U;
|
||||
enum ulong exclusive_max = cast(ulong) 1U;
|
||||
enum ulong exclusive_min = 0UL;
|
||||
enum ulong exclusive_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_user() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -596,8 +596,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 4U) & 16U));
|
||||
}
|
||||
|
||||
enum ulong exclude_user_min = cast(ulong) 0U;
|
||||
enum ulong exclude_user_max = cast(ulong) 1U;
|
||||
enum ulong exclude_user_min = 0UL;
|
||||
enum ulong exclude_user_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_kernel() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -616,8 +616,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 5U) & 32U));
|
||||
}
|
||||
|
||||
enum ulong exclude_kernel_min = cast(ulong) 0U;
|
||||
enum ulong exclude_kernel_max = cast(ulong) 1U;
|
||||
enum ulong exclude_kernel_min = 0UL;
|
||||
enum ulong exclude_kernel_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_hv() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -636,8 +636,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 6U) & 64U));
|
||||
}
|
||||
|
||||
enum ulong exclude_hv_min = cast(ulong) 0U;
|
||||
enum ulong exclude_hv_max = cast(ulong) 1U;
|
||||
enum ulong exclude_hv_min = 0UL;
|
||||
enum ulong exclude_hv_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_idle() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -656,8 +656,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 7U) & 128U));
|
||||
}
|
||||
|
||||
enum ulong exclude_idle_min = cast(ulong) 0U;
|
||||
enum ulong exclude_idle_max = cast(ulong) 1U;
|
||||
enum ulong exclude_idle_min = 0UL;
|
||||
enum ulong exclude_idle_max = 1UL;
|
||||
///
|
||||
@property ulong mmap() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -674,8 +674,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 8U) & 256U));
|
||||
}
|
||||
|
||||
enum ulong mmap_min = cast(ulong) 0U;
|
||||
enum ulong mmap_max = cast(ulong) 1U;
|
||||
enum ulong mmap_min = 0UL;
|
||||
enum ulong mmap_max = 1UL;
|
||||
///
|
||||
@property ulong comm() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -692,8 +692,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 9U) & 512U));
|
||||
}
|
||||
|
||||
enum ulong comm_min = cast(ulong) 0U;
|
||||
enum ulong comm_max = cast(ulong) 1U;
|
||||
enum ulong comm_min = 0UL;
|
||||
enum ulong comm_max = 1UL;
|
||||
///
|
||||
@property ulong freq() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -710,8 +710,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 10U) & 1024U));
|
||||
}
|
||||
|
||||
enum ulong freq_min = cast(ulong) 0U;
|
||||
enum ulong freq_max = cast(ulong) 1U;
|
||||
enum ulong freq_min = 0UL;
|
||||
enum ulong freq_max = 1UL;
|
||||
///
|
||||
@property ulong inherit_stat() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -730,8 +730,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 11U) & 2048U));
|
||||
}
|
||||
|
||||
enum ulong inherit_stat_min = cast(ulong) 0U;
|
||||
enum ulong inherit_stat_max = cast(ulong) 1U;
|
||||
enum ulong inherit_stat_min = 0UL;
|
||||
enum ulong inherit_stat_max = 1UL;
|
||||
///
|
||||
@property ulong enable_on_exec() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -750,8 +750,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 12U) & 4096U));
|
||||
}
|
||||
|
||||
enum ulong enable_on_exec_min = cast(ulong) 0U;
|
||||
enum ulong enable_on_exec_max = cast(ulong) 1U;
|
||||
enum ulong enable_on_exec_min = 0UL;
|
||||
enum ulong enable_on_exec_max = 1UL;
|
||||
///
|
||||
@property ulong task() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -768,8 +768,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 13U) & 8192U));
|
||||
}
|
||||
|
||||
enum ulong task_min = cast(ulong) 0U;
|
||||
enum ulong task_max = cast(ulong) 1U;
|
||||
enum ulong task_min = 0UL;
|
||||
enum ulong task_max = 1UL;
|
||||
///
|
||||
@property ulong watermark() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -788,8 +788,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 14U) & 16384U));
|
||||
}
|
||||
|
||||
enum ulong watermark_min = cast(ulong) 0U;
|
||||
enum ulong watermark_max = cast(ulong) 1U;
|
||||
enum ulong watermark_min = 0UL;
|
||||
enum ulong watermark_max = 1UL;
|
||||
///
|
||||
@property ulong precise_ip() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -808,8 +808,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 15U) & 98304U));
|
||||
}
|
||||
|
||||
enum ulong precise_ip_min = cast(ulong) 0U;
|
||||
enum ulong precise_ip_max = cast(ulong) 3U;
|
||||
enum ulong precise_ip_min = 0UL;
|
||||
enum ulong precise_ip_max = 3UL;
|
||||
///
|
||||
@property ulong mmap_data() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -828,8 +828,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 17U) & 131072U));
|
||||
}
|
||||
|
||||
enum ulong mmap_data_min = cast(ulong) 0U;
|
||||
enum ulong mmap_data_max = cast(ulong) 1U;
|
||||
enum ulong mmap_data_min = 0UL;
|
||||
enum ulong mmap_data_max = 1UL;
|
||||
///
|
||||
@property ulong sample_id_all() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -848,8 +848,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 18U) & 262144U));
|
||||
}
|
||||
|
||||
enum ulong sample_id_all_min = cast(ulong) 0U;
|
||||
enum ulong sample_id_all_max = cast(ulong) 1U;
|
||||
enum ulong sample_id_all_min = 0UL;
|
||||
enum ulong sample_id_all_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_host() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -868,8 +868,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 19U) & 524288U));
|
||||
}
|
||||
|
||||
enum ulong exclude_host_min = cast(ulong) 0U;
|
||||
enum ulong exclude_host_max = cast(ulong) 1U;
|
||||
enum ulong exclude_host_min = 0UL;
|
||||
enum ulong exclude_host_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_guest() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -888,8 +888,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 20U) & 1048576U));
|
||||
}
|
||||
|
||||
enum ulong exclude_guest_min = cast(ulong) 0U;
|
||||
enum ulong exclude_guest_max = cast(ulong) 1U;
|
||||
enum ulong exclude_guest_min = 0UL;
|
||||
enum ulong exclude_guest_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_callchain_kernel() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -908,8 +908,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 21U) & 2097152U));
|
||||
}
|
||||
|
||||
enum ulong exclude_callchain_kernel_min = cast(ulong) 0U;
|
||||
enum ulong exclude_callchain_kernel_max = cast(ulong) 1U;
|
||||
enum ulong exclude_callchain_kernel_min = 0UL;
|
||||
enum ulong exclude_callchain_kernel_max = 1UL;
|
||||
///
|
||||
@property ulong exclude_callchain_user() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -928,8 +928,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 22U) & 4194304U));
|
||||
}
|
||||
|
||||
enum ulong exclude_callchain_user_min = cast(ulong) 0U;
|
||||
enum ulong exclude_callchain_user_max = cast(ulong) 1U;
|
||||
enum ulong exclude_callchain_user_min = 0UL;
|
||||
enum ulong exclude_callchain_user_max = 1UL;
|
||||
///
|
||||
@property ulong mmap2() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -948,8 +948,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 23U) & 8388608U));
|
||||
}
|
||||
|
||||
enum ulong mmap2_min = cast(ulong) 0U;
|
||||
enum ulong mmap2_max = cast(ulong) 1U;
|
||||
enum ulong mmap2_min = 0UL;
|
||||
enum ulong mmap2_max = 1UL;
|
||||
///
|
||||
@property ulong comm_exec() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -968,8 +968,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 24U) & 16777216U));
|
||||
}
|
||||
|
||||
enum ulong comm_exec_min = cast(ulong) 0U;
|
||||
enum ulong comm_exec_max = cast(ulong) 1U;
|
||||
enum ulong comm_exec_min = 0UL;
|
||||
enum ulong comm_exec_max = 1UL;
|
||||
///
|
||||
@property ulong use_clockid() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -988,8 +988,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 25U) & 33554432U));
|
||||
}
|
||||
|
||||
enum ulong use_clockid_min = cast(ulong) 0U;
|
||||
enum ulong use_clockid_max = cast(ulong) 1U;
|
||||
enum ulong use_clockid_min = 0UL;
|
||||
enum ulong use_clockid_max = 1UL;
|
||||
///
|
||||
@property ulong context_switch() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1008,8 +1008,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 26U) & 67108864U));
|
||||
}
|
||||
|
||||
enum ulong context_switch_min = cast(ulong) 0U;
|
||||
enum ulong context_switch_max = cast(ulong) 1U;
|
||||
enum ulong context_switch_min = 0UL;
|
||||
enum ulong context_switch_max = 1UL;
|
||||
///
|
||||
@property ulong write_backward() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1028,8 +1028,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 27U) & 134217728U));
|
||||
}
|
||||
|
||||
enum ulong write_backward_min = cast(ulong) 0U;
|
||||
enum ulong write_backward_max = cast(ulong) 1U;
|
||||
enum ulong write_backward_min = 0UL;
|
||||
enum ulong write_backward_max = 1UL;
|
||||
///
|
||||
@property ulong namespaces() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1048,8 +1048,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 28U) & 268435456U));
|
||||
}
|
||||
|
||||
enum ulong namespaces_min = cast(ulong) 0U;
|
||||
enum ulong namespaces_max = cast(ulong) 1U;
|
||||
enum ulong namespaces_min = 0UL;
|
||||
enum ulong namespaces_max = 1UL;
|
||||
///
|
||||
@property ulong __reserved_1() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1069,8 +1069,8 @@ struct perf_event_attr
|
||||
(cast(typeof(perf_event_attr_bitmanip)) v << 29U) & 18446744073172680704UL));
|
||||
}
|
||||
|
||||
enum ulong __reserved_1_min = cast(ulong) 0U;
|
||||
enum ulong __reserved_1_max = cast(ulong) 34359738367UL;
|
||||
enum ulong __reserved_1_min = 0UL;
|
||||
enum ulong __reserved_1_max = 34359738367UL;
|
||||
///
|
||||
union
|
||||
{
|
||||
@ -1242,8 +1242,8 @@ struct perf_event_mmap_page
|
||||
(cast(typeof(mmap_page_bitmanip)) v << 0U) & 1U));
|
||||
}
|
||||
|
||||
enum ulong cap_bit0_min = cast(ulong) 0U;
|
||||
enum ulong cap_bit0_max = cast(ulong) 1U;
|
||||
enum ulong cap_bit0_min = 0UL;
|
||||
enum ulong cap_bit0_max = 1UL;
|
||||
///
|
||||
@property ulong cap_bit0_is_deprecated() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1262,8 +1262,8 @@ struct perf_event_mmap_page
|
||||
(cast(typeof(mmap_page_bitmanip)) v << 1U) & 2U));
|
||||
}
|
||||
|
||||
enum ulong cap_bit0_is_deprecated_min = cast(ulong) 0U;
|
||||
enum ulong cap_bit0_is_deprecated_max = cast(ulong) 1U;
|
||||
enum ulong cap_bit0_is_deprecated_min = 0UL;
|
||||
enum ulong cap_bit0_is_deprecated_max = 1UL;
|
||||
///
|
||||
@property ulong cap_user_rdpmc() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1282,8 +1282,8 @@ struct perf_event_mmap_page
|
||||
(cast(typeof(mmap_page_bitmanip)) v << 2U) & 4U));
|
||||
}
|
||||
|
||||
enum ulong cap_user_rdpmc_min = cast(ulong) 0U;
|
||||
enum ulong cap_user_rdpmc_max = cast(ulong) 1U;
|
||||
enum ulong cap_user_rdpmc_min = 0UL;
|
||||
enum ulong cap_user_rdpmc_max = 1UL;
|
||||
///
|
||||
@property ulong cap_user_time() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1302,8 +1302,8 @@ struct perf_event_mmap_page
|
||||
(cast(typeof(mmap_page_bitmanip)) v << 3U) & 8U));
|
||||
}
|
||||
|
||||
enum ulong cap_user_time_min = cast(ulong) 0U;
|
||||
enum ulong cap_user_time_max = cast(ulong) 1U;
|
||||
enum ulong cap_user_time_min = 0UL;
|
||||
enum ulong cap_user_time_max = 1UL;
|
||||
///
|
||||
@property ulong cap_user_time_zero() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1322,8 +1322,8 @@ struct perf_event_mmap_page
|
||||
(cast(typeof(mmap_page_bitmanip)) v << 4U) & 16U));
|
||||
}
|
||||
|
||||
enum ulong cap_user_time_zero_min = cast(ulong) 0U;
|
||||
enum ulong cap_user_time_zero_max = cast(ulong) 1U;
|
||||
enum ulong cap_user_time_zero_min = 0UL;
|
||||
enum ulong cap_user_time_zero_max = 1UL;
|
||||
///
|
||||
@property ulong cap_____res() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1342,8 +1342,8 @@ struct perf_event_mmap_page
|
||||
(cast(typeof(mmap_page_bitmanip)) v << 5U) & 18446744073709551584UL));
|
||||
}
|
||||
|
||||
enum ulong cap_____res_min = cast(ulong) 0U;
|
||||
enum ulong cap_____res_max = cast(ulong) 576460752303423487UL;
|
||||
enum ulong cap_____res_min = 0UL;
|
||||
enum ulong cap_____res_max = 576460752303423487UL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1891,8 +1891,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 0U) & 31U));
|
||||
}
|
||||
|
||||
enum ulong mem_op_min = cast(ulong) 0U;
|
||||
enum ulong mem_op_max = cast(ulong) 31U;
|
||||
enum ulong mem_op_min = 0UL;
|
||||
enum ulong mem_op_max = 31UL;
|
||||
///
|
||||
@property ulong mem_lvl() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1912,8 +1912,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 5U) & 524256U));
|
||||
}
|
||||
|
||||
enum ulong mem_lvl_min = cast(ulong) 0U;
|
||||
enum ulong mem_lvl_max = cast(ulong) 16383U;
|
||||
enum ulong mem_lvl_min = 0UL;
|
||||
enum ulong mem_lvl_max = 16383UL;
|
||||
///
|
||||
@property ulong mem_snoop() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1933,8 +1933,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 19U) & 16252928U));
|
||||
}
|
||||
|
||||
enum ulong mem_snoop_min = cast(ulong) 0U;
|
||||
enum ulong mem_snoop_max = cast(ulong) 31U;
|
||||
enum ulong mem_snoop_min = 0UL;
|
||||
enum ulong mem_snoop_max = 31UL;
|
||||
///
|
||||
@property ulong mem_lock() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1954,8 +1954,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 24U) & 50331648U));
|
||||
}
|
||||
|
||||
enum ulong mem_lock_min = cast(ulong) 0U;
|
||||
enum ulong mem_lock_max = cast(ulong) 3U;
|
||||
enum ulong mem_lock_min = 0UL;
|
||||
enum ulong mem_lock_max = 3UL;
|
||||
///
|
||||
@property ulong mem_dtlb() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1975,8 +1975,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 26U) & 8522825728UL));
|
||||
}
|
||||
|
||||
enum ulong mem_dtlb_min = cast(ulong) 0U;
|
||||
enum ulong mem_dtlb_max = cast(ulong) 127U;
|
||||
enum ulong mem_dtlb_min = 0UL;
|
||||
enum ulong mem_dtlb_max = 127UL;
|
||||
///
|
||||
@property ulong mem_lvl_num() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -1996,8 +1996,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 33U) & 128849018880UL));
|
||||
}
|
||||
|
||||
enum ulong mem_lvl_num_min = cast(ulong) 0U;
|
||||
enum ulong mem_lvl_num_max = cast(ulong) 15U;
|
||||
enum ulong mem_lvl_num_min = 0UL;
|
||||
enum ulong mem_lvl_num_max = 15UL;
|
||||
///
|
||||
@property ulong mem_remote() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2017,8 +2017,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 37U) & 137438953472UL));
|
||||
}
|
||||
|
||||
enum ulong mem_remote_min = cast(ulong) 0U;
|
||||
enum ulong mem_remote_max = cast(ulong) 1U;
|
||||
enum ulong mem_remote_min = 0UL;
|
||||
enum ulong mem_remote_max = 1UL;
|
||||
///
|
||||
@property ulong mem_snoopx() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2038,8 +2038,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 38U) & 824633720832UL));
|
||||
}
|
||||
|
||||
enum ulong mem_snoopx_min = cast(ulong) 0U;
|
||||
enum ulong mem_snoopx_max = cast(ulong) 3U;
|
||||
enum ulong mem_snoopx_min = 0UL;
|
||||
enum ulong mem_snoopx_max = 3UL;
|
||||
///
|
||||
@property ulong mem_rsvd() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2060,8 +2060,8 @@ version (LittleEndian)
|
||||
(cast(typeof(perf_mem_data_src_bitmanip)) v << 40U) & 18446742974197923840UL));
|
||||
}
|
||||
|
||||
enum ulong mem_rsvd_min = cast(ulong) 0U;
|
||||
enum ulong mem_rsvd_max = cast(ulong) 16777215U;
|
||||
enum ulong mem_rsvd_min = 0UL;
|
||||
enum ulong mem_rsvd_max = 16777215UL;
|
||||
|
||||
}
|
||||
}
|
||||
@ -2099,8 +2099,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 0U) & 16777215U));
|
||||
}
|
||||
|
||||
enum ulong mem_rsvd_min = cast(ulong) 0U;
|
||||
enum ulong mem_rsvd_max = cast(ulong) 16777215U;
|
||||
enum ulong mem_rsvd_min = 0UL;
|
||||
enum ulong mem_rsvd_max = 16777215UL;
|
||||
///
|
||||
@property ulong mem_snoopx() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2119,8 +2119,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 24U) & 50331648U));
|
||||
}
|
||||
|
||||
enum ulong mem_snoopx_min = cast(ulong) 0U;
|
||||
enum ulong mem_snoopx_max = cast(ulong) 3U;
|
||||
enum ulong mem_snoopx_min = 0UL;
|
||||
enum ulong mem_snoopx_max = 3UL;
|
||||
///
|
||||
@property ulong mem_remote() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2139,8 +2139,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 26U) & 67108864U));
|
||||
}
|
||||
|
||||
enum ulong mem_remote_min = cast(ulong) 0U;
|
||||
enum ulong mem_remote_max = cast(ulong) 1U;
|
||||
enum ulong mem_remote_min = 0UL;
|
||||
enum ulong mem_remote_max = 1UL;
|
||||
///
|
||||
@property ulong mem_lvl_num() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2159,8 +2159,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 27U) & 2013265920U));
|
||||
}
|
||||
|
||||
enum ulong mem_lvl_num_min = cast(ulong) 0U;
|
||||
enum ulong mem_lvl_num_max = cast(ulong) 15U;
|
||||
enum ulong mem_lvl_num_min = 0UL;
|
||||
enum ulong mem_lvl_num_max = 15UL;
|
||||
///
|
||||
@property ulong mem_dtlb() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2179,8 +2179,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 31U) & 272730423296UL));
|
||||
}
|
||||
|
||||
enum ulong mem_dtlb_min = cast(ulong) 0U;
|
||||
enum ulong mem_dtlb_max = cast(ulong) 127U;
|
||||
enum ulong mem_dtlb_min = 0UL;
|
||||
enum ulong mem_dtlb_max = 127UL;
|
||||
///
|
||||
@property ulong mem_lock() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2199,8 +2199,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 38U) & 824633720832UL));
|
||||
}
|
||||
|
||||
enum ulong mem_lock_min = cast(ulong) 0U;
|
||||
enum ulong mem_lock_max = cast(ulong) 3U;
|
||||
enum ulong mem_lock_min = 0UL;
|
||||
enum ulong mem_lock_max = 3UL;
|
||||
///
|
||||
@property ulong mem_snoop() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2219,8 +2219,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 40U) & 34084860461056UL));
|
||||
}
|
||||
|
||||
enum ulong mem_snoop_min = cast(ulong) 0U;
|
||||
enum ulong mem_snoop_max = cast(ulong) 31U;
|
||||
enum ulong mem_snoop_min = 0UL;
|
||||
enum ulong mem_snoop_max = 31UL;
|
||||
///
|
||||
@property ulong mem_lvl() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2239,8 +2239,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 45U) & 576425567931334656UL));
|
||||
}
|
||||
|
||||
enum ulong mem_lvl_min = cast(ulong) 0U;
|
||||
enum ulong mem_lvl_max = cast(ulong) 16383U;
|
||||
enum ulong mem_lvl_min = 0UL;
|
||||
enum ulong mem_lvl_max = 16383UL;
|
||||
///
|
||||
@property ulong mem_op() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2259,8 +2259,8 @@ else
|
||||
(cast(typeof(perf_mem_data_src)) v << 59U) & 17870283321406128128UL));
|
||||
}
|
||||
|
||||
enum ulong mem_op_min = cast(ulong) 0U;
|
||||
enum ulong mem_op_max = cast(ulong) 31U;
|
||||
enum ulong mem_op_min = 0UL;
|
||||
enum ulong mem_op_max = 31UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2392,8 +2392,8 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 0U) & 1U));
|
||||
}
|
||||
|
||||
enum ulong mispred_min = cast(ulong) 0U;
|
||||
enum ulong mispred_max = cast(ulong) 1U;
|
||||
enum ulong mispred_min = 0UL;
|
||||
enum ulong mispred_max = 1UL;
|
||||
///
|
||||
@property ulong predicted() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2412,8 +2412,8 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 1U) & 2U));
|
||||
}
|
||||
|
||||
enum ulong predicted_min = cast(ulong) 0U;
|
||||
enum ulong predicted_max = cast(ulong) 1U;
|
||||
enum ulong predicted_min = 0UL;
|
||||
enum ulong predicted_max = 1UL;
|
||||
///
|
||||
@property ulong in_tx() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2432,8 +2432,8 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 2U) & 4U));
|
||||
}
|
||||
|
||||
enum ulong in_tx_min = cast(ulong) 0U;
|
||||
enum ulong in_tx_max = cast(ulong) 1U;
|
||||
enum ulong in_tx_min = 0UL;
|
||||
enum ulong in_tx_max = 1UL;
|
||||
///
|
||||
@property ulong abort() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2452,8 +2452,8 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 3U) & 8U));
|
||||
}
|
||||
|
||||
enum ulong abort_min = cast(ulong) 0U;
|
||||
enum ulong abort_max = cast(ulong) 1U;
|
||||
enum ulong abort_min = 0UL;
|
||||
enum ulong abort_max = 1UL;
|
||||
///
|
||||
@property ulong cycles() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2472,8 +2472,8 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 4U) & 1048560U));
|
||||
}
|
||||
|
||||
enum ulong cycles_min = cast(ulong) 0U;
|
||||
enum ulong cycles_max = cast(ulong) 65535U;
|
||||
enum ulong cycles_min = 0UL;
|
||||
enum ulong cycles_max = 65535UL;
|
||||
///
|
||||
@property ulong type() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2490,8 +2490,8 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 20U) & 15728640U));
|
||||
}
|
||||
|
||||
enum ulong type_min = cast(ulong) 0U;
|
||||
enum ulong type_max = cast(ulong) 15U;
|
||||
enum ulong type_min = 0UL;
|
||||
enum ulong type_max = 15UL;
|
||||
///
|
||||
@property ulong reserved() @safe pure nothrow @nogc const
|
||||
{
|
||||
@ -2511,6 +2511,6 @@ struct perf_branch_entry
|
||||
(cast(typeof(perf_branch_entry_bitmanip)) v << 24U) & 18446744073692774400UL));
|
||||
}
|
||||
|
||||
enum ulong reserved_min = cast(ulong) 0U;
|
||||
enum ulong reserved_max = cast(ulong) 1099511627775UL;
|
||||
enum ulong reserved_min = 0UL;
|
||||
enum ulong reserved_max = 1099511627775UL;
|
||||
}
|
||||
|
@ -59,72 +59,11 @@ else version (D_InlineAsm_X86_64)
|
||||
version = AsmX86_64_Posix;
|
||||
}
|
||||
}
|
||||
else version (X86)
|
||||
{
|
||||
version (CET) {} else
|
||||
{
|
||||
version = AsmExternal;
|
||||
}
|
||||
}
|
||||
else version (X86_64)
|
||||
{
|
||||
version (CET) {} else
|
||||
version (D_X32) {} else
|
||||
{
|
||||
version = AsmExternal;
|
||||
}
|
||||
}
|
||||
else version (PPC)
|
||||
{
|
||||
version (Posix)
|
||||
{
|
||||
version = AsmExternal;
|
||||
}
|
||||
}
|
||||
else version (MIPS_O32)
|
||||
{
|
||||
version (Posix)
|
||||
{
|
||||
version = AsmExternal;
|
||||
}
|
||||
}
|
||||
else version (AArch64)
|
||||
{
|
||||
version (Posix)
|
||||
{
|
||||
version = AsmExternal;
|
||||
}
|
||||
}
|
||||
else version (ARM)
|
||||
{
|
||||
version (Posix)
|
||||
{
|
||||
version = AsmExternal;
|
||||
}
|
||||
}
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
version (AsmX86_Windows) {} else
|
||||
version (AsmX86_Posix) {} else
|
||||
version (AsmX86_64_Windows) {} else
|
||||
version (AsmX86_64_Posix) {} else
|
||||
version (AsmExternal) {} else
|
||||
{
|
||||
// NOTE: The ucontext implementation requires architecture specific
|
||||
// data definitions to operate so testing for it must be done
|
||||
// by checking for the existence of ucontext_t rather than by
|
||||
// a version identifier. Please note that this is considered
|
||||
// an obsolescent feature according to the POSIX spec, so a
|
||||
// custom solution is still preferred.
|
||||
static import core.sys.posix.ucontext;
|
||||
}
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below
|
||||
import core.stdc.stdlib; // for malloc, atexit
|
||||
import core.stdc.stdlib : free, malloc, realloc;
|
||||
import core.sys.windows.basetsd /+: HANDLE+/;
|
||||
import core.sys.windows.threadaux /+: getThreadStackBottom, impersonate_thread, OpenThreadHandle+/;
|
||||
import core.sys.windows.winbase /+: CloseHandle, CREATE_SUSPENDED, DuplicateHandle, GetCurrentThread,
|
||||
@ -142,7 +81,7 @@ else version (Posix)
|
||||
{
|
||||
static import core.sys.posix.pthread;
|
||||
static import core.sys.posix.signal;
|
||||
import core.stdc.errno;
|
||||
import core.stdc.errno : EINTR, errno;
|
||||
import core.sys.posix.pthread : pthread_atfork, pthread_attr_destroy, pthread_attr_getstack, pthread_attr_init,
|
||||
pthread_attr_setstacksize, pthread_create, pthread_detach, pthread_getschedparam, pthread_join, pthread_self,
|
||||
pthread_setschedparam, sched_get_priority_max, sched_get_priority_min, sched_param, sched_yield;
|
||||
@ -157,9 +96,34 @@ else version (Posix)
|
||||
{
|
||||
import core.sys.darwin.mach.kern_return : KERN_SUCCESS;
|
||||
import core.sys.darwin.mach.port : mach_port_t;
|
||||
import core.sys.darwin.mach.thread_act : mach_msg_type_number_t, thread_get_state, thread_resume,
|
||||
thread_suspend, x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, x86_thread_state64_t;
|
||||
import core.sys.darwin.mach.thread_act : mach_msg_type_number_t,
|
||||
thread_get_state, thread_resume, thread_suspend;
|
||||
import core.sys.darwin.pthread : pthread_mach_thread_np;
|
||||
version (X86)
|
||||
{
|
||||
import core.sys.darwin.mach.thread_act :
|
||||
x86_THREAD_STATE32, x86_THREAD_STATE32_COUNT, x86_thread_state32_t;
|
||||
}
|
||||
else version (X86_64)
|
||||
{
|
||||
import core.sys.darwin.mach.thread_act :
|
||||
x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, x86_thread_state64_t;
|
||||
}
|
||||
else version (AArch64)
|
||||
{
|
||||
import core.sys.darwin.mach.thread_act :
|
||||
ARM_THREAD_STATE64, ARM_THREAD_STATE64_COUNT, arm_thread_state64_t;
|
||||
}
|
||||
else version (PPC)
|
||||
{
|
||||
import core.sys.darwin.mach.thread_act :
|
||||
PPC_THREAD_STATE32, PPC_THREAD_STATE32_COUNT, ppc_thread_state32_t;
|
||||
}
|
||||
else version (PPC64)
|
||||
{
|
||||
import core.sys.darwin.mach.thread_act :
|
||||
PPC_THREAD_STATE64, PPC_THREAD_STATE64_COUNT, ppc_thread_state64_t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,8 +67,7 @@ module core.time;
|
||||
|
||||
import core.exception;
|
||||
import core.internal.string;
|
||||
import core.stdc.stdio;
|
||||
import core.stdc.time;
|
||||
import core.stdc.time : time;
|
||||
|
||||
version (OSX)
|
||||
version = Darwin;
|
||||
@ -94,6 +93,8 @@ else version (Posix)
|
||||
import core.sys.posix.time : clock_getres, clock_gettime, CLOCK_MONOTONIC, timespec;
|
||||
}
|
||||
|
||||
version (unittest) import core.stdc.stdio : printf;
|
||||
|
||||
|
||||
//This probably should be moved somewhere else in druntime which
|
||||
//is Darwin-specific.
|
||||
@ -2700,7 +2701,7 @@ unittest
|
||||
|
||||
// It would be too expensive to cover a large range of possible values for
|
||||
// ticks, so we use random values in an attempt to get reasonable coverage.
|
||||
import core.stdc.stdlib;
|
||||
import core.stdc.stdlib : rand, srand;
|
||||
immutable seed = cast(int)time(null);
|
||||
srand(seed);
|
||||
scope(failure) printf("seed %d\n", seed);
|
||||
@ -2714,7 +2715,7 @@ unittest
|
||||
// than or equal to freq5, which at one point was considered for MonoTime's
|
||||
// ticksPerSecond rather than using the system's actual clock frequency, so
|
||||
// it seemed like a good test case to have.
|
||||
import core.stdc.math;
|
||||
import core.stdc.math : floor, log10, pow;
|
||||
immutable numDigitsMinus1 = cast(int)floor(log10(freq5));
|
||||
auto freq6 = cast(long)pow(10, numDigitsMinus1);
|
||||
if (freq5 > freq6)
|
||||
|
@ -471,6 +471,13 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF
|
||||
useExceptionTrap = false;
|
||||
}
|
||||
|
||||
version (none)
|
||||
{
|
||||
// Causes test failures related to Fibers, not enabled by default yet
|
||||
import etc.linux.memoryerror;
|
||||
cast(void) registerMemoryAssertHandler();
|
||||
}
|
||||
|
||||
void tryExec(scope void delegate() dg)
|
||||
{
|
||||
if (useExceptionTrap)
|
||||
@ -627,10 +634,7 @@ extern (C) void _d_print_throwable(Throwable t)
|
||||
|
||||
HANDLE windowsHandle(int fd)
|
||||
{
|
||||
version (CRuntime_Microsoft)
|
||||
return cast(HANDLE)_get_osfhandle(fd);
|
||||
else
|
||||
return _fdToHandle(fd);
|
||||
return cast(HANDLE)_get_osfhandle(fd);
|
||||
}
|
||||
|
||||
// ensure the exception is shown at the beginning of the line, while also
|
||||
|
@ -13,10 +13,8 @@
|
||||
module rt.lifetime;
|
||||
|
||||
import core.attribute : weak;
|
||||
import core.internal.array.utils : __arrayStart, __arrayClearPad;
|
||||
import core.memory;
|
||||
import core.internal.gc.blkcache;
|
||||
import core.internal.gc.blockmeta;
|
||||
import core.internal.gc.blockmeta : PAGESIZE;
|
||||
debug(PRINTF) import core.stdc.stdio;
|
||||
static import rt.tlsgc;
|
||||
|
||||
@ -210,43 +208,22 @@ inout(TypeInfo) unqualify(return scope inout(TypeInfo) cti) pure nothrow @nogc
|
||||
return ti;
|
||||
}
|
||||
|
||||
/**
|
||||
allocate an array memory block by applying the proper padding and
|
||||
assigning block attributes if not inherited from the existing block
|
||||
*/
|
||||
private BlkInfo __arrayAlloc(size_t arrsize, const scope TypeInfo ti, const TypeInfo tinext) nothrow pure
|
||||
private uint __typeAttrs(const scope TypeInfo ti, void *copyAttrsFrom = null) pure nothrow
|
||||
{
|
||||
import core.checkedint;
|
||||
|
||||
return __arrayAlloc(arrsize, null, ti, tinext);
|
||||
}
|
||||
|
||||
private BlkInfo __arrayAlloc(size_t arrsize, void* copyAttrsFrom, const scope TypeInfo ti, const TypeInfo tinext) nothrow pure
|
||||
{
|
||||
import core.checkedint;
|
||||
|
||||
immutable padsize = __arrayPad(arrsize, tinext);
|
||||
bool overflow;
|
||||
auto padded_size = addu(arrsize, padsize, overflow);
|
||||
if (overflow)
|
||||
{
|
||||
return BlkInfo();
|
||||
}
|
||||
|
||||
uint attr = (!(tinext.flags & 1) ? BlkAttr.NO_SCAN : 0);
|
||||
if (copyAttrsFrom)
|
||||
{
|
||||
// try to copy attrs from the given block
|
||||
auto info = GC.query(copyAttrsFrom);
|
||||
if (info.base)
|
||||
attr = info.attr;
|
||||
return info.attr;
|
||||
}
|
||||
// always make sure the appendable attr is set.
|
||||
attr |= BlkAttr.APPENDABLE;
|
||||
|
||||
auto bi = GC.qalloc(padded_size, attr, tinext);
|
||||
__arrayClearPad(bi, arrsize, padsize);
|
||||
return bi;
|
||||
uint attrs = !(ti.flags & 1) ? BlkAttr.NO_SCAN : 0;
|
||||
if (typeid(ti) is typeid(TypeInfo_Struct)) {
|
||||
auto sti = cast(TypeInfo_Struct)cast(void*)ti;
|
||||
if (sti.xdtor)
|
||||
attrs |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -417,37 +394,38 @@ Lcontinue:
|
||||
|
||||
// step 2, if reserving in-place doesn't work, allocate a new array with at
|
||||
// least the requested allocated size.
|
||||
auto info = __arrayAlloc(reqsize, (*p).ptr, ti, tinext);
|
||||
if (info.base is null)
|
||||
auto attrs = __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE;
|
||||
auto ptr = GC.malloc(reqsize, attrs, tinext);
|
||||
if (ptr is null)
|
||||
goto Loverflow;
|
||||
|
||||
// copy the data over.
|
||||
// note that malloc will have initialized the data we did not request to 0.
|
||||
auto tgt = __arrayStart(info);
|
||||
memcpy(tgt, (*p).ptr, datasize);
|
||||
memcpy(ptr, (*p).ptr, datasize);
|
||||
|
||||
// handle postblit
|
||||
__doPostblit(tgt, datasize, tinext);
|
||||
__doPostblit(ptr, datasize, tinext);
|
||||
|
||||
if (!(info.attr & BlkAttr.NO_SCAN))
|
||||
if (!(attrs & BlkAttr.NO_SCAN))
|
||||
{
|
||||
// need to memset the newly requested data, except for the data that
|
||||
// malloc returned that we didn't request.
|
||||
void *endptr = tgt + reqsize;
|
||||
void *begptr = tgt + datasize;
|
||||
void *endptr = ptr + reqsize;
|
||||
void *begptr = ptr + datasize;
|
||||
|
||||
// sanity check
|
||||
assert(endptr >= begptr);
|
||||
memset(begptr, 0, endptr - begptr);
|
||||
}
|
||||
|
||||
// set up the correct length
|
||||
__setArrayAllocLength(info, datasize, isshared, tinext);
|
||||
if (!isshared)
|
||||
__insertBlkInfoCache(info, null);
|
||||
*p = ptr[0 .. (*p).length];
|
||||
|
||||
*p = (cast(void*)tgt)[0 .. (*p).length];
|
||||
// set up the correct length. Note that we need to do this here, because
|
||||
// the GC malloc will automatically set the used size to what we requested.
|
||||
gc_shrinkArrayUsed(ptr[0 .. datasize], reqsize, isshared);
|
||||
|
||||
curCapacity = __arrayAllocCapacity(info);
|
||||
curCapacity = gc_reserveArrayCapacity(ptr[0 .. datasize], 0, isshared);
|
||||
assert(curCapacity);
|
||||
return curCapacity / size;
|
||||
}
|
||||
|
||||
@ -509,15 +487,11 @@ Loverflow:
|
||||
assert(0);
|
||||
Lcontinue:
|
||||
|
||||
auto info = __arrayAlloc(size, ti, tinext);
|
||||
if (!info.base)
|
||||
auto ptr = GC.malloc(size, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext);
|
||||
if (!ptr)
|
||||
goto Loverflow;
|
||||
debug(PRINTF) printf(" p = %p\n", info.base);
|
||||
// update the length of the array
|
||||
auto arrstart = __arrayStart(info);
|
||||
auto isshared = typeid(ti) is typeid(TypeInfo_Shared);
|
||||
__setArrayAllocLength(info, size, isshared, tinext);
|
||||
return arrstart[0..length];
|
||||
debug(PRINTF) printf(" p = %p\n", ptr);
|
||||
return ptr[0 .. length];
|
||||
}
|
||||
|
||||
/// ditto
|
||||
@ -580,24 +554,9 @@ Returns:
|
||||
extern (C) void* _d_newitemU(scope const TypeInfo _ti) pure nothrow @weak
|
||||
{
|
||||
auto ti = unqualify(_ti);
|
||||
auto flags = !(ti.flags & 1) ? BlkAttr.NO_SCAN : 0;
|
||||
immutable tiSize = structTypeInfoSize(ti);
|
||||
immutable itemSize = ti.tsize;
|
||||
immutable size = itemSize + tiSize;
|
||||
if (tiSize)
|
||||
flags |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
|
||||
auto flags = __typeAttrs(ti);
|
||||
|
||||
auto blkInf = GC.qalloc(size, flags, ti);
|
||||
auto p = blkInf.base;
|
||||
|
||||
if (tiSize)
|
||||
{
|
||||
// the GC might not have cleared the padding area in the block
|
||||
*cast(TypeInfo*)(p + (itemSize & ~(size_t.sizeof - 1))) = null;
|
||||
__setBlockFinalizerInfo(blkInf, cast() ti);
|
||||
}
|
||||
|
||||
return p;
|
||||
return GC.malloc(ti.tsize, flags, ti);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -659,16 +618,25 @@ extern (C) CollectHandler rt_getCollectHandler()
|
||||
*/
|
||||
extern (C) int rt_hasFinalizerInSegment(void* p, size_t size, uint attr, scope const(void)[] segment) nothrow
|
||||
{
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
if (attr & BlkAttr.STRUCTFINAL)
|
||||
{
|
||||
if (attr & BlkAttr.APPENDABLE)
|
||||
return hasArrayFinalizerInSegment(p, size, segment);
|
||||
return hasStructFinalizerInSegment(p, size, segment);
|
||||
import core.internal.gc.blockmeta;
|
||||
auto info = BlkInfo(
|
||||
base: p,
|
||||
size: size,
|
||||
attr: attr
|
||||
);
|
||||
|
||||
auto ti = cast(TypeInfo_Struct)cast(void*)__getBlockFinalizerInfo(info);
|
||||
return cast(size_t)(cast(void*)ti.xdtor - segment.ptr) < segment.length;
|
||||
}
|
||||
|
||||
// otherwise class
|
||||
auto ppv = cast(void**) p;
|
||||
if (!p || !*ppv)
|
||||
if (!*ppv)
|
||||
return false;
|
||||
|
||||
auto c = *cast(ClassInfo*)*ppv;
|
||||
@ -682,68 +650,8 @@ extern (C) int rt_hasFinalizerInSegment(void* p, size_t size, uint attr, scope c
|
||||
return false;
|
||||
}
|
||||
|
||||
int hasStructFinalizerInSegment(void* p, size_t size, in void[] segment) nothrow
|
||||
{
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
auto ti = *cast(TypeInfo_Struct*)(p + size - size_t.sizeof);
|
||||
return cast(size_t)(cast(void*)ti.xdtor - segment.ptr) < segment.length;
|
||||
}
|
||||
|
||||
int hasArrayFinalizerInSegment(void* p, size_t size, in void[] segment) nothrow
|
||||
{
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
TypeInfo_Struct si = void;
|
||||
if (size < PAGESIZE)
|
||||
si = *cast(TypeInfo_Struct*)(p + size - size_t.sizeof);
|
||||
else
|
||||
si = *cast(TypeInfo_Struct*)(p + size_t.sizeof);
|
||||
|
||||
return cast(size_t)(cast(void*)si.xdtor - segment.ptr) < segment.length;
|
||||
}
|
||||
|
||||
debug (VALGRIND) import etc.valgrind.valgrind;
|
||||
|
||||
// called by the GC
|
||||
void finalize_array2(void* p, size_t size) nothrow
|
||||
{
|
||||
debug(PRINTF) printf("rt_finalize_array2(p = %p)\n", p);
|
||||
|
||||
// construct a BlkInfo to match the array API
|
||||
auto info = BlkInfo(
|
||||
base: p,
|
||||
size: size,
|
||||
attr: BlkAttr.APPENDABLE | BlkAttr.STRUCTFINAL
|
||||
);
|
||||
auto usedsize = __arrayAllocLength(info);
|
||||
auto arrptr = __arrayStart(info);
|
||||
|
||||
debug (VALGRIND)
|
||||
{
|
||||
auto block = p[0..size];
|
||||
disableAddrReportingInRange(block);
|
||||
}
|
||||
|
||||
TypeInfo_Struct si = size < PAGESIZE ?
|
||||
*cast(TypeInfo_Struct*)(p + size - size_t.sizeof) : // small
|
||||
*cast(TypeInfo_Struct*)(p + size_t.sizeof); // large
|
||||
|
||||
debug (VALGRIND) enableAddrReportingInRange(block);
|
||||
|
||||
try
|
||||
{
|
||||
finalize_array(arrptr, usedsize, si);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
import core.exception : onFinalizeError;
|
||||
onFinalizeError(si, e);
|
||||
}
|
||||
}
|
||||
|
||||
void finalize_array(void* p, size_t size, const TypeInfo_Struct si)
|
||||
{
|
||||
// Due to the fact that the delete operator calls destructors
|
||||
@ -758,11 +666,10 @@ void finalize_array(void* p, size_t size, const TypeInfo_Struct si)
|
||||
}
|
||||
|
||||
// called by the GC
|
||||
void finalize_struct(void* p, size_t size) nothrow
|
||||
void finalize_struct(void* p, TypeInfo_Struct ti) nothrow
|
||||
{
|
||||
debug(PRINTF) printf("finalize_struct(p = %p)\n", p);
|
||||
|
||||
auto ti = *cast(TypeInfo_Struct*)(p + size - size_t.sizeof);
|
||||
try
|
||||
{
|
||||
ti.destroy(p); // call destructor
|
||||
@ -828,12 +735,37 @@ extern (C) void rt_finalize(void* p, bool det = true) nothrow
|
||||
extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr) nothrow
|
||||
{
|
||||
// to verify: reset memory necessary?
|
||||
if (!(attr & BlkAttr.STRUCTFINAL))
|
||||
if (!(attr & BlkAttr.STRUCTFINAL)) {
|
||||
rt_finalize2(p, false, false); // class
|
||||
else if (attr & BlkAttr.APPENDABLE)
|
||||
finalize_array2(p, size); // array of structs
|
||||
return;
|
||||
}
|
||||
|
||||
// get the struct typeinfo from the block, and the used size.
|
||||
import core.internal.gc.blockmeta;
|
||||
auto info = BlkInfo(
|
||||
base: p,
|
||||
size: size,
|
||||
attr: attr
|
||||
);
|
||||
|
||||
auto si = cast(TypeInfo_Struct)cast(void*)__getBlockFinalizerInfo(info);
|
||||
|
||||
if (attr & BlkAttr.APPENDABLE)
|
||||
{
|
||||
auto usedsize = __arrayAllocLength(info);
|
||||
auto arrptr = __arrayStart(info);
|
||||
try
|
||||
{
|
||||
finalize_array(arrptr, usedsize, si);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
import core.exception : onFinalizeError;
|
||||
onFinalizeError(si, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
finalize_struct(p, size); // struct
|
||||
finalize_struct(p, si); // struct
|
||||
}
|
||||
|
||||
|
||||
@ -927,28 +859,23 @@ do
|
||||
|
||||
debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength);
|
||||
|
||||
const isshared = typeid(ti) is typeid(TypeInfo_Shared);
|
||||
|
||||
if (!(*p).ptr)
|
||||
{
|
||||
assert((*p).length == 0);
|
||||
// pointer was null, need to allocate
|
||||
auto info = __arrayAlloc(newsize, ti, tinext);
|
||||
if (info.base is null)
|
||||
auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext);
|
||||
if (ptr is null)
|
||||
{
|
||||
onOutOfMemoryError();
|
||||
assert(0);
|
||||
}
|
||||
__setArrayAllocLength(info, newsize, isshared, tinext);
|
||||
if (!isshared)
|
||||
__insertBlkInfoCache(info, null);
|
||||
void* newdata = cast(byte *)__arrayStart(info);
|
||||
memset(newdata, 0, newsize);
|
||||
*p = newdata[0 .. newlength];
|
||||
memset(ptr, 0, newsize);
|
||||
*p = ptr[0 .. newlength];
|
||||
return *p;
|
||||
}
|
||||
|
||||
const size_t size = (*p).length * sizeelem;
|
||||
const isshared = typeid(ti) is typeid(TypeInfo_Shared);
|
||||
|
||||
/* Attempt to extend past the end of the existing array.
|
||||
* If not possible, allocate new space for entire array and copy.
|
||||
@ -956,24 +883,17 @@ do
|
||||
void* newdata = (*p).ptr;
|
||||
if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared))
|
||||
{
|
||||
auto info = __arrayAlloc(newsize, (*p).ptr, ti, tinext);
|
||||
if (info.base is null)
|
||||
newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext);
|
||||
if (newdata is null)
|
||||
{
|
||||
onOutOfMemoryError();
|
||||
assert(0);
|
||||
}
|
||||
|
||||
newdata = __arrayStart(info);
|
||||
newdata[0 .. size] = (*p).ptr[0 .. size];
|
||||
|
||||
__setArrayAllocLength(info, newsize, isshared, tinext);
|
||||
|
||||
// Do postblit processing, as we are making a copy.
|
||||
__doPostblit(newdata, size, tinext);
|
||||
|
||||
// this hasn't been added to the cache yet.
|
||||
if (!isshared)
|
||||
__insertBlkInfoCache(info, null);
|
||||
}
|
||||
|
||||
// Zero the unused portion of the newly allocated space
|
||||
@ -1049,8 +969,6 @@ do
|
||||
|
||||
debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength);
|
||||
|
||||
const isshared = typeid(ti) is typeid(TypeInfo_Shared);
|
||||
|
||||
static void doInitialize(void *start, void *end, const void[] initializer)
|
||||
{
|
||||
if (initializer.length == 1)
|
||||
@ -1072,22 +990,19 @@ do
|
||||
{
|
||||
assert((*p).length == 0);
|
||||
// pointer was null, need to allocate
|
||||
auto info = __arrayAlloc(newsize, ti, tinext);
|
||||
if (info.base is null)
|
||||
auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext);
|
||||
if (ptr is null)
|
||||
{
|
||||
onOutOfMemoryError();
|
||||
assert(0);
|
||||
}
|
||||
__setArrayAllocLength(info, newsize, isshared, tinext);
|
||||
if (!isshared)
|
||||
__insertBlkInfoCache(info, null);
|
||||
void* newdata = cast(byte *)__arrayStart(info);
|
||||
doInitialize(newdata, newdata + newsize, tinext.initializer);
|
||||
*p = newdata[0 .. newlength];
|
||||
doInitialize(ptr, ptr + newsize, tinext.initializer);
|
||||
*p = ptr[0 .. newlength];
|
||||
return *p;
|
||||
}
|
||||
|
||||
const size_t size = (*p).length * sizeelem;
|
||||
const isshared = typeid(ti) is typeid(TypeInfo_Shared);
|
||||
|
||||
/* Attempt to extend past the end of the existing array.
|
||||
* If not possible, allocate new space for entire array and copy.
|
||||
@ -1095,24 +1010,17 @@ do
|
||||
void* newdata = (*p).ptr;
|
||||
if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared))
|
||||
{
|
||||
auto info = __arrayAlloc(newsize, (*p).ptr, ti, tinext);
|
||||
if (info.base is null)
|
||||
newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext);
|
||||
if (newdata is null)
|
||||
{
|
||||
onOutOfMemoryError();
|
||||
assert(0);
|
||||
}
|
||||
|
||||
newdata = __arrayStart(info);
|
||||
newdata[0 .. size] = (*p).ptr[0 .. size];
|
||||
|
||||
__setArrayAllocLength(info, newsize, isshared, tinext);
|
||||
|
||||
// Do postblit processing, as we are making a copy.
|
||||
__doPostblit(newdata, size, tinext);
|
||||
|
||||
// this hasn't been added to the cache yet.
|
||||
if (!isshared)
|
||||
__insertBlkInfoCache(info, null);
|
||||
}
|
||||
|
||||
// Initialize the unused portion of the newly allocated space
|
||||
@ -1207,6 +1115,11 @@ byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n
|
||||
import core.exception : onOutOfMemoryError;
|
||||
// This is a cut&paste job from _d_arrayappendT(). Should be refactored.
|
||||
|
||||
// Short circuit if no data is being appended.
|
||||
if (n == 0)
|
||||
return px;
|
||||
|
||||
|
||||
// only optimize array append where ti is not a shared type
|
||||
auto tinext = unqualify(ti.next);
|
||||
auto sizeelem = tinext.tsize; // array element size
|
||||
@ -1220,32 +1133,33 @@ byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n
|
||||
{
|
||||
// could not set the size, we must reallocate.
|
||||
auto newcap = newCapacity(newlength, sizeelem);
|
||||
auto info = __arrayAlloc(newcap, px.ptr, ti, tinext);
|
||||
if (info.base is null)
|
||||
auto attrs = __typeAttrs(tinext, px.ptr) | BlkAttr.APPENDABLE;
|
||||
auto ptr = cast(byte*) GC.malloc(newcap, attrs, tinext);
|
||||
if (ptr is null)
|
||||
{
|
||||
onOutOfMemoryError();
|
||||
assert(0);
|
||||
}
|
||||
|
||||
__setArrayAllocLength(info, newsize, isshared, tinext);
|
||||
if (!isshared)
|
||||
__insertBlkInfoCache(info, null);
|
||||
if (newsize != newcap)
|
||||
{
|
||||
// For small blocks that are always fully scanned, if we allocated more
|
||||
// capacity than was requested, we are responsible for zeroing that
|
||||
// memory.
|
||||
// TODO: should let the GC figure this out, as this property may
|
||||
// not always hold.
|
||||
if (!(attrs & BlkAttr.NO_SCAN) && newcap < PAGESIZE)
|
||||
memset(ptr + newsize, 0, newcap - newsize);
|
||||
|
||||
auto newdata = cast(byte*)__arrayStart(info);
|
||||
memcpy(newdata, px.ptr, size);
|
||||
gc_shrinkArrayUsed(ptr[0 .. newsize], newcap, isshared);
|
||||
}
|
||||
|
||||
|
||||
// For small blocks that are always fully scanned, if we allocated more
|
||||
// capacity than was requested, we are responsible for zeroing that
|
||||
// memory.
|
||||
// large blocks are only scanned up to the used size.
|
||||
if (!(info.attr & BlkAttr.NO_SCAN) && newcap > newcap && info.size < PAGESIZE)
|
||||
memset(newdata + newsize, 0, newcap - newsize);
|
||||
memcpy(ptr, px.ptr, size);
|
||||
|
||||
// do potsblit processing.
|
||||
__doPostblit(newdata, size, tinext);
|
||||
__doPostblit(ptr, size, tinext);
|
||||
|
||||
px = newdata[0 .. newlength];
|
||||
px = ptr[0 .. newlength];
|
||||
return px;
|
||||
}
|
||||
|
||||
@ -1428,16 +1342,12 @@ void* _d_arrayliteralTX(const TypeInfo ti, size_t length) @weak
|
||||
|
||||
debug(PRINTF) printf("_d_arrayliteralTX(sizeelem = %zd, length = %zd)\n", sizeelem, length);
|
||||
if (length == 0 || sizeelem == 0)
|
||||
result = null;
|
||||
return null;
|
||||
else
|
||||
{
|
||||
auto allocsize = length * sizeelem;
|
||||
auto info = __arrayAlloc(allocsize, ti, tinext);
|
||||
auto isshared = typeid(ti) is typeid(TypeInfo_Shared);
|
||||
__setArrayAllocLength(info, allocsize, isshared, tinext);
|
||||
result = __arrayStart(info);
|
||||
return GC.malloc(allocsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -1804,6 +1714,7 @@ unittest
|
||||
GC.free(larr1);
|
||||
|
||||
auto larr2 = new S[255];
|
||||
import core.internal.gc.blockmeta : LARGEPREFIX;
|
||||
if (cast(void*)larr1 is cast(void*)larr2.ptr - LARGEPREFIX) // reusage not guaranteed
|
||||
{
|
||||
auto ptr = cast(S**)larr1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
336bed6d8ffec74d117b755866c5bd22e3d610a1
|
||||
1b242048c9db88c52cb0df6cd50c2b7455bedc01
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/phobos repository.
|
||||
|
@ -2885,6 +2885,17 @@ if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
|
||||
{
|
||||
if (&lhs != &rhs)
|
||||
{
|
||||
static if (__traits(compiles, lhs.tupleof = rhs.tupleof))
|
||||
{
|
||||
if (__ctfe)
|
||||
{
|
||||
// can't reinterpret cast
|
||||
foreach (i, ref e; lhs.tupleof)
|
||||
swap(e, rhs.tupleof[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// For structs with non-trivial assignment, move memory directly
|
||||
ubyte[T.sizeof] t = void;
|
||||
auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof];
|
||||
@ -3128,6 +3139,18 @@ if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
|
||||
swap(a3, a4);
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=21429
|
||||
@safe unittest
|
||||
{
|
||||
enum e = (){
|
||||
Tuple!int a = 5, b = 6;
|
||||
swap(a, b);
|
||||
assert(a[0] == 6);
|
||||
assert(b[0] == 5);
|
||||
return 0;
|
||||
}();
|
||||
}
|
||||
|
||||
/**
|
||||
Swaps two elements in-place of a range `r`,
|
||||
specified by their indices `i1` and `i2`.
|
||||
|
@ -2169,13 +2169,13 @@ Allows to directly use range operations on lines of a file.
|
||||
private struct ByLineImpl(Char, Terminator)
|
||||
{
|
||||
private:
|
||||
import std.typecons : RefCounted, RefCountedAutoInitialize;
|
||||
import std.typecons : borrow, RefCountedAutoInitialize, SafeRefCounted;
|
||||
|
||||
/* Ref-counting stops the source range's Impl
|
||||
* from getting out of sync after the range is copied, e.g.
|
||||
* when accessing range.front, then using std.range.take,
|
||||
* then accessing range.front again. */
|
||||
alias PImpl = RefCounted!(Impl, RefCountedAutoInitialize.no);
|
||||
alias PImpl = SafeRefCounted!(Impl, RefCountedAutoInitialize.no);
|
||||
PImpl impl;
|
||||
|
||||
static if (isScalarType!Terminator)
|
||||
@ -2190,19 +2190,24 @@ Allows to directly use range operations on lines of a file.
|
||||
impl = PImpl(f, kt, terminator);
|
||||
}
|
||||
|
||||
@property bool empty()
|
||||
/* Verifiably `@safe` when built with -preview=DIP1000. */
|
||||
@property bool empty() @trusted
|
||||
{
|
||||
return impl.refCountedPayload.empty;
|
||||
// Using `ref` is actually necessary here.
|
||||
return impl.borrow!((ref i) => i.empty);
|
||||
}
|
||||
|
||||
@property Char[] front()
|
||||
/* Verifiably `@safe` when built with -preview=DIP1000. */
|
||||
@property Char[] front() @trusted
|
||||
{
|
||||
return impl.refCountedPayload.front;
|
||||
// Using `ref` is likely optional here.
|
||||
return impl.borrow!((ref i) => i.front);
|
||||
}
|
||||
|
||||
void popFront()
|
||||
/* Verifiably `@safe` when built with -preview=DIP1000. */
|
||||
void popFront() @trusted
|
||||
{
|
||||
impl.refCountedPayload.popFront();
|
||||
return impl.borrow!((ref i) => i.popFront());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2216,6 +2221,7 @@ Allows to directly use range operations on lines of a file.
|
||||
KeepTerminator keepTerminator;
|
||||
bool haveLine;
|
||||
|
||||
@safe:
|
||||
public:
|
||||
this(File f, KeepTerminator kt, Terminator terminator)
|
||||
{
|
||||
@ -2375,7 +2381,7 @@ void main()
|
||||
return ByLineImpl!(Char, Terminator)(this, keepTerminator, terminator);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
@safe unittest
|
||||
{
|
||||
static import std.file;
|
||||
auto deleteme = testFilename();
|
||||
@ -2393,7 +2399,7 @@ void main()
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19980
|
||||
@system unittest
|
||||
@safe unittest
|
||||
{
|
||||
static import std.file;
|
||||
auto deleteme = testFilename();
|
||||
@ -2541,12 +2547,11 @@ $(REF readText, std,file)
|
||||
is(typeof(File("").byLineCopy!(char, char).front) == char[]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
static import std.file;
|
||||
|
||||
scope(failure) printf("Failed test at line %d\n", __LINE__);
|
||||
auto deleteme = testFilename();
|
||||
std.file.write(deleteme, "");
|
||||
scope(success) std.file.remove(deleteme);
|
||||
@ -2620,7 +2625,7 @@ $(REF readText, std,file)
|
||||
test("sue\r", ["sue\r"], kt, '\r');
|
||||
}
|
||||
|
||||
@system unittest
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : drop, take;
|
||||
@ -4765,6 +4770,15 @@ struct lines
|
||||
foreach (line; myByLineCopy)
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
auto f = File(deleteMe, "r");
|
||||
scope(exit) { f.close(); }
|
||||
|
||||
auto myByLine = f.byLine;
|
||||
foreach (line; myByLine)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
|
@ -980,24 +980,35 @@ if (distinctFieldNames!(Specs))
|
||||
{
|
||||
import std.algorithm.mutation : swap;
|
||||
|
||||
static if (is(R == Tuple!Types) && !__traits(isRef, rhs) && isTuple!R)
|
||||
/*
|
||||
This optimization caused compilation failures with no error message available:
|
||||
|
||||
> Error: unknown, please file report on issues.dlang.org
|
||||
> std/sumtype.d(1262): Error: template instance `std.sumtype.SumType!(Flag, Tuple!(This*))` error instantiating
|
||||
*/
|
||||
version (none)
|
||||
{
|
||||
if (__ctfe)
|
||||
static if (is(R == Tuple!Types) && !__traits(isRef, rhs) && isTuple!R)
|
||||
{
|
||||
// Cannot use swap at compile time
|
||||
field[] = rhs.field[];
|
||||
if (__ctfe)
|
||||
{
|
||||
// Cannot use swap at compile time
|
||||
field[] = rhs.field[];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use swap-and-destroy to optimize rvalue assignment
|
||||
swap!(Tuple!Types)(this, rhs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use swap-and-destroy to optimize rvalue assignment
|
||||
swap!(Tuple!Types)(this, rhs);
|
||||
// Do not swap; opAssign should be called on the fields.
|
||||
field[] = rhs.field[];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not swap; opAssign should be called on the fields.
|
||||
field[] = rhs.field[];
|
||||
}
|
||||
|
||||
field[] = rhs.field[];
|
||||
return this;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user