From 2ead01297ced8fd03387021025222a839503eaf6 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 18 Jan 2025 17:35:27 +0100 Subject: [PATCH] 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. --- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/blockexit.d | 4 +- gcc/d/dmd/dcast.d | 11 +- gcc/d/dmd/dscope.d | 2 + gcc/d/dmd/dversion.d | 18 +- gcc/d/dmd/escape.d | 4 +- gcc/d/dmd/expression.d | 2 +- gcc/d/dmd/expressionsem.d | 26 +- gcc/d/dmd/func.d | 31 +- gcc/d/dmd/funcsem.d | 16 +- gcc/d/dmd/lexer.d | 14 +- gcc/d/dmd/mtype.d | 9 +- gcc/d/dmd/nogc.d | 36 +- gcc/d/dmd/ob.d | 2 +- gcc/d/dmd/opover.d | 2 +- gcc/d/dmd/parse.d | 39 +-- gcc/d/dmd/root/filename.d | 5 +- gcc/d/dmd/safe.d | 71 ++-- gcc/d/dmd/semantic3.d | 2 +- gcc/d/dmd/statementsem.d | 6 +- gcc/d/dmd/typesem.d | 4 +- gcc/testsuite/gdc.dg/asm3.d | 2 +- .../fail_compilation/attributediagnostic.d | 25 +- .../attributediagnostic_nogc.d | 12 +- .../attributediagnostic_nothrow.d | 20 +- .../attributediagnostic_pure.d | 5 +- .../gdc.test/fail_compilation/diag10319.d | 27 +- .../gdc.test/fail_compilation/diag11198.d | 14 +- .../gdc.test/fail_compilation/diag9620.d | 7 +- .../fail_compilation/diag_debug_conditional.d | 4 +- .../gdc.test/fail_compilation/fail12932.d | 4 +- .../gdc.test/fail_compilation/fail21928.d | 2 +- .../gdc.test/fail_compilation/fail21928b.d | 2 +- .../gdc.test/fail_compilation/lexer23465.d | 19 +- .../gdc.test/fail_compilation/nogc1.d | 22 +- .../gdc.test/fail_compilation/nogc2.d | 32 +- .../gdc.test/fail_compilation/nogc3.d | 14 +- .../systemvariables_deprecation.d | 7 +- .../gdc.test/fail_compilation/test13786.d | 12 +- .../gdc.test/fail_compilation/test20655.d | 15 +- .../gdc.test/fail_compilation/test23170.d | 2 +- .../gdc.test/fail_compilation/testInference.d | 9 +- gcc/testsuite/gdc.test/runnable/lexer.d | 17 - gcc/testsuite/gdc.test/runnable/sdtor.d | 40 +-- libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/core/gc/config.d | 2 +- libphobos/libdruntime/core/int128.d | 2 +- .../core/internal/array/construction.d | 40 ++- .../libdruntime/core/internal/array/utils.d | 115 +------ .../libdruntime/core/internal/gc/blockmeta.d | 79 ++++- .../core/internal/gc/impl/conservative/gc.d | 162 +++++++-- libphobos/libdruntime/core/lifetime.d | 2 +- libphobos/libdruntime/core/memory.d | 2 +- libphobos/libdruntime/core/runtime.d | 4 +- libphobos/libdruntime/core/sync/condition.d | 2 +- libphobos/libdruntime/core/sync/semaphore.d | 4 +- .../libdruntime/core/sys/linux/perf_event.d | 240 ++++++------- libphobos/libdruntime/core/thread/osthread.d | 94 ++---- libphobos/libdruntime/core/time.d | 9 +- libphobos/libdruntime/rt/dmain2.d | 12 +- libphobos/libdruntime/rt/lifetime.d | 315 +++++++----------- libphobos/src/MERGE | 2 +- libphobos/src/std/algorithm/mutation.d | 23 ++ libphobos/src/std/stdio.d | 40 ++- libphobos/src/std/typecons.d | 33 +- 65 files changed, 851 insertions(+), 952 deletions(-) diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 33bb398c00d4..4172630afa08 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -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. diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d index dc3e379e8d4b..2125fb9386aa 100644 --- a/gcc/d/dmd/blockexit.d +++ b/gcc/d/dmd/blockexit.d @@ -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_; } diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 0c4b469de5d4..2f33301f0c27 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -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(); } } diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index 8648231b4a83..a683d9c3c0fb 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -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; } } diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d index 36e9cf80189d..42d7d8f45188 100644 --- a/gcc/d/dmd/dversion.d +++ b/gcc/d/dmd/dversion.d @@ -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 diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 947abf0c4bcb..ecf4f919f28f 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -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); } /*************************************** diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 2a828d85473f..75d64682aea5 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -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; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index cd7548ea27cf..eb4a5f884f64 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -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()); diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index b42ac768b450..993bce85ee6c 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -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(); } } diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d index 2bd593ed49b2..9f2ff1e1afd1 100644 --- a/gcc/d/dmd/funcsem.d +++ b/gcc/d/dmd/funcsem.d @@ -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; diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 7bf32a9ddb8d..406829d8257e 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -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; diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index b6d44c7f136b..f91687b7f39f 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -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++) diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d index ff1e173af476..d9a742f7022a 100644 --- a/gcc/d/dmd/nogc.d +++ b/gcc/d/dmd/nogc.d @@ -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()) { diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d index 2019e82cd7bd..ab480190a5d5 100644 --- a/gcc/d/dmd/ob.d +++ b/gcc/d/dmd/ob.d @@ -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()); diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d index c126b1d28c4a..56b36010be59 100644 --- a/gcc/d/dmd/opover.d +++ b/gcc/d/dmd/opover.d @@ -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; diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 415d57824d14..b851b9aafe7e 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -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 = ` 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( )` 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 = ` 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( )` 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); } diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d index cf00d8ad7f63..bd1233d2acb5 100644 --- a/gcc/d/dmd/root/filename.d +++ b/gcc/d/dmd/root/filename.d @@ -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 diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d index f6427a33fc12..bb9cbe9f1676 100644 --- a/gcc/d/dmd/safe.d +++ b/gcc/d/dmd/safe.d @@ -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; } diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index 3553d3dbbf46..def7d46d3e49 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -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 diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 932830d533f0..6bbc1a9b28eb 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -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(); diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index dc3f9da89410..ca10db1a2f5e 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -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) { diff --git a/gcc/testsuite/gdc.dg/asm3.d b/gcc/testsuite/gdc.dg/asm3.d index eadb1c7f7e3f..00c500762248 100644 --- a/gcc/testsuite/gdc.dg/asm3.d +++ b/gcc/testsuite/gdc.dg/asm3.d @@ -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" } } diff --git a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d index da7f8edb6d84..18d1f3604d5a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d +++ b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nogc.d b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nogc.d index e3dbee899fc1..9069ecc4788d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nogc.d +++ b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nogc.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nothrow.d b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nothrow.d index 7fea32244126..add5ccc05a67 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nothrow.d +++ b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_nothrow.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_pure.d b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_pure.d index a120dabf852d..ef3863c475b0 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_pure.d +++ b/gcc/testsuite/gdc.test/fail_compilation/attributediagnostic_pure.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10319.d b/gcc/testsuite/gdc.test/fail_compilation/diag10319.d index 78bd57fe1f21..308319295001 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10319.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10319.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag11198.d b/gcc/testsuite/gdc.test/fail_compilation/diag11198.d index 1be0f1e85a2c..7f8979ccb33f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag11198.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag11198.d @@ -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 = ` 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 = ` 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 = ""; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9620.d b/gcc/testsuite/gdc.test/fail_compilation/diag9620.d index 4af87df0a2f7..87ec1c5a9849 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag9620.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag9620.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag_debug_conditional.d b/gcc/testsuite/gdc.test/fail_compilation/diag_debug_conditional.d index 99884c70c429..51df97c8038f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag_debug_conditional.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag_debug_conditional.d @@ -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 --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12932.d b/gcc/testsuite/gdc.test/fail_compilation/fail12932.d index fe68fea01ca5..2ef9e152d09f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail12932.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail12932.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21928.d b/gcc/testsuite/gdc.test/fail_compilation/fail21928.d index c9fac133ddb2..fd6c26ebd357 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail21928.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21928.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21928b.d b/gcc/testsuite/gdc.test/fail_compilation/fail21928b.d index 3ce93e0a097b..2caf737baa38 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail21928b.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21928b.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer23465.d b/gcc/testsuite/gdc.test/fail_compilation/lexer23465.d index 4ea41a58af14..adf12f5b6bf9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/lexer23465.d +++ b/gcc/testsuite/gdc.test/fail_compilation/lexer23465.d @@ -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, /+ diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc1.d b/gcc/testsuite/gdc.test/fail_compilation/nogc1.d index 859bd40ab061..b2bea5be8e8f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/nogc1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/nogc1.d @@ -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() diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc2.d b/gcc/testsuite/gdc.test/fail_compilation/nogc2.d index 9016dd9e9696..9601c2faa2e6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/nogc2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/nogc2.d @@ -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) diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d index b53903ffbc0f..6fa115a6a8ac 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d index 5ba078d51665..88f6d83632b6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d +++ b/gcc/testsuite/gdc.test/fail_compilation/systemvariables_deprecation.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test13786.d b/gcc/testsuite/gdc.test/fail_compilation/test13786.d index 73ec588c7773..5a873bf9c96e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test13786.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test13786.d @@ -1,21 +1,15 @@ /* TEST_OUTPUT: --- -fail_compilation/test13786.d(16): Deprecation: `debug = ` is deprecated, use debug identifiers instead -fail_compilation/test13786.d(18): Deprecation: `version = ` 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; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20655.d b/gcc/testsuite/gdc.test/fail_compilation/test20655.d index 48a6fe2e9c14..25471d242fa1 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test20655.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test20655.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23170.d b/gcc/testsuite/gdc.test/fail_compilation/test23170.d index fedf31b5fc83..f447128da029 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test23170.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test23170.d @@ -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 diff --git a/gcc/testsuite/gdc.test/fail_compilation/testInference.d b/gcc/testsuite/gdc.test/fail_compilation/testInference.d index a04feae2500f..8a72ff116f8f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/testInference.d +++ b/gcc/testsuite/gdc.test/fail_compilation/testInference.d @@ -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` --- */ diff --git a/gcc/testsuite/gdc.test/runnable/lexer.d b/gcc/testsuite/gdc.test/runnable/lexer.d index 18ad055addcd..0e1068a42899 100644 --- a/gcc/testsuite/gdc.test/runnable/lexer.d +++ b/gcc/testsuite/gdc.test/runnable/lexer.d @@ -1,14 +1,3 @@ -// REQUIRED_ARGS: -verrors=simple -/* -TEST_OUTPUT: ---- -runnable/lexer.d(86): Deprecation: `version( )` is deprecated, use version identifiers instead -runnable/lexer.d(87): Deprecation: `debug( )` 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; /*********************************************************/ diff --git a/gcc/testsuite/gdc.test/runnable/sdtor.d b/gcc/testsuite/gdc.test/runnable/sdtor.d index be15cb244a1b..507c1143feca 100644 --- a/gcc/testsuite/gdc.test/runnable/sdtor.d +++ b/gcc/testsuite/gdc.test/runnable/sdtor.d @@ -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)."); diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 33bb398c00d4..4172630afa08 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -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. diff --git a/libphobos/libdruntime/core/gc/config.d b/libphobos/libdruntime/core/gc/config.d index 258183fd5051..af077be77bcb 100644 --- a/libphobos/libdruntime/core/gc/config.d +++ b/libphobos/libdruntime/core/gc/config.d @@ -7,8 +7,8 @@ module core.gc.config; -import core.stdc.stdio; import core.internal.parseoptions; +import core.stdc.stdio : printf; __gshared Config config; diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d index 4c88f15abfb6..27c8b99d2cbf 100644 --- a/libphobos/libdruntime/core/int128.d +++ b/libphobos/libdruntime/core/int128.d @@ -794,7 +794,7 @@ version (unittest) { version (none) { - import core.stdc.stdio; + import core.stdc.stdio : printf; @trusted void print(Cent c) diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d index c9761ece24bb..c5d8c79bfbc7 100644 --- a/libphobos/libdruntime/core/internal/array/construction.d +++ b/libphobos/libdruntime/core/internal/array/construction.d @@ -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 { diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d index 54cfc26af564..03d414471ad6 100644 --- a/libphobos/libdruntime/core/internal/array/utils.d +++ b/libphobos/libdruntime/core/internal/array/utils.d @@ -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; } diff --git a/libphobos/libdruntime/core/internal/gc/blockmeta.d b/libphobos/libdruntime/core/internal/gc/blockmeta.d index 9d959d54721d..768dcd76ba30 100644 --- a/libphobos/libdruntime/core/internal/gc/blockmeta.d +++ b/libphobos/libdruntime/core/internal/gc/blockmeta.d @@ -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); +} diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index 40e361c50f1c..b5d9802db3f0 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -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]; +} diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d index 84ffdde7a2cb..695f9bc84e74 100644 --- a/libphobos/libdruntime/core/lifetime.d +++ b/libphobos/libdruntime/core/lifetime.d @@ -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` diff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d index 63a3c2e04c80..3b3cb8e6a66f 100644 --- a/libphobos/libdruntime/core/memory.d +++ b/libphobos/libdruntime/core/memory.d @@ -1167,7 +1167,7 @@ extern (C) private @system @nogc nothrow { ref int fakePureErrnoImpl() { - import core.stdc.errno; + import core.stdc.errno : errno; return errno(); } } diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d index dc765e7ecadf..ff1df7ffad13 100644 --- a/libphobos/libdruntime/core/runtime.d +++ b/libphobos/libdruntime/core/runtime.d @@ -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() { diff --git a/libphobos/libdruntime/core/sync/condition.d b/libphobos/libdruntime/core/sync/condition.d index 51ab7b5aa31b..3acee7a7f456 100644 --- a/libphobos/libdruntime/core/sync/condition.d +++ b/libphobos/libdruntime/core/sync/condition.d @@ -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; diff --git a/libphobos/libdruntime/core/sync/semaphore.d b/libphobos/libdruntime/core/sync/semaphore.d index a4dae042ee3b..44465669b7e7 100644 --- a/libphobos/libdruntime/core/sync/semaphore.d +++ b/libphobos/libdruntime/core/sync/semaphore.d @@ -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; diff --git a/libphobos/libdruntime/core/sys/linux/perf_event.d b/libphobos/libdruntime/core/sys/linux/perf_event.d index e0a0c99514cb..0ad072974d5c 100644 --- a/libphobos/libdruntime/core/sys/linux/perf_event.d +++ b/libphobos/libdruntime/core/sys/linux/perf_event.d @@ -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; } diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index e5f0cadbbf2d..e08e4a113eb4 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -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; + } } } diff --git a/libphobos/libdruntime/core/time.d b/libphobos/libdruntime/core/time.d index 53a0533f25e3..8189e67f8af1 100644 --- a/libphobos/libdruntime/core/time.d +++ b/libphobos/libdruntime/core/time.d @@ -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) diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d index be416c47906a..a1ddba513957 100644 --- a/libphobos/libdruntime/rt/dmain2.d +++ b/libphobos/libdruntime/rt/dmain2.d @@ -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 diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index dbdfcb0b1f06..71ed51bf05c0 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -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; diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index fdcc058c9035..9603e65aa423 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -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. diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d index ea1a1b290dc2..8a45ecb81319 100644 --- a/libphobos/src/std/algorithm/mutation.d +++ b/libphobos/src/std/algorithm/mutation.d @@ -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`. diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d index b4413f68f3d3..4734c1b71658 100644 --- a/libphobos/src/std/stdio.d +++ b/libphobos/src/std/stdio.d @@ -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 diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index a841e4720b2c..989ccba042cc 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -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; }