aboutsummaryrefslogtreecommitdiff
path: root/libphobos
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-07-10 03:07:41 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2023-07-10 03:13:00 +0200
commit0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3 (patch)
tree8c549ddd4b93c78f44959d47a4956837022a5cf1 /libphobos
parentd41a57c46df6f8f7dae0c0a8b349e734806a837b (diff)
downloadgcc-0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3.zip
gcc-0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3.tar.gz
gcc-0cafc3b6272d1dd738e8d7e66e1d8741e08f74d3.tar.bz2
d: Merge upstream dmd, druntime 17ccd12af3, phobos 8d3800bee.
D front-end changes: - Import dmd v2.104.0. - Assignment-style syntax is now allowed for `alias this'. - Overloading `extern(C)' functions is now an error. D runtime changes: - Import druntime v2.104.0. Phobos changes: - Import phobos v2.104.0. - Better static assert messages when instantiating `std.algorithm.iteration.permutations' with wrong inputs. - Added `std.system.instructionSetArchitecture' and `std.system.ISA'. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 17ccd12af3. * dmd/VERSION: Bump version to v2.104.0. * Make-lang.in (D_FRONTEND_OBJS): Rename d/apply.o to d/postordervisitor.o. * d-codegen.cc (make_location_t): Update for new front-end interface. (build_filename_from_loc): Likewise. (build_assert_call): Likewise. (build_array_bounds_call): Likewise. (build_bounds_index_condition): Likewise. (build_bounds_slice_condition): Likewise. (build_frame_type): Likewise. (get_frameinfo): Likewise. * d-diagnostic.cc (d_diagnostic_report_diagnostic): Likewise. * decl.cc (build_decl_tree): Likewise. (start_function): Likewise. * expr.cc (ExprVisitor::visit (NewExp *)): Replace code generation of `new pointer' with front-end lowering. * runtime.def (NEWITEMT): Remove. (NEWITEMIT): Remove. * toir.cc (IRVisitor::visit (LabelStatement *)): Update for new front-end interface. * typeinfo.cc (check_typeinfo_type): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 17ccd12af3. * src/MERGE: Merge upstream phobos 8d3800bee. gcc/testsuite/ChangeLog: * gdc.dg/asm4.d: Update test.
Diffstat (limited to 'libphobos')
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/__builtins.di3
-rw-r--r--libphobos/libdruntime/core/atomic.d2
-rw-r--r--libphobos/libdruntime/core/internal/string.d8
-rw-r--r--libphobos/libdruntime/core/internal/util/array.d16
-rw-r--r--libphobos/libdruntime/core/lifetime.d197
-rw-r--r--libphobos/libdruntime/core/stdc/assert_.d31
-rw-r--r--libphobos/libdruntime/object.d5
-rw-r--r--libphobos/libdruntime/rt/cast_.d20
-rw-r--r--libphobos/libdruntime/rt/lifetime.d136
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/std/algorithm/iteration.d12
-rw-r--r--libphobos/src/std/bigint.d10
-rw-r--r--libphobos/src/std/checkedint.d8
-rw-r--r--libphobos/src/std/conv.d59
-rw-r--r--libphobos/src/std/experimental/allocator/mallocator.d18
-rw-r--r--libphobos/src/std/getopt.d19
-rw-r--r--libphobos/src/std/path.d26
-rw-r--r--libphobos/src/std/range/package.d51
-rw-r--r--libphobos/src/std/system.d72
-rw-r--r--libphobos/src/std/typecons.d10
21 files changed, 438 insertions, 269 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 95ea67d..1cff48a 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-28a3b24c2e45de39cd3df528142fd06b6456e8fd
+17ccd12af386543c0b9935bf7e0a8e701b903105
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/__builtins.di b/libphobos/libdruntime/__builtins.di
index 1c49035..74147a0 100644
--- a/libphobos/libdruntime/__builtins.di
+++ b/libphobos/libdruntime/__builtins.di
@@ -67,8 +67,7 @@ version (DigitalMars)
ushort __builtin_bswap16()(ushort value)
{
- import core.bitop;
- return core.bitop.byteswap(value);
+ return cast(ushort) (((value >> 8) & 0xFF) | ((value << 8) & 0xFF00U));
}
uint __builtin_bswap32()(uint value)
diff --git a/libphobos/libdruntime/core/atomic.d b/libphobos/libdruntime/core/atomic.d
index 1fba06c..5a7d00c 100644
--- a/libphobos/libdruntime/core/atomic.d
+++ b/libphobos/libdruntime/core/atomic.d
@@ -162,7 +162,7 @@ void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref shared T val, V new
}
/// Ditto
-void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref shared T val, shared V newval) pure nothrow @nogc @trusted
+void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref shared T val, auto ref shared V newval) pure nothrow @nogc @trusted
if (is(T == class))
{
static assert (is (V : T), "Can't assign `newval` of type `shared " ~ V.stringof ~ "` to `shared " ~ T.stringof ~ "`.");
diff --git a/libphobos/libdruntime/core/internal/string.d b/libphobos/libdruntime/core/internal/string.d
index e09bba4..7bb319e 100644
--- a/libphobos/libdruntime/core/internal/string.d
+++ b/libphobos/libdruntime/core/internal/string.d
@@ -152,7 +152,7 @@ T[] signedToTempString(uint radix = 10, bool upperCase = false, T)(long value, r
if (neg)
{
// about to do a slice without a bounds check
- auto trustedSlice(return scope char[] r) @trusted { assert(r.ptr > buf.ptr); return (r.ptr-1)[0..r.length+1]; }
+ auto trustedSlice(return scope T[] r) @trusted { assert(r.ptr > buf.ptr); return (r.ptr-1)[0..r.length+1]; }
r = trustedSlice(r);
r[0] = '-';
}
@@ -190,6 +190,12 @@ unittest
assert(long.max.signedToTempString(buf) == "9223372036854775807");
assert(long.min.signedToTempString(buf) == "-9223372036854775808");
+ wchar[65] wbuf = void;
+ assert(1.signedToTempString(wbuf) == "1"w);
+
+ dchar[65] dbuf = void;
+ assert(1.signedToTempString(dbuf) == "1"d);
+
// use stack allocated struct version
assert(0.signedToTempString() == "0");
assert(1.signedToTempString == "1");
diff --git a/libphobos/libdruntime/core/internal/util/array.d b/libphobos/libdruntime/core/internal/util/array.d
index 6136cfe..066ee7e 100644
--- a/libphobos/libdruntime/core/internal/util/array.d
+++ b/libphobos/libdruntime/core/internal/util/array.d
@@ -26,14 +26,6 @@ private char[] errorMessage(Args...)(scope const(char*) format,
@safe /* pure dmd @@@BUG11461@@@ */ nothrow:
-void enforceTypedArraysConformable(T)(const char[] action,
- const T[] a1, const T[] a2, const bool allowOverlap = false)
-{
- _enforceSameLength(action, a1.length, a2.length);
- if (!allowOverlap)
- _enforceNoOverlap(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
-}
-
void enforceRawArraysConformable(const char[] action, const size_t elementSize,
const void[] a1, const void[] a2, const bool allowOverlap = false)
{
@@ -76,14 +68,6 @@ private void _enforceNoOverlap(const char[] action,
assert(0, msg);
}
-void enforceTypedArraysConformableNogc(T)(const char[] action,
- const T[] a1, const T[] a2, const bool allowOverlap = false)
-{
- _enforceSameLengthNogc(action, a1.length, a2.length);
- if (!allowOverlap)
- _enforceNoOverlapNogc(action, arrayToPtr(a1), arrayToPtr(a2), T.sizeof * a1.length);
-}
-
void enforceRawArraysConformableNogc(const char[] action, const size_t elementSize,
const void[] a1, const void[] a2, const bool allowOverlap = false)
{
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 5e339c0..ae047cb 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -2777,6 +2777,70 @@ if (is(T == class))
return cast(T) p;
}
+/**
+ * TraceGC wrapper around $(REF _d_newclassT, core,lifetime).
+ */
+T _d_newclassTTrace(T)(string file, int line, string funcname) @trusted
+{
+ version (D_TypeInfo)
+ {
+ import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure;
+ mixin(TraceHook!(T.stringof, "_d_newclassT"));
+
+ return _d_newclassT!T();
+ }
+ else
+ assert(0, "Cannot create new class if compiling without support for runtime type information!");
+}
+
+/**
+ * Allocate an initialized non-array item.
+ *
+ * This is an optimization to avoid things needed for arrays like the __arrayPad(size).
+ * Used to allocate struct instances on the heap.
+ *
+ * ---
+ * struct Sz {int x = 0;}
+ * struct Si {int x = 3;}
+ *
+ * void main()
+ * {
+ * new Sz(); // uses zero-initialization
+ * new Si(); // uses Si.init
+ * }
+ * ---
+ *
+ * Returns:
+ * newly allocated item
+ */
+T* _d_newitemT(T)() @trusted
+{
+ import core.internal.lifetime : emplaceInitializer;
+ import core.internal.traits : hasElaborateDestructor, hasIndirections;
+ import core.memory : GC;
+
+ auto flags = !hasIndirections!T ? GC.BlkAttr.NO_SCAN : GC.BlkAttr.NONE;
+ immutable tiSize = hasElaborateDestructor!T ? size_t.sizeof : 0;
+ immutable itemSize = T.sizeof;
+ immutable totalSize = itemSize + tiSize;
+ if (tiSize)
+ flags |= GC.BlkAttr.STRUCTFINAL | GC.BlkAttr.FINALIZE;
+
+ auto blkInfo = GC.qalloc(totalSize, flags, null);
+ auto p = blkInfo.base;
+
+ if (tiSize)
+ {
+ // The GC might not have cleared the padding area in the block.
+ *cast(TypeInfo*) (p + (itemSize & ~(size_t.sizeof - 1))) = null;
+ *cast(TypeInfo*) (p + blkInfo.size - tiSize) = cast() typeid(T);
+ }
+
+ emplaceInitializer(*(cast(T*) p));
+
+ return cast(T*) p;
+}
+
// Test allocation
@safe unittest
{
@@ -2805,15 +2869,134 @@ if (is(T == class))
}
}
-T _d_newclassTTrace(T)(string file, int line, string funcname) @trusted
+// Test allocation
+@safe unittest
+{
+ struct S { }
+ S* s = _d_newitemT!S();
+
+ assert(s !is null);
+}
+
+// Test initializers
+@safe unittest
{
- version (D_TypeInfo)
{
- import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;
- mixin(TraceHook!(T.stringof, "_d_newclassT"));
+ // zero-initialization
+ struct S { int x, y; }
+ S* s = _d_newitemT!S();
- return _d_newclassT!T();
+ assert(s.x == 0);
+ assert(s.y == 0);
+ }
+ {
+ // S.init
+ struct S { int x = 2, y = 3; }
+ S* s = _d_newitemT!S();
+
+ assert(s.x == 2);
+ assert(s.y == 3);
+ }
+}
+
+// Test GC attributes
+version (CoreUnittest)
+{
+ struct S1
+ {
+ int x = 5;
+ }
+ struct S2
+ {
+ int x;
+ this(int x) { this.x = x; }
+ }
+ struct S3
+ {
+ int[4] x;
+ this(int x) { this.x[] = x; }
+ }
+ struct S4
+ {
+ int *x;
+ }
+
+}
+@system unittest
+{
+ import core.memory : GC;
+
+ auto s1 = new S1;
+ assert(s1.x == 5);
+ assert(GC.getAttr(s1) == GC.BlkAttr.NO_SCAN);
+
+ auto s2 = new S2(3);
+ assert(s2.x == 3);
+ assert(GC.getAttr(s2) == GC.BlkAttr.NO_SCAN);
+
+ auto s3 = new S3(1);
+ assert(s3.x == [1, 1, 1, 1]);
+ assert(GC.getAttr(s3) == GC.BlkAttr.NO_SCAN);
+ debug(SENTINEL) {} else
+ assert(GC.sizeOf(s3) == 16);
+
+ auto s4 = new S4;
+ assert(s4.x == null);
+ assert(GC.getAttr(s4) == 0);
+}
+
+// Test struct finalizers exception handling
+debug(SENTINEL) {} else
+@system unittest
+{
+ import core.memory : GC;
+
+ bool test(E)()
+ {
+ import core.exception;
+ static struct S1
+ {
+ E exc;
+ ~this() { throw exc; }
+ }
+
+ bool caught = false;
+ S1* s = new S1(new E("test onFinalizeError"));
+ try
+ {
+ GC.runFinalizers((cast(char*)(typeid(S1).xdtor))[0 .. 1]);
+ }
+ catch (FinalizeError err)
+ {
+ caught = true;
+ }
+ catch (E)
+ {
+ }
+ GC.free(s);
+ return caught;
+ }
+
+ assert(test!Exception);
+ import core.exception : InvalidMemoryOperationError;
+ assert(!test!InvalidMemoryOperationError);
+}
+
+version (D_ProfileGC)
+{
+ /**
+ * TraceGC wrapper around $(REF _d_newitemT, core,lifetime).
+ */
+ T* _d_newitemTTrace(T)(string file, int line, string funcname) @trusted
+ {
+ version (D_TypeInfo)
+ {
+ import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure;
+ mixin(TraceHook!(T.stringof, "_d_newitemT"));
+
+ return _d_newitemT!T();
+ }
+ else
+ assert(0, "Cannot create new `struct` if compiling without support for runtime type information!");
}
- else
- assert(0, "Cannot create new class if compiling without support for runtime type information!");
}
diff --git a/libphobos/libdruntime/core/stdc/assert_.d b/libphobos/libdruntime/core/stdc/assert_.d
index fc9402f..a8909e2 100644
--- a/libphobos/libdruntime/core/stdc/assert_.d
+++ b/libphobos/libdruntime/core/stdc/assert_.d
@@ -12,7 +12,6 @@
/****************************
* These are the various functions called by the assert() macro.
- * They are all noreturn functions, although D doesn't have a specific attribute for that.
*/
module core.stdc.assert_;
@@ -36,7 +35,7 @@ version (CRuntime_DigitalMars)
/***
* Assert failure function in the Digital Mars C library.
*/
- void _assert(const(void)* exp, const(void)* file, uint line);
+ noreturn _assert(const(void)* exp, const(void)* file, uint line);
}
else version (CRuntime_Microsoft)
{
@@ -44,37 +43,37 @@ else version (CRuntime_Microsoft)
* Assert failure function in the Microsoft C library.
* `_assert` is not in assert.h, but it is in the library.
*/
- void _wassert(const(wchar)* exp, const(wchar)* file, uint line);
+ noreturn _wassert(const(wchar)* exp, const(wchar)* file, uint line);
///
- void _assert(const(char)* exp, const(char)* file, uint line);
+ noreturn _assert(const(char)* exp, const(char)* file, uint line);
}
else version (Darwin)
{
/***
* Assert failure function in the Darwin C library.
*/
- void __assert_rtn(const(char)* func, const(char)* file, uint line, const(char)* exp);
+ noreturn __assert_rtn(const(char)* func, const(char)* file, uint line, const(char)* exp);
}
else version (FreeBSD)
{
/***
* Assert failure function in the FreeBSD C library.
*/
- void __assert(const(char)* exp, const(char)* file, uint line);
+ noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* exp);
}
else version (NetBSD)
{
/***
* Assert failure function in the NetBSD C library.
*/
- void __assert(const(char)* file, int line, const(char)* exp);
+ noreturn __assert(const(char)* file, int line, const(char)* exp);
}
else version (OpenBSD)
{
/***
* Assert failure function in the OpenBSD C library.
*/
- void __assert(const(char)* file, int line, const(char)* exp);
+ noreturn __assert(const(char)* file, int line, const(char)* exp);
///
void __assert2(const(char)* file, int line, const(char)* func, const(char)* exp);
}
@@ -83,37 +82,37 @@ else version (DragonFlyBSD)
/***
* Assert failure function in the DragonFlyBSD C library.
*/
- void __assert(const(char)* exp, const(char)* file, uint line);
+ noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* exp);
}
else version (CRuntime_Glibc)
{
/***
* Assert failure functions in the GLIBC library.
*/
- void __assert(const(char)* exp, const(char)* file, uint line);
+ noreturn __assert(const(char)* exp, const(char)* file, uint line);
///
- void __assert_fail(const(char)* exp, const(char)* file, uint line, const(char)* func);
+ noreturn __assert_fail(const(char)* exp, const(char)* file, uint line, const(char)* func);
///
- void __assert_perror_fail(int errnum, const(char)* file, uint line, const(char)* func);
+ noreturn __assert_perror_fail(int errnum, const(char)* file, uint line, const(char)* func);
}
else version (CRuntime_Bionic)
{
- void __assert(const(char)* __file, int __line, const(char)* __msg);
+ noreturn __assert(const(char)* __file, int __line, const(char)* __msg);
}
else version (CRuntime_Musl)
{
/***
* Assert failure function in the Musl C library.
*/
- void __assert_fail(const(char)* exp, const(char)* file, uint line, const(char)* func);
+ noreturn __assert_fail(const(char)* exp, const(char)* file, uint line, const(char)* func);
}
else version (CRuntime_UClibc)
{
- void __assert(const(char)* exp, const(char)* file, uint line, const(char)* func);
+ noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* func);
}
else version (Solaris)
{
- void __assert_c99(const(char)* exp, const(char)* file, uint line, const(char)* func);
+ noreturn __assert_c99(const(char)* exp, const(char)* file, uint line, const(char)* func);
}
else
{
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 610cb7a..337eabf 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -527,7 +527,8 @@ private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner)
void setSameMutex(shared Object ownee, shared Object owner)
{
- _d_setSameMutex(ownee, owner);
+ import core.atomic : atomicLoad;
+ _d_setSameMutex(atomicLoad(ownee), atomicLoad(owner));
}
@system unittest
@@ -4532,6 +4533,7 @@ version (D_ProfileGC)
{
public import core.internal.array.appending : _d_arrayappendTTrace;
public import core.internal.array.concatenation : _d_arraycatnTXTrace;
+ public import core.lifetime : _d_newitemTTrace;
}
public import core.internal.array.appending : _d_arrayappendcTXImpl;
public import core.internal.array.comparison : __cmp;
@@ -4560,6 +4562,7 @@ public import core.lifetime : _d_delstructImpl;
public import core.lifetime : _d_newThrowable;
public import core.lifetime : _d_newclassT;
public import core.lifetime : _d_newclassTTrace;
+public import core.lifetime : _d_newitemT;
public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable);
diff --git a/libphobos/libdruntime/rt/cast_.d b/libphobos/libdruntime/rt/cast_.d
index 1604510..925599e 100644
--- a/libphobos/libdruntime/rt/cast_.d
+++ b/libphobos/libdruntime/rt/cast_.d
@@ -117,22 +117,6 @@ int _d_isbaseof2(scope ClassInfo oc, scope const ClassInfo c, scope ref size_t o
int _d_isbaseof(scope ClassInfo oc, scope const ClassInfo c) @safe
{
- if (areClassInfosEqual(oc, c))
- return true;
-
- do
- {
- if (oc.base && areClassInfosEqual(oc.base, c))
- return true;
-
- foreach (iface; oc.interfaces)
- {
- if (areClassInfosEqual(iface.classinfo, c) || _d_isbaseof(iface.classinfo, c))
- return true;
- }
-
- oc = oc.base;
- } while (oc);
-
- return false;
+ size_t offset = 0;
+ return _d_isbaseof2(oc, c, offset);
}
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index a37541b..40fa3e0 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -676,7 +676,7 @@ Params:
ti = `TypeInfo` of array type
arr = array to shrink. Its `.length` is element length, not byte length, despite `void` type
*/
-extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) /+nothrow+/
+extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow
{
// note, we do not care about shared. We are setting the length no matter
// what, so no lock is required.
@@ -701,7 +701,17 @@ extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) /+nothrow+/
{
auto oldsize = __arrayAllocLength(info, tinext);
if (oldsize > cursize)
- finalize_array(arr.ptr + cursize, oldsize - cursize, sti);
+ {
+ try
+ {
+ finalize_array(arr.ptr + cursize, oldsize - cursize, sti);
+ }
+ catch (Exception e)
+ {
+ import core.exception : onFinalizeError;
+ onFinalizeError(sti, e);
+ }
+ }
}
}
// Note: Since we "assume" the append is safe, it means it is not shared.
@@ -1148,25 +1158,8 @@ extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) @weak
}
/**
-Allocate an uninitialized non-array item.
-
-This is an optimization to avoid things needed for arrays like the __arrayPad(size).
-
-- `_d_newitemU` leaves the item uninitialized
-- `_d_newitemT` zero initializes the item
-- `_d_newitemiT` uses a non-zero initializer from `TypeInfo`
-
-Used to allocate struct instances on the heap.
----
-struct Sz {int x = 0;}
-struct Si {int x = 3;}
-
-void main()
-{
- new Sz(); // _d_newitemT(typeid(Sz))
- new Si(); // _d_newitemiT(typeid(Si))
-}
----
+Non-template version of $(REF _d_newitemT, core,lifetime) that does not perform
+initialization. Needed for $(REF allocEntry, rt,aaA).
Params:
_ti = `TypeInfo` of item to allocate
@@ -1196,26 +1189,6 @@ extern (C) void* _d_newitemU(scope const TypeInfo _ti) pure nothrow @weak
return p;
}
-/// ditto
-extern (C) void* _d_newitemT(const TypeInfo _ti) pure nothrow @weak
-{
- import core.stdc.string;
- auto p = _d_newitemU(_ti);
- memset(p, 0, _ti.tsize);
- return p;
-}
-
-/// Same as above, for item with non-zero initializer.
-extern (C) void* _d_newitemiT(const TypeInfo _ti) pure nothrow @weak
-{
- import core.stdc.string;
- auto p = _d_newitemU(_ti);
- auto init = _ti.initializer();
- assert(init.length <= _ti.tsize);
- memcpy(p, init.ptr, init.length);
- return p;
-}
-
debug(PRINTF)
{
extern(C) void printArrayCache()
@@ -2361,52 +2334,6 @@ unittest
testPostBlit!(const(S))();
}
-// cannot define structs inside unit test block, or they become nested structs.
-version (CoreUnittest)
-{
- struct S1
- {
- int x = 5;
- }
- struct S2
- {
- int x;
- this(int x) {this.x = x;}
- }
- struct S3
- {
- int[4] x;
- this(int x)
- {this.x[] = x;}
- }
- struct S4
- {
- int *x;
- }
-
-}
-
-unittest
-{
- auto s1 = new S1;
- assert(s1.x == 5);
- assert(GC.getAttr(s1) == BlkAttr.NO_SCAN);
-
- auto s2 = new S2(3);
- assert(s2.x == 3);
- assert(GC.getAttr(s2) == BlkAttr.NO_SCAN);
-
- auto s3 = new S3(1);
- assert(s3.x == [1,1,1,1]);
- assert(GC.getAttr(s3) == BlkAttr.NO_SCAN);
- debug(SENTINEL) {} else
- assert(GC.sizeOf(s3) == 16);
-
- auto s4 = new S4;
- assert(s4.x == null);
- assert(GC.getAttr(s4) == 0);
-}
-
unittest
{
// Bugzilla 3454 - Inconsistent flag setting in GC.realloc()
@@ -2731,41 +2658,6 @@ unittest
assert(!test!InvalidMemoryOperationError);
}
-// test struct finalizers exception handling
-debug(SENTINEL) {} else
-unittest
-{
- bool test(E)()
- {
- import core.exception;
- static struct S1
- {
- E exc;
- ~this() { throw exc; }
- }
-
- bool caught = false;
- S1* s = new S1(new E("test onFinalizeError"));
- try
- {
- GC.runFinalizers((cast(char*)(typeid(S1).xdtor))[0..1]);
- }
- catch (FinalizeError err)
- {
- caught = true;
- }
- catch (E)
- {
- }
- GC.free(s);
- return caught;
- }
-
- assert( test!Exception);
- import core.exception : InvalidMemoryOperationError;
- assert(!test!InvalidMemoryOperationError);
-}
-
// test bug 14126
unittest
{
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index c6e61f7..d3ebf74 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-8ab95ded5265379e74d507fdc252ff3d2305fc26
+8d3800bee23db56f71ef4066f74bce057fcce256
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/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 9f5a6ac..55ccb51 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -7939,15 +7939,23 @@ See_Also:
$(REF nextPermutation, std,algorithm,sorting).
*/
Permutations!Range permutations(Range)(Range r)
-if (isRandomAccessRange!Range && hasLength!Range)
{
+ static assert(isRandomAccessRange!Range, Range.stringof,
+ " must be a RandomAccessRange");
+ static assert(hasLength!Range, Range.stringof
+ , " must have a length");
+
return typeof(return)(r);
}
/// ditto
struct Permutations(Range)
-if (isRandomAccessRange!Range && hasLength!Range)
{
+ static assert(isRandomAccessRange!Range, Range.stringof,
+ " must be a RandomAccessRange");
+ static assert(hasLength!Range, Range.stringof
+ , " must have a length");
+
private size_t[] _indices, _state;
private Range _r;
private bool _empty;
diff --git a/libphobos/src/std/bigint.d b/libphobos/src/std/bigint.d
index 33d0eae..50f88da 100644
--- a/libphobos/src/std/bigint.d
+++ b/libphobos/src/std/bigint.d
@@ -254,11 +254,11 @@ public:
static if (op=="+")
{
- data = BigUint.addOrSubInt(data, u, sign != (y<0), sign);
+ data = BigUint.addOrSubInt!ulong(data, u, wantSub: sign != (y<0), sign);
}
else static if (op=="-")
{
- data = BigUint.addOrSubInt(data, u, sign == (y<0), sign);
+ data = BigUint.addOrSubInt!ulong(data, u, wantSub: sign == (y<0), sign);
}
else static if (op=="*")
{
@@ -613,7 +613,7 @@ public:
static if (op == "-")
{
r.sign = sign;
- r.data = BigUint.addOrSubInt(data, u, sign == (y<0), r.sign);
+ r.data = BigUint.addOrSubInt!ulong(data, u, wantSub: sign == (y<0), r.sign);
r.negate();
}
return r;
@@ -670,12 +670,12 @@ public:
{
static if (op=="++")
{
- data = BigUint.addOrSubInt(data, 1UL, sign, sign);
+ data = BigUint.addOrSubInt!ulong(data, 1UL, wantSub: sign, sign);
return this;
}
else static if (op=="--")
{
- data = BigUint.addOrSubInt(data, 1UL, !sign, sign);
+ data = BigUint.addOrSubInt!ulong(data, 1UL, wantSub: !sign, sign);
return this;
}
}
diff --git a/libphobos/src/std/checkedint.d b/libphobos/src/std/checkedint.d
index 79597e8..cec1dc1 100644
--- a/libphobos/src/std/checkedint.d
+++ b/libphobos/src/std/checkedint.d
@@ -2129,16 +2129,16 @@ static:
{
// Not value convertible, only viable option is rhs fits within the
// bounds of Lhs
- static if (ProperCompare.hookOpCmp(Rhs.min, Lhs.min) < 0)
+ static if (ProperCompare.hookOpCmp!(Rhs, Lhs)(lhs: Rhs.min, rhs: Lhs.min) < 0)
{
// Example: hookOpCast!short(int(42)), hookOpCast!uint(int(42))
- if (ProperCompare.hookOpCmp(rhs, Lhs.min) < 0)
+ if (ProperCompare.hookOpCmp!(Rhs, Lhs)(lhs: rhs, rhs: Lhs.min) < 0)
return defaultValue!Lhs;
}
- static if (ProperCompare.hookOpCmp(Rhs.max, Lhs.max) > 0)
+ static if (ProperCompare.hookOpCmp!(Rhs, Lhs)(lhs: Rhs.max, rhs: Lhs.max) > 0)
{
// Example: hookOpCast!int(uint(42))
- if (ProperCompare.hookOpCmp(rhs, Lhs.max) > 0)
+ if (ProperCompare.hookOpCmp!(Rhs, Lhs)(lhs: rhs, rhs: Lhs.max) > 0)
return defaultValue!Lhs;
}
return cast(Lhs) rhs;
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index aef2365..89d4e5e 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -102,21 +102,6 @@ private auto convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE_
return new ConvException(msg, fn, ln);
}
-private auto convError(S, T)(S source, int radix, string fn = __FILE__, size_t ln = __LINE__)
-{
- string msg;
-
- if (source.empty)
- msg = text("Unexpected end of input when converting from type " ~ S.stringof ~ " base ", radix,
- " to type " ~ T.stringof);
- else
- msg = text("Unexpected '", source.front,
- "' when converting from type " ~ S.stringof ~ " base ", radix,
- " to type " ~ T.stringof);
-
- return new ConvException(msg, fn, ln);
-}
-
@safe pure/* nothrow*/ // lazy parameter bug
private auto parseError(lazy string msg, string fn = __FILE__, size_t ln = __LINE__)
{
@@ -1023,7 +1008,15 @@ if (!(is(S : T) &&
else static if (isIntegral!S && !is(S == enum))
{
// other integral-to-string conversions with default radix
- return toImpl!(T, S)(value, 10);
+
+ import core.internal.string : signedToTempString, unsignedToTempString;
+
+ alias EEType = Unqual!(ElementEncodingType!T);
+ EEType[long.sizeof * 3 + 1] buf = void;
+ EEType[] t = isSigned!S
+ ? signedToTempString!(10, false, EEType)(value, buf)
+ : unsignedToTempString!(10, false, EEType)(value, buf);
+ return t.dup;
}
else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[]))
{
@@ -5726,33 +5719,13 @@ if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
{
void initialize(UT value)
{
- bool neg = false;
- if (value < 10)
- {
- if (value >= 0)
- {
- lwr = 0;
- upr = 1;
- buf[0] = cast(char)(cast(uint) value + '0');
- return;
- }
- value = -value;
- neg = true;
- }
- auto i = cast(uint) buf.length - 1;
- while (cast(Unsigned!UT) value >= 10)
- {
- buf[i] = cast(ubyte)('0' + cast(Unsigned!UT) value % 10);
- value = unsigned(value) / 10;
- --i;
- }
- buf[i] = cast(char)(cast(uint) value + '0');
- if (neg)
- {
- buf[i - 1] = '-';
- --i;
- }
- lwr = i;
+ import core.internal.string : signedToTempString, unsignedToTempString;
+
+ char[] t = value < 0
+ ? signedToTempString!(10, false, char)(value, buf)
+ : unsignedToTempString!(10, false, char)(value, buf);
+
+ lwr = cast(uint) (buf.length - t.length);
upr = cast(uint) buf.length;
}
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index de9afbb..02d5cf8 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -376,17 +376,17 @@ version (Posix)
{
// https://issues.dlang.org/show_bug.cgi?id=16398
// test the "pseudo" alignedReallocate for Posix
- void[] s = AlignedMallocator.instance.alignedAllocate(16, 32);
- (cast(ubyte[]) s)[] = ubyte(1);
- AlignedMallocator.instance.alignedReallocate(s, 32, 32);
+ void[] b = AlignedMallocator.instance.alignedAllocate(16, 32);
+ (cast(ubyte[]) b)[] = ubyte(1);
+ AlignedMallocator.instance.alignedReallocate(b, 32, 32);
ubyte[16] o;
o[] = 1;
- assert((cast(ubyte[]) s)[0 .. 16] == o);
- AlignedMallocator.instance.alignedReallocate(s, 4, 32);
- assert((cast(ubyte[]) s)[0 .. 3] == o[0 .. 3]);
- AlignedMallocator.instance.alignedReallocate(s, 128, 32);
- assert((cast(ubyte[]) s)[0 .. 3] == o[0 .. 3]);
- AlignedMallocator.instance.deallocate(s);
+ assert((cast(ubyte[]) b)[0 .. 16] == o);
+ AlignedMallocator.instance.alignedReallocate(b, 4, 32);
+ assert((cast(ubyte[]) b)[0 .. 3] == o[0 .. 3]);
+ AlignedMallocator.instance.alignedReallocate(b, 128, 32);
+ assert((cast(ubyte[]) b)[0 .. 3] == o[0 .. 3]);
+ AlignedMallocator.instance.deallocate(b);
void[] c;
AlignedMallocator.instance.alignedReallocate(c, 32, 32);
diff --git a/libphobos/src/std/getopt.d b/libphobos/src/std/getopt.d
index 42aeb40..cb97eeb 100644
--- a/libphobos/src/std/getopt.d
+++ b/libphobos/src/std/getopt.d
@@ -685,6 +685,7 @@ private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
import std.algorithm.mutation : remove;
import std.conv : to;
+ import std.uni : toLower;
static if (opts.length)
{
static if (is(typeof(opts[0]) : config))
@@ -708,7 +709,10 @@ private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
if (optionHelp.optLong.length)
{
- assert(optionHelp.optLong !in visitedLongOpts,
+ auto name = optionHelp.optLong;
+ if (!cfg.caseSensitive)
+ name = name.toLower();
+ assert(name !in visitedLongOpts,
"Long option " ~ optionHelp.optLong ~ " is multiply defined");
visitedLongOpts[optionHelp.optLong] = [];
@@ -716,7 +720,10 @@ private void getoptImpl(T...)(ref string[] args, ref configuration cfg,
if (optionHelp.optShort.length)
{
- assert(optionHelp.optShort !in visitedShortOpts,
+ auto name = optionHelp.optShort;
+ if (!cfg.caseSensitive)
+ name = name.toLower();
+ assert(name !in visitedShortOpts,
"Short option " ~ optionHelp.optShort
~ " is multiply defined");
@@ -1779,6 +1786,14 @@ void defaultGetoptFormatter(Output)(Output output, string text, Option[] opt, st
assertThrown!AssertError(getopt(args, "abc", &abc, "abc", &abc));
assertThrown!AssertError(getopt(args, "abc|a", &abc, "def|a", &def));
assertNotThrown!AssertError(getopt(args, "abc", &abc, "def", &def));
+
+ // https://issues.dlang.org/show_bug.cgi?id=23940
+ assertThrown!AssertError(getopt(args,
+ "abc", &abc, "ABC", &def));
+ assertThrown!AssertError(getopt(args, config.caseInsensitive,
+ "abc", &abc, "ABC", &def));
+ assertNotThrown!AssertError(getopt(args, config.caseSensitive,
+ "abc", &abc, "ABC", &def));
}
// https://issues.dlang.org/show_bug.cgi?id=17327 repeated option use
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index 63d60d1..e81f2b6 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -3955,7 +3955,7 @@ if (isConvertibleToString!Range)
}
-----
*/
-string expandTilde(string inputPath) @safe nothrow
+string expandTilde(return scope const string inputPath) @safe nothrow
{
version (Posix)
{
@@ -4138,7 +4138,7 @@ string expandTilde(string inputPath) @safe nothrow
}
///
-@system unittest
+@safe unittest
{
version (Posix)
{
@@ -4153,7 +4153,7 @@ string expandTilde(string inputPath) @safe nothrow
}
}
-@system unittest
+@safe unittest
{
version (Posix)
{
@@ -4205,6 +4205,26 @@ string expandTilde(string inputPath) @safe nothrow
}
}
+@safe unittest
+{
+ version (Posix)
+ {
+ import std.process : environment;
+
+ string testPath(scope const string source_path) {
+ return source_path.expandTilde;
+ }
+
+ auto oldHome = environment["HOME"];
+ scope(exit) environment["HOME"] = oldHome;
+
+ environment["HOME"] = "dmd/test";
+ assert(testPath("~/") == "dmd/test/");
+ assert(testPath("~") == "dmd/test");
+ }
+}
+
+
version (StdUnittest)
{
private:
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index 7a724b0..d37c641 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -232,7 +232,7 @@ module std.range;
public import std.array;
public import std.range.interfaces;
public import std.range.primitives;
-public import std.typecons : Flag, Yes, No;
+public import std.typecons : Flag, Yes, No, Rebindable, rebindable;
import std.internal.attributes : betterC;
import std.meta : aliasSeqOf, allSatisfy, anySatisfy, staticMap;
@@ -978,6 +978,11 @@ if (Ranges.length > 0 &&
static if (bidirectional) size_t backIndex;
else enum backIndex = source.length;
+ this(typeof(Result.tupleof) fields)
+ {
+ this.tupleof = fields;
+ }
+
public:
this(R input)
{
@@ -1376,25 +1381,34 @@ if (Ranges.length > 0 &&
static if (allSatisfy!(hasLength, R) && allSatisfy!(hasSlicing, R))
auto opSlice(size_t begin, size_t end) return scope
{
- auto result = this;
+ // force staticMap type conversion to Rebindable
+ static struct ResultRanges
+ {
+ staticMap!(Rebindable, Ranges) fields;
+ }
+ auto sourceI(size_t i)() => rebindable(this.source[i]);
+ auto resultRanges = ResultRanges(staticMap!(sourceI, aliasSeqOf!(R.length.iota))).fields;
+ size_t resultFrontIndex = this.frontIndex;
+ static if (bidirectional)
+ size_t resultBackIndex = this.backIndex;
sw: switch (frontIndex)
{
static foreach (i; 0 .. R.length)
{
case i:
- immutable len = result.source[i].length;
+ immutable len = resultRanges[i].length;
if (len <= begin)
{
- result.source[i] = result.source[i]
+ resultRanges[i] = resultRanges[i]
[len .. len];
begin -= len;
- result.frontIndex++;
+ resultFrontIndex++;
goto case;
}
else
{
- result.source[i] = result.source[i]
+ resultRanges[i] = resultRanges[i]
[begin .. len];
break sw;
}
@@ -1418,18 +1432,18 @@ if (Ranges.length > 0 &&
static foreach_reverse (i; 1 .. R.length + 1)
{
case i:
- immutable len = result.source[i-1].length;
+ immutable len = resultRanges[i-1].length;
if (len <= cut)
{
- result.source[i-1] = result.source[i-1]
+ resultRanges[i-1] = resultRanges[i-1]
[0 .. 0];
cut -= len;
- result.backIndex--;
+ resultBackIndex--;
goto case;
}
else
{
- result.source[i-1] = result.source[i-1]
+ resultRanges[i-1] = resultRanges[i-1]
[0 .. len - cut];
break sw2;
}
@@ -1445,7 +1459,10 @@ if (Ranges.length > 0 &&
assert(0, "Internal library error. Please report it.");
}
- return result;
+ static if (bidirectional)
+ return Result(resultRanges, resultFrontIndex, resultBackIndex);
+ else
+ return Result(resultRanges, resultFrontIndex);
}
}
return Result(rs);
@@ -1643,6 +1660,18 @@ pure @safe unittest
assert(equal(r, "foobar"));
}
+// https://issues.dlang.org/show_bug.cgi?id=23844
+pure @safe unittest
+{
+ struct S
+ {
+ immutable int value;
+ }
+
+ auto range = chain(only(S(5)), only(S(6)));
+ assert(range.array == [S(5), S(6)]);
+}
+
pure @safe nothrow @nogc unittest
{
// support non-copyable items
diff --git a/libphobos/src/std/system.d b/libphobos/src/std/system.d
index 55fcfd7..aa672a5 100644
--- a/libphobos/src/std/system.d
+++ b/libphobos/src/std/system.d
@@ -82,5 +82,77 @@ immutable
/// The endianness that the program was compiled for.
version (LittleEndian) Endian endian = Endian.littleEndian;
else Endian endian = Endian.bigEndian;
+ /++
+ Instruction Set Architecture.
+
+ Note:
+ This is intended for cases where you need a value representing the
+ instruction set architecture at runtime. If you're doing something
+ which should compile differently depending on instruction set
+ architecture, then please use `version (X86_64)`, `version (ARM)`,
+ etc.
+
+ See_Also:
+ $(DDSUBLINK spec/version,PredefinedVersions, Predefined Versions)
+ +/
+ enum ISA
+ {
+ x86, /// Intel and AMD 32-bit processors
+ x86_64, /// Intel and AMD 64-bit processors
+ arm, /// The ARM architecture (32-bit) (AArch32 et al)
+ aarch64, /// The Advanced RISC Machine architecture (64-bit)
+ asmJS, /// The asm.js intermediate programming language
+ avr, /// 8-bit Atmel AVR Microcontrollers
+ epiphany, /// The Epiphany architecture
+ ppc, /// The PowerPC architecture, 32-bit
+ ppc64, /// The PowerPC architecture, 64-bit
+ ia64, /// The Itanium architecture (64-bit)
+ mips32, /// The MIPS architecture, 32-bit
+ mips64, /// The MIPS architecture, 64-bit
+ msp430, /// The MSP430 architecture
+ nvptx, /// The Nvidia Parallel Thread Execution (PTX) architecture, 32-bit
+ nvptx64, /// The Nvidia Parallel Thread Execution (PTX) architecture, 64-bit
+ riscv32, /// The RISC-V architecture, 32-bit
+ riscv64, /// The RISC-V architecture, 64-bit
+ sparc, /// The SPARC architecture, 32-bit
+ sparc64, /// The SPARC architecture, 64-bit
+ s390, /// The System/390 architecture, 32-bit
+ systemZ, /// The System Z architecture, 64-bit
+ hppa, /// The HP PA-RISC architecture, 32-bit
+ hppa64, /// The HP PA-RISC architecture, 64-bit
+ sh, /// The SuperH architecture, 32-bit
+ webAssembly, /// The WebAssembly virtual ISA (instruction set architecture), 32-bit
+ alpha, /// The Alpha architecture
+ unknown, /// Unknown
+ }
+
+ /// The instruction set architecture that the program was compiled for.
+ version (X86) ISA instructionSetArchitecture = ISA.x86;
+ else version (X86_64) ISA instructionSetArchitecture = ISA.x86_64;
+ else version (ARM) ISA instructionSetArchitecture = ISA.arm;
+ else version (AArch64) ISA instructionSetArchitecture = ISA.aarch64;
+ else version (AsmJS) ISA instructionSetArchitecture = ISA.asmJS;
+ else version (AVR) ISA instructionSetArchitecture = ISA.avr;
+ else version (Epiphany) ISA instructionSetArchitecture = ISA.epiphany;
+ else version (PPC) ISA instructionSetArchitecture = ISA.ppc;
+ else version (PPC64) ISA instructionSetArchitecture = ISA.ppc64;
+ else version (IA64) ISA instructionSetArchitecture = ISA.ia64;
+ else version (MIPS32) ISA instructionSetArchitecture = ISA.mips32;
+ else version (MIPS64) ISA instructionSetArchitecture = ISA.mips64;
+ else version (MSP430) ISA instructionSetArchitecture = ISA.msp430;
+ else version (NVPTX) ISA instructionSetArchitecture = ISA.nvptx;
+ else version (NVPTX64) ISA instructionSetArchitecture = ISA.nvptx64;
+ else version (RISCV32) ISA instructionSetArchitecture = ISA.riscv32;
+ else version (RISCV64) ISA instructionSetArchitecture = ISA.riscv64;
+ else version (SPARC) ISA instructionSetArchitecture = ISA.sparc;
+ else version (SPARC64) ISA instructionSetArchitecture = ISA.sparc64;
+ else version (S390) ISA instructionSetArchitecture = ISA.s390;
+ else version (SystemZ) ISA instructionSetArchitecture = ISA.systemZ;
+ else version (HPPA) ISA instructionSetArchitecture = ISA.hppa;
+ else version (HPPA64) ISA instructionSetArchitecture = ISA.hppa64;
+ else version (SH) ISA instructionSetArchitecture = ISA.sh;
+ else version (WebAssembly) ISA instructionSetArchitecture = ISA.webAssembly;
+ else version (Alpha) ISA instructionSetArchitecture = ISA.alpha;
+ else ISA instructionSetArchitecture = ISA.unknown;
}
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index d267e71..0748d52 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -7406,11 +7406,11 @@ pure @system unittest
foreach (MyRefCounted; AliasSeq!(SafeRefCounted, RefCounted))
{
MyRefCounted!int* p;
+ auto rc1 = MyRefCounted!int(5);
+ p = &rc1;
+ assert(rc1 == 5);
+ assert(rc1._refCounted._store._count == 1);
{
- auto rc1 = MyRefCounted!int(5);
- p = &rc1;
- assert(rc1 == 5);
- assert(rc1._refCounted._store._count == 1);
auto rc2 = rc1;
assert(rc1._refCounted._store._count == 2);
// Reference semantics
@@ -7421,6 +7421,8 @@ pure @system unittest
rc1 = rc2;
assert(rc1._refCounted._store._count == 2);
}
+ // Artificially end scope of rc1 by calling ~this() explicitly
+ rc1.__xdtor();
assert(p._refCounted._store == null);
// [Safe]RefCounted as a member