diff options
author | Ian Lance Taylor <iant@golang.org> | 2022-09-22 06:29:20 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2022-09-22 06:29:20 -0700 |
commit | 795cffe109e28b248a54b8ee583cbae48368c2a7 (patch) | |
tree | 0c12b075c51c0d5097f26953835ae540d9f2f501 /libphobos/libdruntime | |
parent | 9f62ed218fa656607740b386c0caa03e65dcd283 (diff) | |
parent | f35be1268c996d993ab0b4ff329734d467474445 (diff) | |
download | gcc-795cffe109e28b248a54b8ee583cbae48368c2a7.zip gcc-795cffe109e28b248a54b8ee583cbae48368c2a7.tar.gz gcc-795cffe109e28b248a54b8ee583cbae48368c2a7.tar.bz2 |
Merge from trunk revision f35be1268c996d993ab0b4ff329734d467474445.
Diffstat (limited to 'libphobos/libdruntime')
38 files changed, 1012 insertions, 692 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 6e25a9d..85fc49d 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -651389b52243dcadb338dd0c14dd27e7850cda8d +817610b16d0f0f469b9fbb28c000956fb910c43f 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..d828749 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -171,9 +171,10 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \ core/exception.d core/gc/config.d core/gc/gcinterface.d \ core/gc/registry.d core/int128.d core/internal/abort.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/appending.d core/internal/array/arrayassign.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/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 \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 24865fb..57660ee 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -192,10 +192,12 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \ core/demangle.lo core/exception.lo core/gc/config.lo \ core/gc/gcinterface.lo core/gc/registry.lo core/int128.lo \ core/internal/abort.lo core/internal/array/appending.lo \ + core/internal/array/arrayassign.lo \ core/internal/array/capacity.lo core/internal/array/casting.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 \ @@ -838,9 +840,10 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \ core/exception.d core/gc/config.d core/gc/gcinterface.d \ core/gc/registry.d core/int128.d core/internal/abort.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/appending.d core/internal/array/arrayassign.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/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 \ @@ -1200,6 +1203,8 @@ core/internal/array/$(am__dirstamp): @$(MKDIR_P) core/internal/array @: > core/internal/array/$(am__dirstamp) core/internal/array/appending.lo: core/internal/array/$(am__dirstamp) +core/internal/array/arrayassign.lo: \ + core/internal/array/$(am__dirstamp) core/internal/array/capacity.lo: core/internal/array/$(am__dirstamp) core/internal/array/casting.lo: core/internal/array/$(am__dirstamp) core/internal/array/comparison.lo: \ @@ -1208,6 +1213,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/demangle.d b/libphobos/libdruntime/core/demangle.d index cb8d433..ca87f90 100644 --- a/libphobos/libdruntime/core/demangle.d +++ b/libphobos/libdruntime/core/demangle.d @@ -2328,7 +2328,7 @@ char[] mangle(T)(return scope const(char)[] fqn, return scope char[] dst = null) @property bool empty() const { return !s.length; } - @property const(char)[] front() const return + @property const(char)[] front() const return scope { immutable i = indexOfDot(); return i == -1 ? s[0 .. $] : s[0 .. i]; diff --git a/libphobos/libdruntime/core/exception.d b/libphobos/libdruntime/core/exception.d index 81aa43b..a05a24c 100644 --- a/libphobos/libdruntime/core/exception.d +++ b/libphobos/libdruntime/core/exception.d @@ -14,7 +14,7 @@ void __switch_errorT()(string file = __FILE__, size_t line = __LINE__) @trusted { // Consider making this a compile time check. version (D_Exceptions) - throw staticError!SwitchError(file, line, null); + throw staticError!SwitchError("No appropriate switch clause found", file, line, null); else assert(0, "No appropriate switch clause found"); } @@ -446,16 +446,16 @@ class ForkError : Error */ class SwitchError : Error { - @safe pure nothrow @nogc this( string file = __FILE__, size_t line = __LINE__, Throwable next = null ) + @safe pure nothrow @nogc this( string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null ) { - super( "No appropriate switch clause found", file, line, next ); + super( msg, file, line, next ); } } unittest { { - auto se = new SwitchError(); + auto se = new SwitchError("No appropriate switch clause found"); assert(se.file == __FILE__); assert(se.line == __LINE__ - 2); assert(se.next is null); @@ -463,7 +463,7 @@ unittest } { - auto se = new SwitchError("hello", 42, new Exception("It's an Exception!")); + auto se = new SwitchError("No appropriate switch clause found", "hello", 42, new Exception("It's an Exception!")); assert(se.file == "hello"); assert(se.line == 42); assert(se.next !is null); 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/arrayassign.d b/libphobos/libdruntime/core/internal/array/arrayassign.d new file mode 100644 index 0000000..6132e68 --- /dev/null +++ b/libphobos/libdruntime/core/internal/array/arrayassign.d @@ -0,0 +1,304 @@ +module core.internal.array.arrayassign; + +// Force `enforceRawArraysConformable` to remain `pure` `@nogc` +private void enforceRawArraysConformable(const char[] action, const size_t elementSize, + const void[] a1, const void[] a2, const bool allowOverlap) @trusted @nogc pure nothrow +{ + import core.internal.util.array : enforceRawArraysConformable; + + alias Type = void function(const char[] action, const size_t elementSize, + const void[] a1, const void[] a2, in bool allowOverlap = false) @nogc pure nothrow; + (cast(Type)&enforceRawArraysConformable)(action, elementSize, a1, a2, allowOverlap); +} + +private template CopyElem(string CopyAction) +{ + const char[] CopyElem = "{\n" ~ q{ + memcpy(&tmp, cast(void*) &dst, elemSize); + } ~ CopyAction ~ q{ + auto elem = cast(Unqual!T*) &tmp; + destroy(*elem); + } ~ "}\n"; +} + +private template CopyArray(bool CanOverlap, string CopyAction) +{ + const char[] CopyArray = CanOverlap ? q{ + if (vFrom.ptr < vTo.ptr && vTo.ptr < vFrom.ptr + elemSize * vFrom.length) + foreach_reverse (i, ref dst; to) + } ~ CopyElem!(CopyAction) ~ q{ + else + foreach (i, ref dst; to) + } ~ CopyElem!(CopyAction) + : q{ + foreach (i, ref dst; to) + } ~ CopyElem!(CopyAction); +} + +private template ArrayAssign(string CopyLogic, string AllowOverLap) +{ + const char[] ArrayAssign = q{ + import core.internal.traits : hasElaborateCopyConstructor, Unqual; + import core.lifetime : copyEmplace; + import core.stdc.string : memcpy; + + void[] vFrom = (cast(void*) from.ptr)[0 .. from.length]; + void[] vTo = (cast(void*) to.ptr)[0 .. to.length]; + enum elemSize = T.sizeof; + + enforceRawArraysConformable("copy", elemSize, vFrom, vTo, } ~ AllowOverLap ~ q{); + + void[elemSize] tmp = void; + + } ~ CopyLogic ~ q{ + + return to; + }; +} + +/** + * Does array assignment (not construction) from another array of the same + * element type. Handles overlapping copies. Assumes the right hand side is an + * lvalue, + * + * Used for static array assignment with non-POD element types: + * --- + * struct S + * { + * ~this() {} // destructor, so not Plain Old Data + * } + * + * void main() + * { + * S[3] arr; + * S[3] lvalue; + * + * arr = lvalue; + * // Generates: + * // _d_arrayassign_l(arr[], lvalue[]), arr; + * } + * --- + * + * Params: + * to = destination array + * from = source array + * Returns: + * `to` + */ +Tarr _d_arrayassign_l(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted +{ + mixin(ArrayAssign!(q{ + static if (hasElaborateCopyConstructor!T) + } ~ CopyArray!(true, "copyEmplace(from[i], dst);") ~ q{ + else + } ~ CopyArray!(true, "memcpy(cast(void*) &dst, cast(void*) &from[i], elemSize);"), + "true")); +} + +@safe unittest +{ + int counter; + struct S + { + int val; + this(int val) { this.val = val; } + this(const scope ref S rhs) + { + val = rhs.val; + counter++; + } + } + + S[4] arr1; + S[4] arr2 = [S(0), S(1), S(2), S(3)]; + _d_arrayassign_l(arr1[], arr2[]); + + assert(counter == 4); + assert(arr1 == arr2); +} + +// copy constructor +@safe unittest +{ + int counter; + struct S + { + int val; + this(int val) { this.val = val; } + this(const scope ref S rhs) + { + val = rhs.val; + counter++; + } + } + + S[4] arr1; + S[4] arr2 = [S(0), S(1), S(2), S(3)]; + _d_arrayassign_l(arr1[], arr2[]); + + assert(counter == 4); + assert(arr1 == arr2); +} + +@safe nothrow unittest +{ + // Test that throwing works + int counter; + bool didThrow; + + struct Throw + { + int val; + this(this) + { + counter++; + if (counter == 2) + throw new Exception(""); + } + } + try + { + Throw[4] a; + Throw[4] b = [Throw(1), Throw(2), Throw(3), Throw(4)]; + _d_arrayassign_l(a[], b[]); + } + catch (Exception) + { + didThrow = true; + } + assert(didThrow); + assert(counter == 2); + + + // Test that `nothrow` works + didThrow = false; + counter = 0; + struct NoThrow + { + int val; + this(this) + { + counter++; + } + } + try + { + NoThrow[4] a; + NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)]; + _d_arrayassign_l(a[], b[]); + } + catch (Exception) + { + didThrow = false; + } + assert(!didThrow); + assert(counter == 4); +} + +/** + * Does array assignment (not construction) from another array of the same + * element type. Does not support overlapping copies. Assumes the right hand + * side is an rvalue, + * + * Used for static array assignment with non-POD element types: + * --- + * struct S + * { + * ~this() {} // destructor, so not Plain Old Data + * } + * + * void main() + * { + * S[3] arr; + * S[3] getRvalue() {return lvalue;} + * + * arr = getRvalue(); + * // Generates: + * // (__appendtmp = getRvalue), _d_arrayassign_l(arr[], __appendtmp), arr; + * } + * --- + * + * Params: + * to = destination array + * from = source array + * Returns: + * `to` + */ +Tarr _d_arrayassign_r(Tarr : T[], T)(return scope Tarr to, scope Tarr from) @trusted +{ + mixin(ArrayAssign!( + CopyArray!(false, "memcpy(cast(void*) &dst, cast(void*) &from[i], elemSize);"), + "false")); +} + +@safe unittest +{ + int counter; + struct S + { + int val; + this(int val) { this.val = val; } + this(const scope ref S rhs) + { + val = rhs.val; + counter++; + } + } + + S[4] arr1; + S[4] arr2 = [S(0), S(1), S(2), S(3)]; + _d_arrayassign_r(arr1[], arr2[]); + + assert(counter == 0); + assert(arr1 == arr2); +} + +// copy constructor +@safe unittest +{ + int counter; + struct S + { + int val; + this(int val) { this.val = val; } + this(const scope ref S rhs) + { + val = rhs.val; + counter++; + } + } + + S[4] arr1; + S[4] arr2 = [S(0), S(1), S(2), S(3)]; + _d_arrayassign_r(arr1[], arr2[]); + + assert(counter == 0); + assert(arr1 == arr2); +} + +@safe nothrow unittest +{ + // Test that `nothrow` works + bool didThrow = false; + int counter = 0; + struct NoThrow + { + int val; + this(this) + { + counter++; + } + } + try + { + NoThrow[4] a; + NoThrow[4] b = [NoThrow(1), NoThrow(2), NoThrow(3), NoThrow(4)]; + _d_arrayassign_r(a[], b[]); + } + catch (Exception) + { + didThrow = false; + } + assert(!didThrow); + assert(counter == 0); +} 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/array/equality.d b/libphobos/libdruntime/core/internal/array/equality.d index d3fdd65..c110d64 100644 --- a/libphobos/libdruntime/core/internal/array/equality.d +++ b/libphobos/libdruntime/core/internal/array/equality.d @@ -236,6 +236,33 @@ unittest static assert(!useMemcmp!(int[], int[])); } +// https://issues.dlang.org/show_bug.cgi?id=21094 +unittest +{ + static class C + { + int a; + } + static struct S + { + bool isValid; + C fib; + + inout(C) get() pure @safe @nogc nothrow inout + { + return isValid ? fib : C.init; + } + T opCast(T : C)() const { return null; } + + alias get this; + } + + auto foo(S[] lhs, S[] rhs) + { + return lhs == rhs; + } +} + // Returns a reference to an array element, eliding bounds check and // casting void to ubyte. pragma(inline, true) 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 2f8d3f3..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/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d index 3a7b753..fc5dc5d 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/socket.d +++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d @@ -188,10 +188,40 @@ version (linux) extern (D) inout(ubyte)* CMSG_DATA( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); } - private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc; - extern (D) inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc + version (CRuntime_Musl) { - return __cmsg_nxthdr(msg, cmsg); + extern (D) + { + private size_t __CMSG_LEN(inout(cmsghdr)* cmsg) pure nothrow @nogc + { + return (cmsg.cmsg_len + size_t.sizeof -1) & cast(size_t)(~(size_t.sizeof - 1)); + } + + private inout(cmsghdr)* __CMSG_NEXT(inout(cmsghdr)* cmsg) pure nothrow @nogc + { + return cmsg + __CMSG_LEN(cmsg); + } + + private inout(msghdr)* __MHDR_END(inout(msghdr)* mhdr) pure nothrow @nogc + { + return cast(inout(msghdr)*)(mhdr.msg_control + mhdr.msg_controllen); + } + + inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc + { + return cmsg.cmsg_len < cmsghdr.sizeof || + __CMSG_LEN(cmsg) + cmsghdr.sizeof >= __MHDR_END(msg) - cast(inout(msghdr)*)(cmsg) + ? cast(inout(cmsghdr)*) null : cast(inout(cmsghdr)*) __CMSG_NEXT(cmsg); + } + } + } + else + { + private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc; + extern (D) inout(cmsghdr)* CMSG_NXTHDR(inout(msghdr)* msg, inout(cmsghdr)* cmsg) pure nothrow @nogc + { + return __cmsg_nxthdr(msg, cmsg); + } } extern (D) inout(cmsghdr)* CMSG_FIRSTHDR( inout(msghdr)* mhdr ) pure nothrow @nogc 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..d842499 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -6,6 +6,7 @@ * $(TR $(TD Arrays) $(TD * $(MYREF assumeSafeAppend) * $(MYREF capacity) + * $(A #.dup.2, $(TT dup)) * $(MYREF idup) * $(MYREF reserve) * )) @@ -14,6 +15,7 @@ * $(MYREF byKeyValue) * $(MYREF byValue) * $(MYREF clear) + * $(MYREF dup) * $(MYREF get) * $(MYREF keys) * $(MYREF rehash) @@ -23,15 +25,15 @@ * )) * $(TR $(TD General) $(TD * $(MYREF destroy) - * $(MYREF dup) * $(MYREF hashOf) - * $(MYREF opEquals) + * $(MYREF imported) + * $(MYREF noreturn) * )) - * $(TR $(TD Types) $(TD + * $(TR $(TD Classes) $(TD * $(MYREF Error) * $(MYREF Exception) - * $(MYREF noreturn) * $(MYREF Object) + * $(MYREF opEquals) * $(MYREF Throwable) * )) * $(TR $(TD Type info) $(TD @@ -61,7 +63,11 @@ alias size_t = typeof(int.sizeof); alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0); alias sizediff_t = ptrdiff_t; // For backwards compatibility only. -alias noreturn = typeof(*null); /// bottom type +/** + * Bottom type. + * See $(DDSUBLINK spec/type, noreturn). + */ +alias noreturn = typeof(*null); alias hash_t = size_t; // For backwards compatibility only. alias equals_t = bool; // For backwards compatibility only. @@ -266,7 +272,9 @@ class Object the typeinfo name string compare. This is because of dmd's dll implementation. However, it can infer to @safe if your class' opEquals is. +/ -bool opEquals(LHS, RHS)(LHS lhs, RHS rhs) if (is(LHS : const Object) && is(RHS : const Object)) +bool opEquals(LHS, RHS)(LHS lhs, RHS rhs) +if ((is(LHS : const Object) || is(LHS : const shared Object)) && + (is(RHS : const Object) || is(RHS : const shared Object))) { static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs))) { @@ -505,6 +513,16 @@ unittest assert(obj1 != obj2); } +// https://issues.dlang.org/show_bug.cgi?id=23291 +@system unittest +{ + static shared class C { bool opEquals(const(shared(C)) rhs) const shared { return true;}} + const(C) c = new C(); + const(C)[] a = [c]; + const(C)[] b = [c]; + assert(a[0] == b[0]); +} + private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow; void setSameMutex(shared Object ownee, shared Object owner) @@ -3473,13 +3491,18 @@ ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init) private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); })); /*********************************** - * Looks up key; if it exists applies the update callable else evaluates the - * create callable and adds it to the associative array + * Calls `create` if `key` doesn't exist in the associative array, + * otherwise calls `update`. + * `create` returns a corresponding value for `key`. + * `update` accepts a key parameter. If it returns a value, the value is + * set for `key`. * Params: * aa = The associative array. * key = The key. - * create = The callable to apply on create. - * update = The callable to apply on update. + * create = The callable to create a value for `key`. + * Must return V. + * update = The callable to call if `key` exists. + * Takes a K argument, returns a V or void. */ void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update) if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof(update(aa[K.init])) == void))) @@ -3509,23 +3532,39 @@ if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof } /// -@system unittest +@safe unittest { - auto aa = ["k1": 1]; + int[string] aa; - aa.update("k1", { - return -1; // create (won't be executed) - }, (ref int v) { - v += 1; // update - }); - assert(aa["k1"] == 2); - - aa.update("k2", { - return 0; // create - }, (ref int v) { - v = -1; // update (won't be executed) - }); - assert(aa["k2"] == 0); + // create + aa.update("key", + () => 1, + (int) {} // not executed + ); + assert(aa["key"] == 1); + + // update value by ref + aa.update("key", + () => 0, // not executed + (ref int v) { + v += 1; + }); + assert(aa["key"] == 2); + + // update from return value + aa.update("key", + () => 0, // not executed + (int v) => v * 2 + ); + assert(aa["key"] == 4); + + // 'update' without changing value + aa.update("key", + () => 0, // not executed + (int) { + // do something else + }); + assert(aa["key"] == 4); } @safe unittest @@ -3765,6 +3804,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 +3826,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 +3834,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 +3855,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 +4042,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 +4058,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 @@ -4910,6 +4615,8 @@ public import core.internal.array.casting: __ArrayCast; public import core.internal.array.concatenation : _d_arraycatnTXImpl; public import core.internal.array.construction : _d_arrayctor; public import core.internal.array.construction : _d_arraysetctor; +public import core.internal.array.arrayassign : _d_arrayassign_l; +public import core.internal.array.arrayassign : _d_arrayassign_r; public import core.internal.array.capacity: _d_arraysetlengthTImpl; public import core.internal.dassert: _d_assert_fail; diff --git a/libphobos/libdruntime/rt/arrayassign.d b/libphobos/libdruntime/rt/arrayassign.d index c9db2fc..c9e2b15 100644 --- a/libphobos/libdruntime/rt/arrayassign.d +++ b/libphobos/libdruntime/rt/arrayassign.d @@ -19,171 +19,6 @@ private debug(PRINTF) import core.stdc.stdio; } -/* - * Superseded array assignment hook. Does not take into account destructors: - * https://issues.dlang.org/show_bug.cgi?id=13661 - * Kept for backward binary compatibility. This function can be removed in the future. - */ -extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to) -{ - debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize); - - immutable elementSize = ti.tsize; - - // Need a temporary buffer tmp[] big enough to hold one element - void[16] buf = void; - void* ptmp = (elementSize > buf.sizeof) ? malloc(elementSize) : buf.ptr; - scope (exit) - { - if (ptmp != buf.ptr) - free(ptmp); - } - return _d_arrayassign_l(ti, from, to, ptmp); -} - -/** -Does array assignment (not construction) from another array of the same -element type. - -Handles overlapping copies. - -The `_d_arrayassign_l` variant assumes the right hand side is an lvalue, -while `_d_arrayassign_r` assumes it's an rvalue, which means it doesn't have to call copy constructors. - -Used for static array assignment with non-POD element types: ---- -struct S -{ - ~this() {} // destructor, so not Plain Old Data -} - -void main() -{ - S[3] arr; - S[3] lvalue; - - arr = lvalue; - // Generates: - // S _tmp; - // _d_arrayassign_l(typeid(S), (cast(void*) lvalue.ptr)[0..lvalue.length], (cast(void*) arr.ptr)[0..arr.length], &_tmp); - - S[3] getRvalue() {return lvalue;} - arr = getRvalue(); - // Similar, but `_d_arrayassign_r` -} ---- - -Params: - ti = `TypeInfo` of the array element type. - dst = target memory. Its `.length` is equal to the element count, not byte length. - src = source memory. Its `.length` is equal to the element count, not byte length. - ptmp = Temporary memory for element swapping, must have capacity of `ti.tsize` bytes. -Returns: `dst` -*/ -extern (C) void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp) -{ - debug(PRINTF) printf("_d_arrayassign_l(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize); - - immutable elementSize = ti.tsize; - - enforceRawArraysConformable("copy", elementSize, src, dst, true); - - if (src.ptr < dst.ptr && dst.ptr < src.ptr + elementSize * src.length) - { - // If dst is in the middle of src memory, use reverse order. - for (auto i = dst.length; i--; ) - { - void* pdst = dst.ptr + i * elementSize; - void* psrc = src.ptr + i * elementSize; - memcpy(ptmp, pdst, elementSize); - memcpy(pdst, psrc, elementSize); - ti.postblit(pdst); - ti.destroy(ptmp); - } - } - else - { - // Otherwise, use normal order. - foreach (i; 0 .. dst.length) - { - void* pdst = dst.ptr + i * elementSize; - void* psrc = src.ptr + i * elementSize; - memcpy(ptmp, pdst, elementSize); - memcpy(pdst, psrc, elementSize); - ti.postblit(pdst); - ti.destroy(ptmp); - } - } - return dst; -} - -unittest // Bugzilla 14024 -{ - string op; - - struct S - { - char x = 'x'; - this(this) { op ~= x-0x20; } // upper case - ~this() { op ~= x; } // lower case - } - - S[4] mem; - ref S[2] slice(int a, int b) { return mem[a .. b][0 .. 2]; } - - op = null; - mem[0].x = 'a'; - mem[1].x = 'b'; - mem[2].x = 'x'; - mem[3].x = 'y'; - slice(0, 2) = slice(2, 4); // [ab] = [xy] - assert(op == "XaYb", op); - - op = null; - mem[0].x = 'x'; - mem[1].x = 'y'; - mem[2].x = 'a'; - mem[3].x = 'b'; - slice(2, 4) = slice(0, 2); // [ab] = [xy] - assert(op == "XaYb", op); - - op = null; - mem[0].x = 'a'; - mem[1].x = 'b'; - mem[2].x = 'c'; - slice(0, 2) = slice(1, 3); // [ab] = [bc] - assert(op == "BaCb", op); - - op = null; - mem[0].x = 'x'; - mem[1].x = 'y'; - mem[2].x = 'z'; - slice(1, 3) = slice(0, 2); // [yz] = [xy] - assert(op == "YzXy", op); -} - -/// ditto -extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp) -{ - debug(PRINTF) printf("_d_arrayassign_r(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize); - - immutable elementSize = ti.tsize; - - enforceRawArraysConformable("copy", elementSize, src, dst, false); - - // Always use normal order, because we can assume that - // the rvalue src has no overlapping with dst. - foreach (i; 0 .. dst.length) - { - void* pdst = dst.ptr + i * elementSize; - void* psrc = src.ptr + i * elementSize; - memcpy(ptmp, pdst, elementSize); - memcpy(pdst, psrc, elementSize); - ti.destroy(ptmp); - } - return dst; -} - /** Set all elements of an array to a single value. 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(); } - |