aboutsummaryrefslogtreecommitdiff
path: root/libphobos
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-07-26 17:42:23 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-08-03 13:01:53 +0200
commitb6df113247b9f3f7c3db0e65c481dad5bcfddfb4 (patch)
tree31466a07292ad0cc289de7c23e39ba31b9e8b7c3 /libphobos
parent64ce76d940501cb04d14a0d36752b4f93473531c (diff)
downloadgcc-b6df113247b9f3f7c3db0e65c481dad5bcfddfb4.zip
gcc-b6df113247b9f3f7c3db0e65c481dad5bcfddfb4.tar.gz
gcc-b6df113247b9f3f7c3db0e65c481dad5bcfddfb4.tar.bz2
d: Merge upstream dmd d7772a2369, phobos 5748ca43f.
In upstream dmd, the compiler front-end and run-time have been merged together into one repository. Both dmd and libdruntime now track that. D front-end changes: - Deprecated `scope(failure)' blocks that contain `return' statements. - Deprecated using integers for `version' or `debug' conditions. - Deprecated returning a discarded void value from a function. - `new' can now allocate an associative array. D runtime changes: - Added avx512f detection to core.cpuid module. Phobos changes: - Changed std.experimental.logger.core.sharedLog to return shared(Logger). gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd d7772a2369. * dmd/VERSION: Bump version to v2.100.1. * d-codegen.cc (get_frameinfo): Check whether decision to generate closure changed since semantic finished. * d-lang.cc (d_handle_option): Remove handling of -fdebug=level and -fversion=level. * decl.cc (DeclVisitor::visit (VarDeclaration *)): Generate evaluation of noreturn variable initializers before throw. * expr.cc (ExprVisitor::visit (AssignExp *)): Don't generate assignment for noreturn types, only evaluate for side effects. * lang.opt (fdebug=): Undocument -fdebug=level. (fversion=): Undocument -fversion=level. libphobos/ChangeLog: * configure: Regenerate. * configure.ac (libtool_VERSION): Update to 4:0:0. * libdruntime/MERGE: Merge upstream druntime d7772a2369. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/internal/array/duplication.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 5748ca43f. * testsuite/libphobos.gc/nocollect.d:
Diffstat (limited to 'libphobos')
-rwxr-xr-xlibphobos/configure2
-rw-r--r--libphobos/configure.ac2
-rw-r--r--libphobos/libdruntime/MERGE4
-rw-r--r--libphobos/libdruntime/Makefile.am16
-rw-r--r--libphobos/libdruntime/Makefile.in19
-rw-r--r--libphobos/libdruntime/core/cpuid.d16
-rw-r--r--libphobos/libdruntime/core/int128.d2
-rw-r--r--libphobos/libdruntime/core/internal/array/appending.d28
-rw-r--r--libphobos/libdruntime/core/internal/array/duplication.d346
-rw-r--r--libphobos/libdruntime/core/internal/dassert.d2
-rw-r--r--libphobos/libdruntime/core/runtime.d2
-rw-r--r--libphobos/libdruntime/core/stdc/errno.d2
-rw-r--r--libphobos/libdruntime/core/stdc/stdio.d53
-rw-r--r--libphobos/libdruntime/core/stdc/wchar_.d90
-rw-r--r--libphobos/libdruntime/core/sys/darwin/mach/getsect.d1
-rw-r--r--libphobos/libdruntime/core/sys/dragonflybsd/string.d1
-rw-r--r--libphobos/libdruntime/core/sys/linux/sys/time.d1
-rw-r--r--libphobos/libdruntime/core/sys/linux/sys/xattr.d1
-rw-r--r--libphobos/libdruntime/core/sys/linux/tipc.d1
-rw-r--r--libphobos/libdruntime/core/sys/posix/signal.d79
-rw-r--r--libphobos/libdruntime/core/sys/posix/spawn.d2
-rw-r--r--libphobos/libdruntime/core/sys/posix/stdio.d2
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/select.d1
-rw-r--r--libphobos/libdruntime/core/sys/posix/time.d66
-rw-r--r--libphobos/libdruntime/core/sys/posix/ucontext.d1
-rw-r--r--libphobos/libdruntime/core/sys/solaris/sys/priocntl.d1
-rw-r--r--libphobos/libdruntime/core/sys/solaris/sys/procset.d1
-rw-r--r--libphobos/libdruntime/core/sys/windows/cguid.d1
-rw-r--r--libphobos/libdruntime/core/sys/windows/ntsecpkg.d1
-rw-r--r--libphobos/libdruntime/core/sys/windows/olectlid.d1
-rw-r--r--libphobos/libdruntime/core/sys/windows/shlguid.d1
-rw-r--r--libphobos/libdruntime/core/sys/windows/sspi.d1
-rw-r--r--libphobos/libdruntime/object.d340
-rw-r--r--libphobos/libdruntime/rt/dylib_fixes.c1
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/etc/c/curl.d18
-rw-r--r--libphobos/src/std/algorithm/comparison.d2
-rw-r--r--libphobos/src/std/algorithm/iteration.d15
-rw-r--r--libphobos/src/std/algorithm/searching.d12
-rw-r--r--libphobos/src/std/conv.d19
-rw-r--r--libphobos/src/std/experimental/checkedint.d2
-rw-r--r--libphobos/src/std/experimental/logger/core.d176
-rw-r--r--libphobos/src/std/experimental/logger/filelogger.d2
-rw-r--r--libphobos/src/std/experimental/logger/multilogger.d2
-rw-r--r--libphobos/src/std/file.d2
-rw-r--r--libphobos/src/std/format/internal/write.d6
-rw-r--r--libphobos/src/std/format/package.d24
-rw-r--r--libphobos/src/std/math/package.d1
-rw-r--r--libphobos/src/std/math/rounding.d28
-rw-r--r--libphobos/src/std/random.d67
-rw-r--r--libphobos/src/std/stdio.d17
-rw-r--r--libphobos/src/std/sumtype.d148
-rw-r--r--libphobos/src/std/typecons.d20
-rw-r--r--libphobos/src/std/uni/package.d8
-rw-r--r--libphobos/testsuite/libphobos.gc/nocollect.d2
55 files changed, 971 insertions, 690 deletions
diff --git a/libphobos/configure b/libphobos/configure
index 9da06f0..69d2d44 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -15554,7 +15554,7 @@ SPEC_PHOBOS_DEPS="$LIBS"
# Libdruntime / phobos soname version
-libtool_VERSION=3:0:0
+libtool_VERSION=4:0:0
# Set default flags (after DRUNTIME_WERROR!)
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index 31209ba..8bdf733 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -253,7 +253,7 @@ SPEC_PHOBOS_DEPS="$LIBS"
AC_SUBST(SPEC_PHOBOS_DEPS)
# Libdruntime / phobos soname version
-libtool_VERSION=3:0:0
+libtool_VERSION=4:0:0
AC_SUBST(libtool_VERSION)
# Set default flags (after DRUNTIME_WERROR!)
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 6e25a9d..c358b69 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-651389b52243dcadb338dd0c14dd27e7850cda8d
+d7772a236983ec37b92d21b28bad3cd2de57b945
The first line of this file holds the git revision number of the last
-merge done from the dlang/druntime repository.
+merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 56b332d..2e1e91d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -174,14 +174,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/internal/array/appending.d core/internal/array/capacity.d \
core/internal/array/casting.d core/internal/array/comparison.d \
core/internal/array/concatenation.d core/internal/array/construction.d \
- core/internal/array/equality.d core/internal/array/operations.d \
- core/internal/array/utils.d core/internal/atomic.d \
- core/internal/attributes.d core/internal/container/array.d \
- core/internal/container/common.d core/internal/container/hashtab.d \
- core/internal/container/treap.d core/internal/convert.d \
- core/internal/dassert.d core/internal/destruction.d \
- core/internal/entrypoint.d core/internal/gc/bits.d \
- core/internal/gc/impl/conservative/gc.d \
+ core/internal/array/duplication.d core/internal/array/equality.d \
+ core/internal/array/operations.d core/internal/array/utils.d \
+ core/internal/atomic.d core/internal/attributes.d \
+ core/internal/container/array.d core/internal/container/common.d \
+ core/internal/container/hashtab.d core/internal/container/treap.d \
+ core/internal/convert.d core/internal/dassert.d \
+ core/internal/destruction.d core/internal/entrypoint.d \
+ core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
core/internal/gc/os.d core/internal/gc/pooltable.d \
core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 24865fb..de6656c 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -196,6 +196,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
core/internal/array/comparison.lo \
core/internal/array/concatenation.lo \
core/internal/array/construction.lo \
+ core/internal/array/duplication.lo \
core/internal/array/equality.lo \
core/internal/array/operations.lo core/internal/array/utils.lo \
core/internal/atomic.lo core/internal/attributes.lo \
@@ -841,14 +842,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/internal/array/appending.d core/internal/array/capacity.d \
core/internal/array/casting.d core/internal/array/comparison.d \
core/internal/array/concatenation.d core/internal/array/construction.d \
- core/internal/array/equality.d core/internal/array/operations.d \
- core/internal/array/utils.d core/internal/atomic.d \
- core/internal/attributes.d core/internal/container/array.d \
- core/internal/container/common.d core/internal/container/hashtab.d \
- core/internal/container/treap.d core/internal/convert.d \
- core/internal/dassert.d core/internal/destruction.d \
- core/internal/entrypoint.d core/internal/gc/bits.d \
- core/internal/gc/impl/conservative/gc.d \
+ core/internal/array/duplication.d core/internal/array/equality.d \
+ core/internal/array/operations.d core/internal/array/utils.d \
+ core/internal/atomic.d core/internal/attributes.d \
+ core/internal/container/array.d core/internal/container/common.d \
+ core/internal/container/hashtab.d core/internal/container/treap.d \
+ core/internal/convert.d core/internal/dassert.d \
+ core/internal/destruction.d core/internal/entrypoint.d \
+ core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d \
core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d \
core/internal/gc/os.d core/internal/gc/pooltable.d \
core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d \
@@ -1208,6 +1209,8 @@ core/internal/array/concatenation.lo: \
core/internal/array/$(am__dirstamp)
core/internal/array/construction.lo: \
core/internal/array/$(am__dirstamp)
+core/internal/array/duplication.lo: \
+ core/internal/array/$(am__dirstamp)
core/internal/array/equality.lo: core/internal/array/$(am__dirstamp)
core/internal/array/operations.lo: \
core/internal/array/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/cpuid.d b/libphobos/libdruntime/core/cpuid.d
index e31f776..1c2ac06 100644
--- a/libphobos/libdruntime/core/cpuid.d
+++ b/libphobos/libdruntime/core/cpuid.d
@@ -170,6 +170,8 @@ public:
bool hle() {return _hle;}
/// Is RTM (restricted transactional memory) supported
bool rtm() {return _rtm;}
+ /// Is AVX512F supported
+ bool avx512f() {return _avx512f;}
/// Is rdseed supported
bool hasRdseed() {return _hasRdseed;}
/// Is SHA supported
@@ -279,6 +281,7 @@ private immutable
bool _avx2;
bool _hle;
bool _rtm;
+ bool _avx512f;
bool _hasRdseed;
bool _hasSha;
bool _amd3dnow;
@@ -389,6 +392,7 @@ CpuFeatures* getCpuFeatures() @nogc nothrow
enum : uint
{
FSGSBASE_BIT = 1 << 0,
+ SGX_BIT = 1 << 2,
BMI1_BIT = 1 << 3,
HLE_BIT = 1 << 4,
AVX2_BIT = 1 << 5,
@@ -397,8 +401,19 @@ CpuFeatures* getCpuFeatures() @nogc nothrow
ERMS_BIT = 1 << 9,
INVPCID_BIT = 1 << 10,
RTM_BIT = 1 << 11,
+ AVX512F_BIT = 1 << 16,
+ AVX512DQ_BIT = 1 << 17,
RDSEED_BIT = 1 << 18,
+ ADX_BIT = 1 << 19,
+ AVX512IFMA_BIT = 1 << 21,
+ CLFLUSHOPT_BIT = 1 << 23,
+ CLWB_BIT = 1 << 24,
+ AVX512PF_BIT = 1 << 26,
+ AVX512ER_BIT = 1 << 27,
+ AVX512CD_BIT = 1 << 28,
SHA_BIT = 1 << 29,
+ AVX512BW_BIT = 1 << 30,
+ AVX512VL_BIT = 1 << 31,
}
// feature flags XFEATURES_ENABLED_MASK
enum : ulong
@@ -1122,6 +1137,7 @@ shared static this()
_avx2 = avx && (cf.extfeatures & AVX2_BIT) != 0;
_hle = (cf.extfeatures & HLE_BIT) != 0;
_rtm = (cf.extfeatures & RTM_BIT) != 0;
+ _avx512f = (cf.extfeatures & AVX512F_BIT) != 0;
_hasRdseed = (cf.extfeatures&RDSEED_BIT)!=0;
_hasSha = (cf.extfeatures&SHA_BIT)!=0;
_amd3dnow = (cf.amdfeatures&AMD_3DNOW_BIT)!=0;
diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d
index e4326fd..46eb9b2 100644
--- a/libphobos/libdruntime/core/int128.d
+++ b/libphobos/libdruntime/core/int128.d
@@ -943,5 +943,3 @@ unittest
assert(rol(C7_9, 1) == rol1(C7_9));
assert(ror(C7_9, 1) == ror1(C7_9));
}
-
-
diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d
index d416efe..616d27c 100644
--- a/libphobos/libdruntime/core/internal/array/appending.d
+++ b/libphobos/libdruntime/core/internal/array/appending.d
@@ -30,26 +30,14 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
* Returns:
* The new value of `px`
* Bugs:
- * This function template was ported from a much older runtime hook that bypassed safety,
- * purity, and throwabilty checks. To prevent breaking existing code, this function template
- * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
+ * This function template was ported from a much older runtime hook that bypassed safety,
+ * purity, and throwabilty checks. To prevent breaking existing code, this function template
+ * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
*/
- static if (isCopyingNothrow!T) // `nothrow` deduction doesn't work, so this is needed
- ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
- {
- pragma(inline, false);
-
- mixin(_d_arrayappendcTXBody);
- }
- else
- ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
- {
- pragma(inline, false);
-
- mixin(_d_arrayappendcTXBody);
- }
-
- private enum _d_arrayappendcTXBody = q{
+ ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
+ {
+ // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718
+ pragma(inline, false);
version (D_TypeInfo)
{
auto ti = typeid(Tarr);
@@ -64,7 +52,7 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
}
else
assert(0, "Cannot append arrays if compiling without support for runtime type information!");
- };
+ }
/**
* TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl).
diff --git a/libphobos/libdruntime/core/internal/array/duplication.d b/libphobos/libdruntime/core/internal/array/duplication.d
new file mode 100644
index 0000000..41dfab6
--- /dev/null
+++ b/libphobos/libdruntime/core/internal/array/duplication.d
@@ -0,0 +1,346 @@
+/**
+The `.dup` and `.idup` properties for Associative Arrays and Dynamic Arrays
+
+Copyright: Copyright Digital Mars 2000 - 2022.
+License: Distributed under the $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ (See accompanying file LICENSE)
+Source: $(DRUNTIMESRC core/internal/_array/_duplication.d)
+*/
+module core.internal.array.duplication;
+
+private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
+
+U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
+{
+ if (__ctfe)
+ return _dupCtfe!(T, U)(a);
+
+ import core.stdc.string : memcpy;
+ auto arr = _d_newarrayU(typeid(T[]), a.length);
+ memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
+ return *cast(U[]*) &arr;
+}
+
+U[] _dupCtfe(T, U)(scope T[] a)
+{
+ static if (is(T : void))
+ assert(0, "Cannot dup a void[] array at compile time.");
+ else
+ {
+ U[] res;
+ foreach (ref e; a)
+ res ~= e;
+ return res;
+ }
+}
+
+U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
+{
+ // note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
+ // has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
+ if (__ctfe)
+ return _dupCtfe!(T, U)(a);
+
+ import core.lifetime: copyEmplace;
+ U[] res = () @trusted {
+ auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
+ size_t i;
+ scope (failure)
+ {
+ import core.internal.lifetime: emplaceInitializer;
+ // Initialize all remaining elements to not destruct garbage
+ foreach (j; i .. a.length)
+ emplaceInitializer(cast() arr[j]);
+ }
+ for (; i < a.length; i++)
+ {
+ copyEmplace(a.ptr[i], arr[i]);
+ }
+ return cast(U[])(arr[0..a.length]);
+ } ();
+
+ return res;
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=22107
+@safe unittest
+{
+ static int i;
+ @safe struct S
+ {
+ this(this) { i++; }
+ }
+
+ void fun(scope S[] values...) @safe
+ {
+ values.dup;
+ }
+}
+
+@safe unittest
+{
+ static struct S1 { int* p; }
+ static struct S2 { @disable this(); }
+ static struct S3 { @disable this(this); }
+
+ int dg1() pure nothrow @safe
+ {
+ {
+ char[] m;
+ string i;
+ m = m.dup;
+ i = i.idup;
+ m = i.dup;
+ i = m.idup;
+ }
+ {
+ S1[] m;
+ immutable(S1)[] i;
+ m = m.dup;
+ i = i.idup;
+ static assert(!is(typeof(m.idup)));
+ static assert(!is(typeof(i.dup)));
+ }
+ {
+ S3[] m;
+ immutable(S3)[] i;
+ static assert(!is(typeof(m.dup)));
+ static assert(!is(typeof(i.idup)));
+ }
+ {
+ shared(S1)[] m;
+ m = m.dup;
+ static assert(!is(typeof(m.idup)));
+ }
+ {
+ int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
+ }
+ return 1;
+ }
+
+ int dg2() pure nothrow @safe
+ {
+ {
+ S2[] m = [S2.init, S2.init];
+ immutable(S2)[] i = [S2.init, S2.init];
+ m = m.dup;
+ m = i.dup;
+ i = m.idup;
+ i = i.idup;
+ }
+ return 2;
+ }
+
+ enum a = dg1();
+ enum b = dg2();
+ assert(dg1() == a);
+ assert(dg2() == b);
+}
+
+@system unittest
+{
+ static struct Sunpure { this(this) @safe nothrow {} }
+ static struct Sthrow { this(this) @safe pure {} }
+ static struct Sunsafe { this(this) @system pure nothrow {} }
+ static struct Snocopy { @disable this(this); }
+
+ [].dup!Sunpure;
+ [].dup!Sthrow;
+ cast(void) [].dup!Sunsafe;
+ static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
+ static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
+ static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
+ static assert(!__traits(compiles, () { [].dup!Snocopy; }));
+
+ [].idup!Sunpure;
+ [].idup!Sthrow;
+ [].idup!Sunsafe;
+ static assert(!__traits(compiles, () pure { [].idup!Sunpure; }));
+ static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
+ static assert(!__traits(compiles, () @safe { [].idup!Sunsafe; }));
+ static assert(!__traits(compiles, () { [].idup!Snocopy; }));
+}
+
+@safe unittest
+{
+ // test that the copy-constructor is called with .dup
+ static struct ArrElem
+ {
+ int a;
+ this(int a)
+ {
+ this.a = a;
+ }
+ this(ref const ArrElem)
+ {
+ a = 2;
+ }
+ this(ref ArrElem) immutable
+ {
+ a = 3;
+ }
+ }
+
+ auto arr = [ArrElem(1), ArrElem(1)];
+
+ ArrElem[] b = arr.dup;
+ assert(b[0].a == 2 && b[1].a == 2);
+
+ immutable ArrElem[] c = arr.idup;
+ assert(c[0].a == 3 && c[1].a == 3);
+}
+
+@system unittest
+{
+ static struct Sunpure { this(ref const typeof(this)) @safe nothrow {} }
+ static struct Sthrow { this(ref const typeof(this)) @safe pure {} }
+ static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
+ [].dup!Sunpure;
+ [].dup!Sthrow;
+ cast(void) [].dup!Sunsafe;
+ static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
+ static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
+ static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
+
+ // for idup to work on structs that have copy constructors, it is necessary
+ // that the struct defines a copy constructor that creates immutable objects
+ static struct ISunpure { this(ref const typeof(this)) immutable @safe nothrow {} }
+ static struct ISthrow { this(ref const typeof(this)) immutable @safe pure {} }
+ static struct ISunsafe { this(ref const typeof(this)) immutable @system pure nothrow {} }
+ [].idup!ISunpure;
+ [].idup!ISthrow;
+ [].idup!ISunsafe;
+ static assert(!__traits(compiles, () pure { [].idup!ISunpure; }));
+ static assert(!__traits(compiles, () nothrow { [].idup!ISthrow; }));
+ static assert(!__traits(compiles, () @safe { [].idup!ISunsafe; }));
+}
+
+@safe unittest
+{
+ static int*[] pureFoo() pure { return null; }
+ { char[] s; immutable x = s.dup; }
+ { immutable x = (cast(int*[])null).dup; }
+ { immutable x = pureFoo(); }
+ { immutable x = pureFoo().dup; }
+}
+
+@safe unittest
+{
+ auto a = [1, 2, 3];
+ auto b = a.dup;
+ debug(SENTINEL) {} else
+ assert(b.capacity >= 3);
+}
+
+@system unittest
+{
+ // Bugzilla 12580
+ void[] m = [0];
+ shared(void)[] s = [cast(shared)1];
+ immutable(void)[] i = [cast(immutable)2];
+
+ s = s.dup;
+ static assert(is(typeof(s.dup) == shared(void)[]));
+
+ m = i.dup;
+ i = m.dup;
+ i = i.idup;
+ i = m.idup;
+ i = s.idup;
+ i = s.dup;
+ static assert(!__traits(compiles, m = s.dup));
+}
+
+@safe unittest
+{
+ // Bugzilla 13809
+ static struct S
+ {
+ this(this) {}
+ ~this() {}
+ }
+
+ S[] arr;
+ auto a = arr.dup;
+}
+
+@system unittest
+{
+ // Bugzilla 16504
+ static struct S
+ {
+ __gshared int* gp;
+ int* p;
+ // postblit and hence .dup could escape
+ this(this) { gp = p; }
+ }
+
+ int p;
+ scope S[1] arr = [S(&p)];
+ auto a = arr.dup; // dup does escape
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=21983
+// dup/idup destroys partially constructed arrays on failure
+@safe unittest
+{
+ static struct SImpl(bool postblit)
+ {
+ int num;
+ long l = 0xDEADBEEF;
+
+ static if (postblit)
+ {
+ this(this)
+ {
+ if (this.num == 3)
+ throw new Exception("");
+ }
+ }
+ else
+ {
+ this(scope ref const SImpl other)
+ {
+ if (other.num == 3)
+ throw new Exception("");
+
+ this.num = other.num;
+ this.l = other.l;
+ }
+ }
+
+ ~this() @trusted
+ {
+ if (l != 0xDEADBEEF)
+ {
+ import core.stdc.stdio;
+ printf("Unexpected value: %lld\n", l);
+ fflush(stdout);
+ assert(false);
+ }
+ }
+ }
+
+ alias Postblit = SImpl!true;
+ alias Copy = SImpl!false;
+
+ static int test(S)()
+ {
+ S[4] arr = [ S(1), S(2), S(3), S(4) ];
+ try
+ {
+ arr.dup();
+ assert(false);
+ }
+ catch (Exception)
+ {
+ return 1;
+ }
+ }
+
+ static assert(test!Postblit());
+ assert(test!Postblit());
+
+ static assert(test!Copy());
+ assert(test!Copy());
+}
diff --git a/libphobos/libdruntime/core/internal/dassert.d b/libphobos/libdruntime/core/internal/dassert.d
index 2c51b86..07486c2 100644
--- a/libphobos/libdruntime/core/internal/dassert.d
+++ b/libphobos/libdruntime/core/internal/dassert.d
@@ -14,7 +14,7 @@
*
* Copyright: D Language Foundation 2018 - 2020
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/internal/dassert.d, _dassert.d)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/internal/dassert.d, _dassert.d)
* Documentation: https://dlang.org/phobos/core_internal_dassert.html
*/
module core.internal.dassert;
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index d1378af..75e671c 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -4,7 +4,7 @@
* Copyright: Copyright Sean Kelly 2005 - 2009.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Sean Kelly
- * Source: $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/runtime.d, _runtime.d)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/runtime.d, _runtime.d)
* Documentation: https://dlang.org/phobos/core_runtime.html
*/
diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d
index 24b4138..c992a5f 100644
--- a/libphobos/libdruntime/core/stdc/errno.d
+++ b/libphobos/libdruntime/core/stdc/errno.d
@@ -8,7 +8,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Alex Rønne Petersen
- * Source: https://github.com/dlang/druntime/blob/master/src/core/stdc/errno.d
+ * Source: https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/errno.d
* Standards: ISO/IEC 9899:1999 (E)
*/
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index 2e83811..fc98350 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -9,7 +9,7 @@
* (See accompanying file LICENSE)
* Authors: Sean Kelly,
* Alex Rønne Petersen
- * Source: https://github.com/dlang/druntime/blob/master/src/core/stdc/stdio.d
+ * Source: https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/stdio.d
* Standards: ISO/IEC 9899:1999 (E)
*/
@@ -1286,6 +1286,57 @@ version (MinGW)
///
alias __mingw_scanf scanf;
}
+else version (CRuntime_Glibc)
+{
+ ///
+ pragma(printf)
+ int fprintf(FILE* stream, scope const char* format, scope const ...);
+ ///
+ pragma(scanf)
+ int __isoc99_fscanf(FILE* stream, scope const char* format, scope ...);
+ ///
+ alias fscanf = __isoc99_fscanf;
+ ///
+ pragma(printf)
+ int sprintf(scope char* s, scope const char* format, scope const ...);
+ ///
+ pragma(scanf)
+ int __isoc99_sscanf(scope const char* s, scope const char* format, scope ...);
+ ///
+ alias sscanf = __isoc99_sscanf;
+ ///
+ pragma(printf)
+ int vfprintf(FILE* stream, scope const char* format, va_list arg);
+ ///
+ pragma(scanf)
+ int __isoc99_vfscanf(FILE* stream, scope const char* format, va_list arg);
+ ///
+ alias vfscanf = __isoc99_vfscanf;
+ ///
+ pragma(printf)
+ int vsprintf(scope char* s, scope const char* format, va_list arg);
+ ///
+ pragma(scanf)
+ int __isoc99_vsscanf(scope const char* s, scope const char* format, va_list arg);
+ ///
+ alias vsscanf = __isoc99_vsscanf;
+ ///
+ pragma(printf)
+ int vprintf(scope const char* format, va_list arg);
+ ///
+ pragma(scanf)
+ int __isoc99_vscanf(scope const char* format, va_list arg);
+ ///
+ alias vscanf = __isoc99_vscanf;
+ ///
+ pragma(printf)
+ int printf(scope const char* format, scope const ...);
+ ///
+ pragma(scanf)
+ int __isoc99_scanf(scope const char* format, scope ...);
+ ///
+ alias scanf = __isoc99_scanf;
+}
else
{
///
diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d
index e8fb94b..d087029 100644
--- a/libphobos/libdruntime/core/stdc/wchar_.d
+++ b/libphobos/libdruntime/core/stdc/wchar_.d
@@ -127,30 +127,72 @@ alias wchar_t wint_t;
///
enum wchar_t WEOF = 0xFFFF;
-///
-int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
-///
-int fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
-///
-int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
-///
-int swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
-///
-int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
-///
-int vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
-///
-int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
-///
-int vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
-///
-int vwprintf(const scope wchar_t* format, va_list arg);
-///
-int vwscanf(const scope wchar_t* format, va_list arg);
-///
-int wprintf(const scope wchar_t* format, scope const ...);
-///
-int wscanf(const scope wchar_t* format, scope ...);
+version (CRuntime_Glibc)
+{
+ ///
+ int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
+ ///
+ int __isoc99_fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
+ ///
+ alias fwscanf = __isoc99_fwscanf;
+ ///
+ int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
+ ///
+ int __isoc99_swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
+ ///
+ alias swscanf = __isoc99_swscanf;
+ ///
+ int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
+ ///
+ int __isoc99_vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
+ ///
+ alias vfwscanf = __isoc99_vfwscanf;
+ ///
+ int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
+ ///
+ int __isoc99_vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
+ ///
+ alias vswscanf = __isoc99_vswscanf;
+ ///
+ int vwprintf(const scope wchar_t* format, va_list arg);
+ ///
+ int __isoc99_vwscanf(const scope wchar_t* format, va_list arg);
+ ///
+ alias vwscanf = __isoc99_vwscanf;
+ ///
+ int wprintf(const scope wchar_t* format, scope const ...);
+ ///
+ int __isoc99_wscanf(const scope wchar_t* format, scope ...);
+ ///
+ alias wscanf = __isoc99_wscanf;
+}
+else
+{
+ ///
+ int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
+ ///
+ int fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
+ ///
+ int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
+ ///
+ int swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
+ ///
+ int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
+ ///
+ int vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
+ ///
+ int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
+ ///
+ int vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
+ ///
+ int vwprintf(const scope wchar_t* format, va_list arg);
+ ///
+ int vwscanf(const scope wchar_t* format, va_list arg);
+ ///
+ int wprintf(const scope wchar_t* format, scope const ...);
+ ///
+ int wscanf(const scope wchar_t* format, scope ...);
+}
// No unsafe pointer manipulation.
@trusted
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/getsect.d b/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
index fd1a8e4..dc42a2d 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
@@ -468,4 +468,3 @@ const(section)* getsectbynamefromheaderwithswap_64(
const scope char* section,
int fSwap
);
-
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/string.d b/libphobos/libdruntime/core/sys/dragonflybsd/string.d
index 4b84227..1a85ba6 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/string.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/string.d
@@ -19,4 +19,3 @@ static if (__BSD_VISIBLE)
{
pure void* memmem(return scope const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
}
-
diff --git a/libphobos/libdruntime/core/sys/linux/sys/time.d b/libphobos/libdruntime/core/sys/linux/sys/time.d
index 6ea626e..4b56229 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/time.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/time.d
@@ -65,4 +65,3 @@ extern (D) pure @safe @nogc nothrow {
}
}
-
diff --git a/libphobos/libdruntime/core/sys/linux/sys/xattr.d b/libphobos/libdruntime/core/sys/linux/sys/xattr.d
index 2f8d3f37..6446ff8 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/xattr.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/xattr.d
@@ -66,4 +66,3 @@ ssize_t flistxattr (int __fd, char *list, size_t size);
int removexattr (const scope char *path, const scope char *name);
int lremovexattr (const scope char *path, const scope char *name);
int fremovexattr (int fd, const scope char *name);
-
diff --git a/libphobos/libdruntime/core/sys/linux/tipc.d b/libphobos/libdruntime/core/sys/linux/tipc.d
index 3246e62..4d5d886 100644
--- a/libphobos/libdruntime/core/sys/linux/tipc.d
+++ b/libphobos/libdruntime/core/sys/linux/tipc.d
@@ -208,4 +208,3 @@ enum: int
TIPC_DEST_DROPPABLE = 129,
TIPC_CONN_TIMEOUT = 130,
}
-
diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d
index 68aee98..542e83a 100644
--- a/libphobos/libdruntime/core/sys/posix/signal.d
+++ b/libphobos/libdruntime/core/sys/posix/signal.d
@@ -14,7 +14,7 @@ module core.sys.posix.signal;
import core.sys.posix.config;
public import core.stdc.signal;
public import core.sys.posix.sys.types; // for pid_t
-//public import core.sys.posix.time; // for timespec, now defined here
+public import core.sys.posix.time; // for timespec
version (OSX)
version = Darwin;
@@ -2805,83 +2805,6 @@ else
}
//
-// Timer (TMR)
-//
-/*
-NOTE: This should actually be defined in core.sys.posix.time.
- It is defined here instead to break a circular import.
-
-struct timespec
-{
- time_t tv_sec;
- int tv_nsec;
-}
-*/
-
-version (linux)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-}
-else version (Darwin)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-}
-else version (FreeBSD)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-}
-else version (NetBSD)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-}
-else version (OpenBSD)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-}
-else version (DragonFlyBSD)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-}
-else version (Solaris)
-{
- struct timespec
- {
- time_t tv_sec;
- c_long tv_nsec;
- }
-
- alias timespec timestruc_t;
-}
-else
-{
- static assert(false, "Unsupported platform");
-}
-
-//
// Realtime Signals (RTS)
//
/*
diff --git a/libphobos/libdruntime/core/sys/posix/spawn.d b/libphobos/libdruntime/core/sys/posix/spawn.d
index cfa3a40..2064962 100644
--- a/libphobos/libdruntime/core/sys/posix/spawn.d
+++ b/libphobos/libdruntime/core/sys/posix/spawn.d
@@ -4,7 +4,7 @@
* Copyright: Copyright (C) 2018 by The D Language Foundation, All Rights Reserved
* Authors: Petar Kirov
* License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/sys/posix/spawn.d, _spawn.d)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/sys/posix/spawn.d, _spawn.d)
* Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
*/
module core.sys.posix.spawn;
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index 077838d..d0d3d60 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -487,7 +487,7 @@ else version (CRuntime_Musl)
version (HaveMemstream)
{
- FILE* fmemopen(const scope void* buf, in size_t size, const scope char* mode);
+ FILE* fmemopen(const scope void* buf, size_t size, const scope char* mode);
FILE* open_memstream(char** ptr, size_t* sizeloc);
version (CRuntime_UClibc) {} else
FILE* open_wmemstream(wchar_t** ptr, size_t* sizeloc);
diff --git a/libphobos/libdruntime/core/sys/posix/sys/select.d b/libphobos/libdruntime/core/sys/posix/sys/select.d
index 2a659c3..925976d 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/select.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/select.d
@@ -608,4 +608,3 @@ pure unittest
assert(!FD_ISSET(i, &fd));
}
}
-
diff --git a/libphobos/libdruntime/core/sys/posix/time.d b/libphobos/libdruntime/core/sys/posix/time.d
index a9be87c8..ff3a3c4 100644
--- a/libphobos/libdruntime/core/sys/posix/time.d
+++ b/libphobos/libdruntime/core/sys/posix/time.d
@@ -167,9 +167,6 @@ else
CLOCK_PROCESS_CPUTIME_ID (TMR|CPT)
CLOCK_THREAD_CPUTIME_ID (TMR|TCT)
-NOTE: timespec must be defined in core.sys.posix.signal to break
- a circular import.
-
struct timespec
{
time_t tv_sec;
@@ -199,6 +196,69 @@ int timer_getoverrun(timer_t);
int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
*/
+version (linux)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+}
+else version (Darwin)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+}
+else version (FreeBSD)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+}
+else version (NetBSD)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+}
+else version (OpenBSD)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+}
+else version (DragonFlyBSD)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+}
+else version (Solaris)
+{
+ struct timespec
+ {
+ time_t tv_sec;
+ c_long tv_nsec;
+ }
+
+ alias timespec timestruc_t;
+}
+else
+{
+ static assert(false, "Unsupported platform");
+}
+
version (CRuntime_Glibc)
{
enum CLOCK_PROCESS_CPUTIME_ID = 2;
diff --git a/libphobos/libdruntime/core/sys/posix/ucontext.d b/libphobos/libdruntime/core/sys/posix/ucontext.d
index 20297f5..e8c2f87 100644
--- a/libphobos/libdruntime/core/sys/posix/ucontext.d
+++ b/libphobos/libdruntime/core/sys/posix/ucontext.d
@@ -1628,4 +1628,3 @@ version (Solaris)
int addrtosymstr(uintptr_t, char*, int);
int printstack(int);
}
-
diff --git a/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d b/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d
index bfbf3ee..c56be3b 100644
--- a/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d
+++ b/libphobos/libdruntime/core/sys/solaris/sys/priocntl.d
@@ -113,4 +113,3 @@ struct pcadmin_t
id_t pc_cid;
caddr_t pc_cladmin;
}
-
diff --git a/libphobos/libdruntime/core/sys/solaris/sys/procset.d b/libphobos/libdruntime/core/sys/solaris/sys/procset.d
index 43fa997..8bd9115 100644
--- a/libphobos/libdruntime/core/sys/solaris/sys/procset.d
+++ b/libphobos/libdruntime/core/sys/solaris/sys/procset.d
@@ -50,4 +50,3 @@ void setprocset(ref procset_t psp, idop_t op, idtype_t ltype, id_t lid, idtype_t
psp.p_ridtype = rtype;
psp.p_rid = rid;
}
-
diff --git a/libphobos/libdruntime/core/sys/windows/cguid.d b/libphobos/libdruntime/core/sys/windows/cguid.d
index 0afbc42..d0a8fb9 100644
--- a/libphobos/libdruntime/core/sys/windows/cguid.d
+++ b/libphobos/libdruntime/core/sys/windows/cguid.d
@@ -10,4 +10,3 @@ module core.sys.windows.cguid;
version (Windows):
import core.sys.windows.basetyps;
-
diff --git a/libphobos/libdruntime/core/sys/windows/ntsecpkg.d b/libphobos/libdruntime/core/sys/windows/ntsecpkg.d
index d4c93d7..d8c5e95 100644
--- a/libphobos/libdruntime/core/sys/windows/ntsecpkg.d
+++ b/libphobos/libdruntime/core/sys/windows/ntsecpkg.d
@@ -444,4 +444,3 @@ alias NTSTATUS function(ULONG, PULONG,
PSECPKG_FUNCTION_TABLE *, PULONG) SpLsaModeInitializeFn;
alias NTSTATUS function(ULONG, PULONG,
PSECPKG_USER_FUNCTION_TABLE *, PULONG) SpUserModeInitializeFn;
-
diff --git a/libphobos/libdruntime/core/sys/windows/olectlid.d b/libphobos/libdruntime/core/sys/windows/olectlid.d
index 8bbe657..b58c14a 100644
--- a/libphobos/libdruntime/core/sys/windows/olectlid.d
+++ b/libphobos/libdruntime/core/sys/windows/olectlid.d
@@ -10,4 +10,3 @@ module core.sys.windows.olectlid;
version (Windows):
import core.sys.windows.basetyps;
-
diff --git a/libphobos/libdruntime/core/sys/windows/shlguid.d b/libphobos/libdruntime/core/sys/windows/shlguid.d
index 1c0c98f..e0c1af1 100644
--- a/libphobos/libdruntime/core/sys/windows/shlguid.d
+++ b/libphobos/libdruntime/core/sys/windows/shlguid.d
@@ -16,4 +16,3 @@ import core.sys.windows.basetyps, core.sys.windows.w32api;
// I think this is just a helper macro for other win32 headers?
//MACRO #define DEFINE_SHLGUID(n,l,w1,w2) DEFINE_GUID(n,l,w1,w2,0xC0,0,0,0,0,0,0,0x46)
-
diff --git a/libphobos/libdruntime/core/sys/windows/sspi.d b/libphobos/libdruntime/core/sys/windows/sspi.d
index 07a2596..21e982d 100644
--- a/libphobos/libdruntime/core/sys/windows/sspi.d
+++ b/libphobos/libdruntime/core/sys/windows/sspi.d
@@ -380,4 +380,3 @@ version (Unicode) {
alias QUERY_SECURITY_PACKAGE_INFO_FN_A QUERY_SECURITY_PACKAGE_INFO_FN;
alias INIT_SECURITY_INTERFACE_A INIT_SECURITY_INTERFACE;
}
-
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index fe65c09..8ef65489 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -3765,6 +3765,7 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
if (!is(const(T) : T))
{
import core.internal.traits : Unconst;
+ import core.internal.array.duplication : _dup;
static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
" to "~Unconst!T.stringof~" in dup.");
@@ -3786,6 +3787,7 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
@property T[] dup(T)(const(T)[] a)
if (is(const(T) : T))
{
+ import core.internal.array.duplication : _dup;
return _dup!(const(T), T)(a);
}
@@ -3793,6 +3795,7 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
/// Provide the .idup array property.
@property immutable(T)[] idup(T)(T[] a)
{
+ import core.internal.array.duplication : _dup;
static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
" to immutable in idup.");
return _dup!(T, immutable(T))(a);
@@ -3813,73 +3816,6 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr,
assert(s == "abc");
}
-private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
-{
- if (__ctfe)
- return _dupCtfe!(T, U)(a);
-
- import core.stdc.string : memcpy;
- auto arr = _d_newarrayU(typeid(T[]), a.length);
- memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
- return *cast(U[]*) &arr;
-}
-
-private U[] _dupCtfe(T, U)(scope T[] a)
-{
- static if (is(T : void))
- assert(0, "Cannot dup a void[] array at compile time.");
- else
- {
- U[] res;
- foreach (ref e; a)
- res ~= e;
- return res;
- }
-}
-
-private U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
-{
- // note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
- // has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
- if (__ctfe)
- return _dupCtfe!(T, U)(a);
-
- import core.lifetime: copyEmplace;
- U[] res = () @trusted {
- auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
- size_t i;
- scope (failure)
- {
- import core.internal.lifetime: emplaceInitializer;
- // Initialize all remaining elements to not destruct garbage
- foreach (j; i .. a.length)
- emplaceInitializer(cast() arr[j]);
- }
- for (; i < a.length; i++)
- {
- copyEmplace(a.ptr[i], arr[i]);
- }
- return cast(U[])(arr[0..a.length]);
- } ();
-
- return res;
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=22107
-@safe unittest
-{
- static int i;
- @safe struct S
- {
- this(this) { i++; }
- }
-
- void fun(scope S[] values...) @safe
- {
- values.dup;
- }
-}
-
// HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
// necessary for now to prevent breaking code.
private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
@@ -4067,8 +4003,6 @@ auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system
assert(is(typeof(b3) == immutable(int[])));
}
-private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
-
private void _doPostblit(T)(T[] arr)
{
// infer static postblit type, run postblit if any
@@ -4085,274 +4019,6 @@ private void _doPostblit(T)(T[] arr)
}
}
-@safe unittest
-{
- static struct S1 { int* p; }
- static struct S2 { @disable this(); }
- static struct S3 { @disable this(this); }
-
- int dg1() pure nothrow @safe
- {
- {
- char[] m;
- string i;
- m = m.dup;
- i = i.idup;
- m = i.dup;
- i = m.idup;
- }
- {
- S1[] m;
- immutable(S1)[] i;
- m = m.dup;
- i = i.idup;
- static assert(!is(typeof(m.idup)));
- static assert(!is(typeof(i.dup)));
- }
- {
- S3[] m;
- immutable(S3)[] i;
- static assert(!is(typeof(m.dup)));
- static assert(!is(typeof(i.idup)));
- }
- {
- shared(S1)[] m;
- m = m.dup;
- static assert(!is(typeof(m.idup)));
- }
- {
- int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
- }
- return 1;
- }
-
- int dg2() pure nothrow @safe
- {
- {
- S2[] m = [S2.init, S2.init];
- immutable(S2)[] i = [S2.init, S2.init];
- m = m.dup;
- m = i.dup;
- i = m.idup;
- i = i.idup;
- }
- return 2;
- }
-
- enum a = dg1();
- enum b = dg2();
- assert(dg1() == a);
- assert(dg2() == b);
-}
-
-@system unittest
-{
- static struct Sunpure { this(this) @safe nothrow {} }
- static struct Sthrow { this(this) @safe pure {} }
- static struct Sunsafe { this(this) @system pure nothrow {} }
- static struct Snocopy { @disable this(this); }
-
- [].dup!Sunpure;
- [].dup!Sthrow;
- cast(void) [].dup!Sunsafe;
- static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
- static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
- static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
- static assert(!__traits(compiles, () { [].dup!Snocopy; }));
-
- [].idup!Sunpure;
- [].idup!Sthrow;
- [].idup!Sunsafe;
- static assert(!__traits(compiles, () pure { [].idup!Sunpure; }));
- static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
- static assert(!__traits(compiles, () @safe { [].idup!Sunsafe; }));
- static assert(!__traits(compiles, () { [].idup!Snocopy; }));
-}
-
-@safe unittest
-{
- // test that the copy-constructor is called with .dup
- static struct ArrElem
- {
- int a;
- this(int a)
- {
- this.a = a;
- }
- this(ref const ArrElem)
- {
- a = 2;
- }
- this(ref ArrElem) immutable
- {
- a = 3;
- }
- }
-
- auto arr = [ArrElem(1), ArrElem(1)];
-
- ArrElem[] b = arr.dup;
- assert(b[0].a == 2 && b[1].a == 2);
-
- immutable ArrElem[] c = arr.idup;
- assert(c[0].a == 3 && c[1].a == 3);
-}
-
-@system unittest
-{
- static struct Sunpure { this(ref const typeof(this)) @safe nothrow {} }
- static struct Sthrow { this(ref const typeof(this)) @safe pure {} }
- static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
- [].dup!Sunpure;
- [].dup!Sthrow;
- cast(void) [].dup!Sunsafe;
- static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
- static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
- static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
-
- // for idup to work on structs that have copy constructors, it is necessary
- // that the struct defines a copy constructor that creates immutable objects
- static struct ISunpure { this(ref const typeof(this)) immutable @safe nothrow {} }
- static struct ISthrow { this(ref const typeof(this)) immutable @safe pure {} }
- static struct ISunsafe { this(ref const typeof(this)) immutable @system pure nothrow {} }
- [].idup!ISunpure;
- [].idup!ISthrow;
- [].idup!ISunsafe;
- static assert(!__traits(compiles, () pure { [].idup!ISunpure; }));
- static assert(!__traits(compiles, () nothrow { [].idup!ISthrow; }));
- static assert(!__traits(compiles, () @safe { [].idup!ISunsafe; }));
-}
-
-@safe unittest
-{
- static int*[] pureFoo() pure { return null; }
- { char[] s; immutable x = s.dup; }
- { immutable x = (cast(int*[])null).dup; }
- { immutable x = pureFoo(); }
- { immutable x = pureFoo().dup; }
-}
-
-@safe unittest
-{
- auto a = [1, 2, 3];
- auto b = a.dup;
- debug(SENTINEL) {} else
- assert(b.capacity >= 3);
-}
-
-@system unittest
-{
- // Bugzilla 12580
- void[] m = [0];
- shared(void)[] s = [cast(shared)1];
- immutable(void)[] i = [cast(immutable)2];
-
- s = s.dup;
- static assert(is(typeof(s.dup) == shared(void)[]));
-
- m = i.dup;
- i = m.dup;
- i = i.idup;
- i = m.idup;
- i = s.idup;
- i = s.dup;
- static assert(!__traits(compiles, m = s.dup));
-}
-
-@safe unittest
-{
- // Bugzilla 13809
- static struct S
- {
- this(this) {}
- ~this() {}
- }
-
- S[] arr;
- auto a = arr.dup;
-}
-
-@system unittest
-{
- // Bugzilla 16504
- static struct S
- {
- __gshared int* gp;
- int* p;
- // postblit and hence .dup could escape
- this(this) { gp = p; }
- }
-
- int p;
- scope S[1] arr = [S(&p)];
- auto a = arr.dup; // dup does escape
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=21983
-// dup/idup destroys partially constructed arrays on failure
-@safe unittest
-{
- static struct SImpl(bool postblit)
- {
- int num;
- long l = 0xDEADBEEF;
-
- static if (postblit)
- {
- this(this)
- {
- if (this.num == 3)
- throw new Exception("");
- }
- }
- else
- {
- this(scope ref const SImpl other)
- {
- if (other.num == 3)
- throw new Exception("");
-
- this.num = other.num;
- this.l = other.l;
- }
- }
-
- ~this() @trusted
- {
- if (l != 0xDEADBEEF)
- {
- import core.stdc.stdio;
- printf("Unexpected value: %lld\n", l);
- fflush(stdout);
- assert(false);
- }
- }
- }
-
- alias Postblit = SImpl!true;
- alias Copy = SImpl!false;
-
- static int test(S)()
- {
- S[4] arr = [ S(1), S(2), S(3), S(4) ];
- try
- {
- arr.dup();
- assert(false);
- }
- catch (Exception)
- {
- return 1;
- }
- }
-
- static assert(test!Postblit());
- assert(test!Postblit());
-
- static assert(test!Copy());
- assert(test!Copy());
-}
-
/**
Destroys the given object and optionally resets to initial state. It's used to
_destroy an object, calling its destructor or finalizer so it no longer
diff --git a/libphobos/libdruntime/rt/dylib_fixes.c b/libphobos/libdruntime/rt/dylib_fixes.c
index e484fed..c1391b8 100644
--- a/libphobos/libdruntime/rt/dylib_fixes.c
+++ b/libphobos/libdruntime/rt/dylib_fixes.c
@@ -25,4 +25,3 @@ __attribute__((destructor)) static void finalizer ()
{
rt_term();
}
-
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 744e5ad..1f0cfbf 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-1516ecad932d88a1618163384e6f69009d125391
+5748ca43fd5c3e31ce7a8511f542b67e5d5a3dc6
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/etc/c/curl.d b/libphobos/src/etc/c/curl.d
index 0c5b727..e6a1043 100644
--- a/libphobos/src/etc/c/curl.d
+++ b/libphobos/src/etc/c/curl.d
@@ -1372,9 +1372,9 @@ alias curl_TimeCond = int;
/** curl_strequal() and curl_strnequal() are subject for removal in a future
libcurl, see lib/README.curlx for details */
extern (C) {
-int curl_strequal(in const(char) *s1, in const(char) *s2);
+int curl_strequal(scope const(char) *s1, scope const(char) *s2);
/// ditto
-int curl_strnequal(in const(char) *s1, in const(char) *s2, size_t n);
+int curl_strnequal(scope const(char) *s1, scope const(char) *s2, size_t n);
}
enum CurlForm {
nothing, /********** the first one is unused ************/
@@ -1464,7 +1464,7 @@ CURLFORMcode curl_formadd(curl_httppost **httppost, curl_httppost **last_post,.
* Should return the buffer length passed to it as the argument "len" on
* success.
*/
-alias curl_formget_callback = size_t function(void *arg, in const(char) *buf, size_t len);
+alias curl_formget_callback = size_t function(void *arg, const(char) *buf, size_t len);
/**
* Name: curl_formget()
@@ -1494,7 +1494,7 @@ void curl_formfree(curl_httppost *form);
* Returns a malloc()'ed string that MUST be curl_free()ed after usage is
* complete. DEPRECATED - see lib/README.curlx
*/
-char * curl_getenv(in const(char) *variable);
+char * curl_getenv(scope const(char) *variable);
/**
* Name: curl_version()
@@ -1514,10 +1514,10 @@ char * curl_version();
* %XX versions). This function returns a new allocated string or NULL if an
* error occurred.
*/
-char * curl_easy_escape(CURL *handle, in const(char) *string, int length);
+char * curl_easy_escape(CURL *handle, scope const(char) *string, int length);
/** the previous version: */
-char * curl_escape(in const(char) *string, int length);
+char * curl_escape(scope const(char) *string, int length);
/**
@@ -1531,10 +1531,10 @@ char * curl_escape(in const(char) *string, int length);
* Conversion Note: On non-ASCII platforms the ASCII %XX codes are
* converted into the host encoding.
*/
-char * curl_easy_unescape(CURL *handle, in const(char) *string, int length, int *outlength);
+char * curl_easy_unescape(CURL *handle, scope const(char) *string, int length, int *outlength);
/** the previous version */
-char * curl_unescape(in const(char) *string, int length);
+char * curl_unescape(scope const(char) *string, int length);
/**
* Name: curl_free()
@@ -1608,7 +1608,7 @@ struct curl_slist
* Appends a string to a linked list. If no list exists, it will be created
* first. Returns the new list, after appending.
*/
-curl_slist * curl_slist_append(curl_slist *, in const(char) *);
+curl_slist * curl_slist_append(curl_slist *, const(char) *);
/**
* Name: curl_slist_free_all()
diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d
index 2fcc2ba..b810fbb 100644
--- a/libphobos/src/std/algorithm/comparison.d
+++ b/libphobos/src/std/algorithm/comparison.d
@@ -1027,7 +1027,7 @@ template equal(alias pred = "a == b")
}
}
- private bool equalLoop(Rs...)(Rs rs)
+ private bool equalLoop(Rs...)(ref Rs rs)
{
for (; !rs[0].empty; rs[0].popFront)
static foreach (r; rs[1 .. $])
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index af665c4..300a897 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -1263,19 +1263,22 @@ public:
// filter
/**
-Implements the higher order filter function. The predicate is passed to
-$(REF unaryFun, std,functional), and can either accept a string, or any callable
-that can be executed via `pred(element)`.
+`filter!(predicate)(range)` returns a new range containing only elements `x` in `range` for
+which `predicate(x)` returns `true`.
+
+The predicate is passed to $(REF unaryFun, std,functional), and can be either a string, or
+any callable that can be executed via `pred(element)`.
Params:
predicate = Function to apply to each element of range
Returns:
- `filter!(predicate)(range)` returns a new range containing only elements `x` in `range` for
- which `predicate(x)` returns `true`.
+ An input range that contains the filtered elements. If `range` is at least a forward range, the return value of `filter`
+ will also be a forward range.
See_Also:
- $(HTTP en.wikipedia.org/wiki/Filter_(higher-order_function), Filter (higher-order function))
+ $(HTTP en.wikipedia.org/wiki/Filter_(higher-order_function), Filter (higher-order function)),
+ $(REF filterBidirectional, std,algorithm,iteration)
*/
template filter(alias predicate)
if (is(typeof(unaryFun!predicate)))
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index 55a1438..daa4b99 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -2512,6 +2512,8 @@ RandomAccessRange find(RandomAccessRange, alias pred, InputRange)(
Convenience function. Like find, but only returns whether or not the search
was successful.
+For more information about `pred` see $(LREF find).
+
See_Also:
$(REF among, std,algorithm,comparison) for checking a value against multiple possibilities.
+/
@@ -2622,6 +2624,8 @@ Advances `r` until it finds the first two adjacent elements `a`,
`b` that satisfy `pred(a, b)`. Performs $(BIGOH r.length)
evaluations of `pred`.
+For more information about `pred` see $(LREF find).
+
Params:
pred = The predicate to satisfy.
r = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to
@@ -2698,6 +2702,8 @@ Advances `seq` by calling `seq.popFront` until either
`find!(pred)(choices, seq.front)` is `true`, or `seq` becomes empty.
Performs $(BIGOH seq.length * choices.length) evaluations of `pred`.
+For more information about `pred` see $(LREF find).
+
Params:
pred = The predicate to use for determining a match.
seq = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to
@@ -2758,6 +2764,8 @@ if (isInputRange!InputRange && isForwardRange!ForwardRange)
* Similarly, the haystack is positioned so as `pred` evaluates to `false` for
* `haystack.front`.
*
+ * For more information about `pred` see $(LREF find).
+
* Params:
* haystack = The
* $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to search
@@ -2882,6 +2890,8 @@ $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) and
the type of `result[0]` and `result[1]` is the same as $(REF takeExactly,
std,range).
+For more information about `pred` see $(LREF find).
+
Params:
pred = Predicate to use for comparing needle against haystack.
haystack = The range to search.
@@ -4595,6 +4605,8 @@ $(REF_ALTTEXT input range, isInputRange, std,range,primitives) starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate `pred`.
+For more information about `pred` see $(LREF find).
+
Params:
pred = Predicate to use in comparing the elements of the haystack and the
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 8f6c3bf..9164e07 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -3419,17 +3419,20 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
}
}
+ Target result = cast(Target) (sign ? -ldval : ldval);
+
// if overflow occurred
- enforce(ldval != real.infinity, new ConvException("Range error"));
+ import std.math : isFinite;
+ enforce(isFinite(result), new ConvException("Range error"));
advanceSource();
static if (doCount)
{
- return tuple!("data", "count")(cast (Target) (sign ? -ldval : ldval), count);
+ return tuple!("data", "count")(result, count);
}
else
{
- return cast (Target) (sign ? -ldval : ldval);
+ return result;
}
}
@@ -3785,6 +3788,16 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
assertThrown!ConvException(parse!double(s));
}
+@safe unittest // https://issues.dlang.org/show_bug.cgi?id=22637
+{
+ import std.exception : assertThrown, assertNotThrown;
+ auto src = "9991232549867999698999493543521458974414359998784641646846435132132543645435456345634541999999999999999"
+ ~ "9999999943321231321311999231345312413646846354354354399999934153465464654646464654134135354199999999996515734999"
+ ~ "9999999320135273486741354354731567431324134999999999999999999999999999999999999999999999135411.9";
+ assertThrown!ConvException(parse!double(src));
+ static if (real.max_10_exp > 310) assertNotThrown!ConvException(parse!real(src));
+}
+
/**
Parsing one character off a range returns the first element and calls `popFront`.
diff --git a/libphobos/src/std/experimental/checkedint.d b/libphobos/src/std/experimental/checkedint.d
index 9237341..2be5a2e 100644
--- a/libphobos/src/std/experimental/checkedint.d
+++ b/libphobos/src/std/experimental/checkedint.d
@@ -1,6 +1,6 @@
/**
- * This module is now deprecated, use $(MREF std, experimental)
+ * This module is now deprecated, use $(MREF std, checkedint)
* instead.
*
* Copyright: Copyright The D Language Foundation 2005 - 2015.
diff --git a/libphobos/src/std/experimental/logger/core.d b/libphobos/src/std/experimental/logger/core.d
index d899db7..f3c6932 100644
--- a/libphobos/src/std/experimental/logger/core.d
+++ b/libphobos/src/std/experimental/logger/core.d
@@ -4,6 +4,7 @@ Source: $(PHOBOSSRC std/experimental/logger/core.d)
*/
module std.experimental.logger.core;
+import core.atomic : atomicLoad, atomicOp, atomicStore, MemoryOrder;
import core.sync.mutex : Mutex;
import std.datetime.date : DateTime;
import std.datetime.systime : Clock, SysTime;
@@ -555,14 +556,14 @@ abstract class Logger
Params:
lv = `LogLevel` to use for this `Logger` instance.
*/
- this(LogLevel lv) @safe
+ this(this This)(LogLevel lv)
{
this.logLevel_ = lv;
this.fatalHandler_ = delegate() {
throw new Error("A fatal log message was logged");
};
- this.mutex = new Mutex();
+ this.mutex = new typeof(mutex)();
}
/** A custom logger must implement this method in order to work in a
@@ -661,7 +662,7 @@ abstract class Logger
/// Ditto
@property final void logLevel(const LogLevel lv) @safe @nogc
{
- synchronized (mutex) this.logLevel_ = lv;
+ atomicStore(this.logLevel_, lv);
}
/** This `delegate` is called in case a log message with
@@ -1403,28 +1404,28 @@ abstract class Logger
// Thread Global
-private __gshared Logger stdSharedDefaultLogger;
+private shared Logger stdSharedDefaultLogger;
private shared Logger stdSharedLogger;
private shared LogLevel stdLoggerGlobalLogLevel = LogLevel.all;
/* This method returns the global default Logger.
* Marked @trusted because of excessive reliance on __gshared data
*/
-private @property Logger defaultSharedLoggerImpl() @trusted
+private @property shared(Logger) defaultSharedLoggerImpl() @trusted
{
import core.lifetime : emplace;
import std.stdio : stderr;
__gshared align(__traits(classInstanceAlignment, FileLogger))
- void[__traits(classInstanceSize, FileLogger)] _buffer;
+ void[__traits(classInstanceSize, FileLogger)] _buffer = void;
import std.concurrency : initOnce;
initOnce!stdSharedDefaultLogger({
auto buffer = cast(ubyte[]) _buffer;
- return emplace!FileLogger(buffer, stderr, LogLevel.info);
+ return cast(shared) emplace!(FileLogger)(buffer, stderr, LogLevel.info);
}());
- return stdSharedDefaultLogger;
+ return atomicLoad(stdSharedDefaultLogger);
}
/** This property sets and gets the default `Logger`. Unless set to another
@@ -1452,19 +1453,12 @@ if (sharedLog !is myLogger)
sharedLog = new myLogger;
-------------
*/
-@property Logger sharedLog() @safe
+@property shared(Logger) sharedLog() @safe
{
- static auto trustedLoad(ref shared Logger logger) @trusted
- {
- import core.atomic : atomicLoad, MemoryOrder;
- return cast() atomicLoad!(MemoryOrder.acq)(logger);
- //FIXME: Casting shared away here. Not good. See issue 16232.
- }
-
// If we have set up our own logger use that
- if (auto logger = trustedLoad(stdSharedLogger))
+ if (auto logger = atomicLoad!(MemoryOrder.seq)(stdSharedLogger))
{
- return logger;
+ return atomicLoad(logger);
}
else
{
@@ -1474,10 +1468,9 @@ if (sharedLog !is myLogger)
}
/// Ditto
-@property void sharedLog(Logger logger) @trusted
+@property void sharedLog(shared(Logger) logger) @safe
{
- import core.atomic : atomicStore, MemoryOrder;
- atomicStore!(MemoryOrder.rel)(stdSharedLogger, cast(shared) logger);
+ atomicStore!(MemoryOrder.seq)(stdSharedLogger, atomicLoad(logger));
}
/** This methods get and set the global `LogLevel`.
@@ -1523,9 +1516,12 @@ class StdForwardLogger : Logger
this.fatalHandler = delegate() {};
}
- override protected void writeLogMsg(ref LogEntry payload)
+ override protected void writeLogMsg(ref LogEntry payload) @trusted
{
- sharedLog.forwardMsg(payload);
+ synchronized (sharedLog.mutex)
+ {
+ (cast() sharedLog).forwardMsg(payload);
+ }
}
}
@@ -1535,6 +1531,40 @@ class StdForwardLogger : Logger
auto nl1 = new StdForwardLogger(LogLevel.all);
}
+@safe unittest
+{
+ import core.thread : Thread, msecs;
+
+ static class RaceLogger : Logger
+ {
+ int value;
+ this() @safe shared
+ {
+ super(LogLevel.init);
+ }
+ override void writeLogMsg(ref LogEntry payload) @safe
+ {
+ import core.thread : Thread, msecs;
+ if (payload.msg == "foo")
+ {
+ value = 42;
+ () @trusted { Thread.sleep(100.msecs); }();
+ assert(value == 42, "Another thread changed the value");
+ }
+ else
+ {
+ () @trusted { Thread.sleep(50.msecs); } ();
+ value = 13;
+ }
+ }
+ }
+
+ sharedLog = new shared RaceLogger;
+ scope(exit) { sharedLog = null; }
+ () @trusted { new Thread(() { log("foo"); }).start(); }();
+ log("bar");
+}
+
/** This `LogLevel` is unqiue to every thread.
The thread local `Logger` will use this `LogLevel` to filter log calls
@@ -1561,7 +1591,7 @@ private @property Logger stdThreadLocalLogImpl() @trusted
}
/** This function returns a thread unique `Logger`, that by default
-propergates all data logged to it to the `sharedLog`.
+propagates all data logged to it to the `sharedLog`.
These properties can be used to set and get this `Logger`. Every
modification to this `Logger` will only be visible in the thread the
@@ -1671,10 +1701,12 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
auto oldunspecificLogger = sharedLog;
scope(exit) {
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
}
- sharedLog = tl1;
+ () @trusted {
+ sharedLog = cast(shared) tl1;
+ }();
log();
assert(tl1.line == __LINE__ - 1);
@@ -1793,22 +1825,34 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
assert(l.line == lineNumber);
assert(l.logLevel == LogLevel.all);
- auto oldunspecificLogger = sharedLog;
+ Logger oldunspecificLogger;
+ () @trusted {
+ oldunspecificLogger = cast() sharedLog;
+ }();
assert(oldunspecificLogger.logLevel == LogLevel.info,
to!string(oldunspecificLogger.logLevel));
assert(l.logLevel == LogLevel.all);
- sharedLog = l;
+
+ () @trusted {
+ sharedLog = cast(shared) l;
+ }();
+
assert(globalLogLevel == LogLevel.all,
to!string(globalLogLevel));
scope(exit)
{
- sharedLog = oldunspecificLogger;
+ () @trusted {
+ sharedLog = atomicLoad(cast(shared) oldunspecificLogger);
+ }();
}
- assert(sharedLog.logLevel == LogLevel.all);
+ () @trusted {
+ assert((cast() sharedLog).logLevel == LogLevel.all);
+ }();
+
assert(stdThreadLocalLog.logLevel == LogLevel.all);
assert(globalLogLevel == LogLevel.all);
@@ -1880,13 +1924,14 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
string filename = deleteme ~ __FUNCTION__ ~ ".tempLogFile";
FileLogger l = new FileLogger(filename);
auto oldunspecificLogger = sharedLog;
- sharedLog = l;
+
+ sharedLog = cast(shared) l;
scope(exit)
{
remove(filename);
assert(!exists(filename));
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
@@ -1923,7 +1968,7 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
scope(exit)
{
remove(filename);
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
@@ -1931,8 +1976,11 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
string written = "this should be written to file";
auto l = new FileLogger(filename);
- sharedLog = l;
- sharedLog.logLevel = LogLevel.critical;
+ sharedLog = cast(shared) l;
+
+ () @trusted {
+ (cast() sharedLog).logLevel = LogLevel.critical;
+ }();
log(LogLevel.error, false, notWritten);
log(LogLevel.critical, true, written);
@@ -1974,11 +2022,14 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
auto mem = new TestLogger;
mem.fatalHandler = delegate() {};
- sharedLog = mem;
+
+ () @trusted {
+ sharedLog = cast(shared) mem;
+ }();
scope(exit)
{
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
@@ -2221,11 +2272,14 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
auto mem = new TestLogger;
mem.fatalHandler = delegate() {};
- sharedLog = mem;
+
+ () @trusted {
+ sharedLog = cast(shared) mem;
+ }();
scope(exit)
{
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
@@ -2477,10 +2531,13 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
stdThreadLocalLog.logLevel = LogLevel.all;
- sharedLog = mem;
+ () @trusted {
+ sharedLog = cast(shared) mem;
+ }();
+
scope(exit)
{
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
@@ -2707,12 +2764,15 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
scope(exit)
{
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
auto tl = new TestLogger(LogLevel.info);
- sharedLog = tl;
+
+ () @trusted {
+ sharedLog = cast(shared) tl;
+ }();
trace("trace");
assert(tl.msg.indexOf("trace") == -1);
@@ -2730,7 +2790,7 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
scope(exit)
{
- sharedLog = oldunspecificLogger;
+ sharedLog = atomicLoad(oldunspecificLogger);
globalLogLevel = LogLevel.all;
}
@@ -2738,7 +2798,10 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
auto tl = new TestLogger(LogLevel.info);
logger.insertLogger("required", tl);
- sharedLog = logger;
+
+ () @trusted {
+ sharedLog = cast(shared) logger;
+ }();
trace("trace");
assert(tl.msg.indexOf("trace") == -1);
@@ -2774,14 +2837,12 @@ version (StdUnittest) private void testFuncNames(Logger logger) @safe
// Workaround for atomics not allowed in @safe code
private auto trustedLoad(T)(ref shared T value) @trusted
{
- import core.atomic : atomicLoad, MemoryOrder;
return atomicLoad!(MemoryOrder.acq)(value);
}
// ditto
private void trustedStore(T)(ref shared T dst, ref T src) @trusted
{
- import core.atomic : atomicStore, MemoryOrder;
atomicStore!(MemoryOrder.rel)(dst, src);
}
@@ -2789,7 +2850,7 @@ private void trustedStore(T)(ref shared T dst, ref T src) @trusted
// to shared logger
@system unittest
{
- import core.atomic, core.thread, std.concurrency;
+ import core.thread, std.concurrency;
static shared logged_count = 0;
@@ -2826,10 +2887,13 @@ private void trustedStore(T)(ref shared T dst, ref T src) @trusted
auto oldSharedLog = sharedLog;
scope(exit)
{
- sharedLog = oldSharedLog;
+ sharedLog = atomicLoad(oldSharedLog);
}
- sharedLog = new IgnoredLog;
+ () @trusted {
+ sharedLog = cast(shared) new IgnoredLog;
+ }();
+
Thread[] spawned;
foreach (i; 0 .. 4)
@@ -2849,7 +2913,9 @@ private void trustedStore(T)(ref shared T dst, ref T src) @trusted
@safe unittest
{
- auto dl = cast(FileLogger) sharedLog;
+ auto dl = () @trusted {
+ return cast(FileLogger) cast() sharedLog;
+ }();
assert(dl !is null);
assert(dl.logLevel == LogLevel.info);
assert(globalLogLevel == LogLevel.all);
@@ -2946,7 +3012,7 @@ private void trustedStore(T)(ref shared T dst, ref T src) @trusted
auto oldShared = sharedLog;
scope(exit)
{
- sharedLog = oldShared;
+ sharedLog = atomicLoad(oldShared);
if (exists(fn))
{
remove(fn);
@@ -2956,7 +3022,11 @@ private void trustedStore(T)(ref shared T dst, ref T src) @trusted
auto ts = [ "Test log 1", "Test log 2", "Test log 3"];
auto fl = new FileLogger(fn);
- sharedLog = fl;
+
+ () @trusted {
+ sharedLog = cast(shared) fl;
+ }();
+
assert(exists(fn));
foreach (t; ts)
diff --git a/libphobos/src/std/experimental/logger/filelogger.d b/libphobos/src/std/experimental/logger/filelogger.d
index 5112e52..457012e 100644
--- a/libphobos/src/std/experimental/logger/filelogger.d
+++ b/libphobos/src/std/experimental/logger/filelogger.d
@@ -259,7 +259,7 @@ class FileLogger : Logger
file.close();
}
-@safe unittest
+@system unittest
{
auto dl = cast(FileLogger) sharedLog;
assert(dl !is null);
diff --git a/libphobos/src/std/experimental/logger/multilogger.d b/libphobos/src/std/experimental/logger/multilogger.d
index 9acd23a..3593690 100644
--- a/libphobos/src/std/experimental/logger/multilogger.d
+++ b/libphobos/src/std/experimental/logger/multilogger.d
@@ -187,7 +187,7 @@ class MultiLogger : Logger
assert(line.indexOf(iMsg) != -1, line ~ ":" ~ tMsg);
}
-@safe unittest
+@system unittest
{
auto dl = cast(FileLogger) sharedLog;
assert(dl !is null);
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index b8b4a8c..d6cac41 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -1510,7 +1510,7 @@ private
ushort bitmapcount, reserved;
attrgroup_t commonattr, volattr, dirattr, fileattr, forkattr;
}
- extern(C) int setattrlist(in char* path, scope ref attrlist attrs,
+ extern(C) int setattrlist(scope const(char)* path, scope ref attrlist attrs,
scope void* attrbuf, size_t attrBufSize, c_ulong options) nothrow @nogc @system;
}
diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d
index f1d6964..2fd6ff7 100644
--- a/libphobos/src/std/format/internal/write.d
+++ b/libphobos/src/std/format/internal/write.d
@@ -1337,7 +1337,7 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
/*
Static-size arrays are formatted as dynamic arrays.
*/
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, auto ref const(T) obj,
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, auto ref T obj,
scope const ref FormatSpec!Char f)
if (is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
{
@@ -1782,13 +1782,13 @@ void formatChar(Writer)(ref Writer w, in dchar c, in char quote)
Associative arrays are formatted by using `':'` and $(D ", ") as
separators, and enclosed by `'['` and `']'`.
*/
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, T obj, scope const ref FormatSpec!Char f)
if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
{
import std.format : enforceFmt, formatValue;
import std.range.primitives : put;
- AssocArrayTypeOf!(const(T)) val = obj;
+ AssocArrayTypeOf!T val = obj;
const spec = f.spec;
enforceFmt(spec == 's' || spec == '(',
diff --git a/libphobos/src/std/format/package.d b/libphobos/src/std/format/package.d
index 76d68f6..3f6f33a 100644
--- a/libphobos/src/std/format/package.d
+++ b/libphobos/src/std/format/package.d
@@ -1356,6 +1356,30 @@ if (isSomeChar!Char)
assert(result == " 1");
}
+// https://issues.dlang.org/show_bug.cgi?id=23245
+@safe unittest
+{
+ static struct S
+ {
+ string toString() { return "S"; }
+ }
+
+ S[1] s;
+ assert(format("%s", s) == "[S]");
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=23246
+@safe unittest
+{
+ static struct S
+ {
+ string toString() { return "S"; }
+ }
+
+ S[int] s = [0 : S()];
+ assert(format("%s", s) == "[0:S]");
+}
+
/// ditto
typeof(fmt) format(alias fmt, Args...)(Args args)
if (isSomeString!(typeof(fmt)))
diff --git a/libphobos/src/std/math/package.d b/libphobos/src/std/math/package.d
index 7443b0d..19982ec 100644
--- a/libphobos/src/std/math/package.d
+++ b/libphobos/src/std/math/package.d
@@ -383,6 +383,7 @@ template floatTraits(T)
enum ushort EXPBIAS = 0x3FE0;
enum uint EXPMASK_INT = 0x7FF0_0000;
enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only
+ enum ulong MANTISSAMASK_LONG = 0x000F_FFFF_FFFF_FFFF;
enum realFormat = RealFormat.ieeeDouble;
version (LittleEndian)
{
diff --git a/libphobos/src/std/math/rounding.d b/libphobos/src/std/math/rounding.d
index 5c8d708..7dbe89b 100644
--- a/libphobos/src/std/math/rounding.d
+++ b/libphobos/src/std/math/rounding.d
@@ -908,7 +908,9 @@ T floorImpl(T)(const T x) @trusted pure nothrow @nogc
// Other kinds of extractors for real formats.
static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
+ uint vi;
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ ulong vi;
}
floatBits y = void;
y.rv = x;
@@ -919,15 +921,14 @@ T floorImpl(T)(const T x) @trusted pure nothrow @nogc
static if (F.realFormat == RealFormat.ieeeSingle)
{
int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ enum mantissa_mask = F.MANTISSAMASK_INT;
+ enum sign_shift = 31;
}
else static if (F.realFormat == RealFormat.ieeeDouble)
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
-
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
+ long exp = ((y.vi >> (T.mant_dig - 1)) & 0x7ff) - 0x3ff;
+ enum mantissa_mask = F.MANTISSAMASK_LONG;
+ enum sign_shift = 63;
}
else static if (F.realFormat == RealFormat.ieeeExtended ||
F.realFormat == RealFormat.ieeeExtended53)
@@ -959,18 +960,21 @@ T floorImpl(T)(const T x) @trusted pure nothrow @nogc
return 0.0;
}
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ieeeSingle ||
+ F.realFormat == RealFormat.ieeeDouble)
{
if (exp < (T.mant_dig - 1))
{
// Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ // Note: the fraction mask represents the floating point number 0.999999...
+ // i.e: `2.0 ^^ (exp - T.mant_dig + 1) * (fraction_mask + 1) == 1.0`
+ const fraction_mask = mantissa_mask >> exp;
if ((y.vi & fraction_mask) != 0)
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
+ // If 'x' is negative, then first substract (1.0 - T.epsilon) from the value.
+ if (y.vi >> sign_shift)
+ y.vi += fraction_mask;
y.vi &= ~fraction_mask;
}
}
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index 106e51c..b2206ce 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -2762,7 +2762,7 @@ Returns:
return a `ref` to the $(D range element), otherwise it will return
a copy.
*/
-auto ref choice(Range, RandomGen = Random)(auto ref Range range, ref RandomGen urng)
+auto ref choice(Range, RandomGen = Random)(Range range, ref RandomGen urng)
if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
{
assert(range.length > 0,
@@ -2772,7 +2772,22 @@ if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
}
/// ditto
-auto ref choice(Range)(auto ref Range range)
+auto ref choice(Range)(Range range)
+{
+ return choice(range, rndGen);
+}
+
+/// ditto
+auto ref choice(Range, RandomGen = Random)(ref Range range, ref RandomGen urng)
+if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
+{
+ assert(range.length > 0,
+ __PRETTY_FUNCTION__ ~ ": invalid Range supplied. Range cannot be empty");
+ return range[uniform(size_t(0), $, urng)];
+}
+
+/// ditto
+auto ref choice(Range)(ref Range range)
{
return choice(range, rndGen);
}
@@ -2827,6 +2842,39 @@ auto ref choice(Range)(auto ref Range range)
"Choice did not return a valid element from the given Range");
}
+@safe unittest // issue 18631
+{
+ auto rng = MinstdRand0(42);
+ const a = [0,1,2];
+ const(int[]) b = [0, 1, 2];
+ auto x = choice(a);
+ auto y = choice(b);
+ auto z = choice(cast(const)[1, 2, 3]);
+ auto x1 = choice(a, rng);
+ auto y1 = choice(b, rng);
+ auto z1 = choice(cast(const)[1, 2, 3], rng);
+}
+
+@safe unittest // Ref range (issue 18631 PR)
+{
+ struct TestRange
+ {
+ int x;
+ ref int front() return {return x;}
+ ref int back() return {return x;}
+ void popFront() {}
+ void popBack() {}
+ bool empty = false;
+ TestRange save() {return this;}
+ size_t length = 10;
+ alias opDollar = length;
+ ref int opIndex(size_t i) return {return x;}
+ }
+
+ TestRange r = TestRange(10);
+ int* s = &choice(r);
+}
+
/**
Shuffles elements of `r` using `gen` as a shuffler. `r` must be
a random-access range with length. If no RNG is specified, `rndGen`
@@ -3008,8 +3056,16 @@ if (isRandomAccessRange!Range)
}
/**
-Rolls a dice with relative probabilities stored in $(D
-proportions). Returns the index in `proportions` that was chosen.
+Get a random index into a list of weights corresponding to each index
+
+Similar to rolling a die with relative probabilities stored in `proportions`.
+Returns the index in `proportions` that was chosen.
+
+Note:
+ Usually, dice are 'fair', meaning that each side has equal probability
+ to come up, in which case `1 + uniform(0, 6)` can simply be used.
+ In future Phobos versions, this function might get renamed to something like
+ `weightedChoice` to avoid confusion.
Params:
rnd = (optional) random number generator to use; if not
@@ -3055,6 +3111,9 @@ if (isNumeric!Num)
///
@safe unittest
{
+ auto d6 = 1 + dice(1, 1, 1, 1, 1, 1); // fair dice roll
+ auto d6b = 1 + dice(2, 1, 1, 1, 1, 1); // double the chance to roll '1'
+
auto x = dice(0.5, 0.5); // x is 0 or 1 in equal proportions
auto y = dice(50, 50); // y is 0 or 1 in equal proportions
auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time,
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index 8614dc9..a1fe962 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -1132,10 +1132,9 @@ each item is inferred from the size and type of the input array, respectively.
Returns: The slice of `buffer` containing the data that was actually read.
This will be shorter than `buffer` if EOF was reached before the buffer
-could be filled.
+could be filled. If the buffer is empty, it will be returned.
-Throws: `Exception` if `buffer` is empty.
- `ErrnoException` if the file is not opened or the call to `fread` fails.
+Throws: `ErrnoException` if the file is not opened or the call to `fread` fails.
`rawRead` always reads in binary mode on Windows.
*/
@@ -1144,7 +1143,7 @@ Throws: `Exception` if `buffer` is empty.
import std.exception : enforce, errnoEnforce;
if (!buffer.length)
- throw new Exception("rawRead must take a non-empty buffer");
+ return buffer;
enforce(isOpen, "Attempting to read from an unopened file");
version (Windows)
{
@@ -1211,6 +1210,16 @@ Throws: `Exception` if `buffer` is empty.
}
}
+ // https://issues.dlang.org/show_bug.cgi?id=13893
+ @system unittest
+ {
+ import std.exception : assertNotThrown;
+
+ File f;
+ ubyte[0] u;
+ assertNotThrown(f.rawRead(u));
+ }
+
/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/fwrite.html, fwrite) for the file
handle. The number of items to write and the size of each
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index 1d375ef..160665c 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -1941,79 +1941,8 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
auto ref matchImpl(SumTypes...)(auto ref SumTypes args)
if (allSatisfy!(isSumType, SumTypes) && args.length > 0)
{
- enum typeCount(SumType) = SumType.Types.length;
alias stride(size_t i) = .stride!(i, Map!(typeCount, SumTypes));
-
- /* A TagTuple represents a single possible set of tags that `args`
- * could have at runtime.
- *
- * Because D does not allow a struct to be the controlling expression
- * of a switch statement, we cannot dispatch on the TagTuple directly.
- * Instead, we must map each TagTuple to a unique integer and generate
- * a case label for each of those integers.
- *
- * This mapping is implemented in `fromCaseId` and `toCaseId`. It uses
- * the same technique that's used to map index tuples to memory offsets
- * in a multidimensional static array.
- *
- * For example, when `args` consists of two SumTypes with two member
- * types each, the TagTuples corresponding to each case label are:
- *
- * case 0: TagTuple([0, 0])
- * case 1: TagTuple([1, 0])
- * case 2: TagTuple([0, 1])
- * case 3: TagTuple([1, 1])
- *
- * When there is only one argument, the caseId is equal to that
- * argument's tag.
- */
- static struct TagTuple
- {
- size_t[SumTypes.length] tags;
- alias tags this;
-
- invariant
- {
- static foreach (i; 0 .. tags.length)
- {
- assert(tags[i] < SumTypes[i].Types.length, "Invalid tag");
- }
- }
-
- this(ref const(SumTypes) args)
- {
- static foreach (i; 0 .. tags.length)
- {
- tags[i] = args[i].tag;
- }
- }
-
- static TagTuple fromCaseId(size_t caseId)
- {
- TagTuple result;
-
- // Most-significant to least-significant
- static foreach_reverse (i; 0 .. result.length)
- {
- result[i] = caseId / stride!i;
- caseId %= stride!i;
- }
-
- return result;
- }
-
- size_t toCaseId()
- {
- size_t result;
-
- static foreach (i; 0 .. tags.length)
- {
- result += tags[i] * stride!i;
- }
-
- return result;
- }
- }
+ alias TagTuple = .TagTuple!(SumTypes);
/*
* A list of arguments to be passed to a handler needed for the case
@@ -2149,6 +2078,81 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
}
}
+private enum typeCount(SumType) = SumType.Types.length;
+
+/* A TagTuple represents a single possible set of tags that `args`
+ * could have at runtime.
+ *
+ * Because D does not allow a struct to be the controlling expression
+ * of a switch statement, we cannot dispatch on the TagTuple directly.
+ * Instead, we must map each TagTuple to a unique integer and generate
+ * a case label for each of those integers.
+ *
+ * This mapping is implemented in `fromCaseId` and `toCaseId`. It uses
+ * the same technique that's used to map index tuples to memory offsets
+ * in a multidimensional static array.
+ *
+ * For example, when `args` consists of two SumTypes with two member
+ * types each, the TagTuples corresponding to each case label are:
+ *
+ * case 0: TagTuple([0, 0])
+ * case 1: TagTuple([1, 0])
+ * case 2: TagTuple([0, 1])
+ * case 3: TagTuple([1, 1])
+ *
+ * When there is only one argument, the caseId is equal to that
+ * argument's tag.
+ */
+private struct TagTuple(SumTypes...)
+{
+ size_t[SumTypes.length] tags;
+ alias tags this;
+
+ alias stride(size_t i) = .stride!(i, Map!(typeCount, SumTypes));
+
+ invariant
+ {
+ static foreach (i; 0 .. tags.length)
+ {
+ assert(tags[i] < SumTypes[i].Types.length, "Invalid tag");
+ }
+ }
+
+ this(ref const(SumTypes) args)
+ {
+ static foreach (i; 0 .. tags.length)
+ {
+ tags[i] = args[i].tag;
+ }
+ }
+
+ static TagTuple fromCaseId(size_t caseId)
+ {
+ TagTuple result;
+
+ // Most-significant to least-significant
+ static foreach_reverse (i; 0 .. result.length)
+ {
+ result[i] = caseId / stride!i;
+ caseId %= stride!i;
+ }
+
+ return result;
+ }
+
+ size_t toCaseId()
+ {
+ size_t result;
+
+ static foreach (i; 0 .. tags.length)
+ {
+ result += tags[i] * stride!i;
+ }
+
+ return result;
+ }
+}
+
// Matching
@safe unittest
{
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 8a3e22f..4ecfb10 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -4905,8 +4905,14 @@ if (is(Interface == interface) && is(BaseClass == class))
// - try default first
// - only on a failure run & return fallback
enum fallback = q{
- scope (failure) return fallback.%1$s(args);
- return default_.%1$s(args);
+ try
+ {
+ return default_.%1$s(args);
+ }
+ catch (Exception)
+ {
+ return fallback.%1$s(args);
+ }
}.format(__traits(identifier, func));
}
@@ -6589,15 +6595,11 @@ if (!is(T == class) && !(is(T == interface)))
private enum enableGCScan = hasIndirections!T;
}
- // TODO remove pure when https://issues.dlang.org/show_bug.cgi?id=15862 has been fixed
extern(C) private pure nothrow @nogc static
{
pragma(mangle, "free") void pureFree( void *ptr );
static if (enableGCScan)
- {
- pragma(mangle, "gc_addRange") void pureGcAddRange( in void* p, size_t sz, const TypeInfo ti = null );
- pragma(mangle, "gc_removeRange") void pureGcRemoveRange( in void* p );
- }
+ import core.memory : GC;
}
/// `RefCounted` storage implementation.
@@ -6637,7 +6639,7 @@ if (!is(T == class) && !(is(T == interface)))
{
import std.internal.memory : enforceCalloc;
_store = cast(Impl*) enforceCalloc(1, Impl.sizeof);
- pureGcAddRange(&_store._payload, T.sizeof);
+ GC.addRange(&_store._payload, T.sizeof);
}
else
{
@@ -6650,7 +6652,7 @@ if (!is(T == class) && !(is(T == interface)))
{
static if (enableGCScan)
{
- pureGcRemoveRange(&this._store._payload);
+ GC.removeRange(&this._store._payload);
}
pureFree(_store);
_store = null;
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 98735ac..e12a70c 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -7032,9 +7032,7 @@ template genericDecodeGrapheme(bool getValue)
case RI:
if (isRegionalIndicator(ch))
mixin(eat);
- else
- goto L_End_Extend;
- break;
+ goto L_End_Extend;
case L:
if (isHangL(ch))
mixin(eat);
@@ -7166,6 +7164,10 @@ if (isInputRange!Input && is(immutable ElementType!Input == immutable dchar))
s = "\u11A8\u0308\uAC01";
assert(equal(decodeGrapheme(s)[], "\u11A8\u0308"));
assert(equal(decodeGrapheme(s)[], "\uAC01"));
+
+ // Two Union Jacks of the Great Britain
+ s = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7";
+ assert(equal(decodeGrapheme(s)[], "\U0001F1EC\U0001F1E7"));
}
/++
diff --git a/libphobos/testsuite/libphobos.gc/nocollect.d b/libphobos/testsuite/libphobos.gc/nocollect.d
index 5df1483..64ed222 100644
--- a/libphobos/testsuite/libphobos.gc/nocollect.d
+++ b/libphobos/testsuite/libphobos.gc/nocollect.d
@@ -12,4 +12,4 @@ void main()
stats = GC.profileStats();
assert(stats.numCollections == 0);
-} \ No newline at end of file
+}