mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
D front-end changes: - Typesafe variadic class parameters have been deprecated. D runtime changes: - Added `entry' field to TypeInfo_AssociativeArray. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 53a1cc8d13. * d-tree.h (create_typeinfo): Change second parameter to Scope *. (speculative_type_p): Remove prototype. * d-frontend.cc (getTypeInfoType): Adjust. * decl.cc: Include dmd/typinf.h. (DeclVisitor::visit (TypeInfoDeclaration *)): Update for new front-end interface. * typeinfo.cc (create_typeinfo): Likewise. (class SpeculativeTypeVisitor): Remove class. (speculative_type_p): Remove function. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 53a1cc8d13. gcc/testsuite/ChangeLog: * gdc.dg/pr100967.d: Adjust error message.
195 lines
5.0 KiB
D
195 lines
5.0 KiB
D
/**
|
|
This module contains support for controlling dynamic arrays' concatenation
|
|
Copyright: Copyright Digital Mars 2000 - 2019.
|
|
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/_concatenation.d)
|
|
*/
|
|
module core.internal.array.concatenation;
|
|
|
|
/**
|
|
* Concatenate the arrays inside of `froms`.
|
|
* `_d_arraycatnTX(a, b, c)` means `a ~ b ~ c`.
|
|
*
|
|
* Params:
|
|
* froms = Arrays to be concatenated.
|
|
* Returns:
|
|
* A newly allocated array that contains all the elements from `froms`.
|
|
*/
|
|
Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted
|
|
{
|
|
import core.internal.array.capacity : _d_arraysetlengthTImpl;
|
|
import core.internal.traits : hasElaborateCopyConstructor, Unqual;
|
|
import core.lifetime : copyEmplace;
|
|
import core.stdc.string : memcpy;
|
|
|
|
Tret res;
|
|
size_t totalLen;
|
|
|
|
alias T = typeof(res[0]);
|
|
enum elemSize = T.sizeof;
|
|
enum hasPostblit = __traits(hasPostblit, T);
|
|
|
|
static foreach (from; froms)
|
|
static if (is (typeof(from) : T))
|
|
totalLen++;
|
|
else
|
|
totalLen += from.length;
|
|
|
|
if (totalLen == 0)
|
|
return res;
|
|
|
|
// We cannot use this, because it refuses to work if the array type has disabled default construction.
|
|
// res.length = totalLen;
|
|
// Call the runtime function directly instead.
|
|
// TODO: once `__arrayAlloc` is templated, call that instead.
|
|
version (D_ProfileGC)
|
|
{
|
|
// TODO: forward file, line, name from _d_arraycatnTXTrace
|
|
_d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthTTrace(
|
|
res, totalLen, __FILE__, __LINE__, __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
_d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthT(res, totalLen);
|
|
}
|
|
|
|
/* Currently, if both a postblit and a cpctor are defined, the postblit is
|
|
* used. If this changes, the condition below will have to be adapted.
|
|
*/
|
|
static if (hasElaborateCopyConstructor!T && !hasPostblit)
|
|
{
|
|
size_t i = 0;
|
|
foreach (ref from; froms)
|
|
static if (is(typeof(from) : T))
|
|
copyEmplace(cast(T) from, res[i++]);
|
|
else
|
|
{
|
|
if (from.length)
|
|
foreach (ref elem; from)
|
|
copyEmplace(cast(T) elem, res[i++]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto resptr = cast(Unqual!T *) res;
|
|
foreach (ref from; froms)
|
|
static if (is (typeof(from) : T))
|
|
memcpy(resptr++, cast(Unqual!T *) &from, elemSize);
|
|
else
|
|
{
|
|
const len = from.length;
|
|
if (len)
|
|
{
|
|
memcpy(resptr, cast(Unqual!T *) from, len * elemSize);
|
|
resptr += len;
|
|
}
|
|
}
|
|
|
|
static if (hasPostblit)
|
|
foreach (ref elem; res)
|
|
(cast() elem).__xpostblit();
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
// postblit
|
|
@safe unittest
|
|
{
|
|
int counter;
|
|
struct S
|
|
{
|
|
int val;
|
|
this(this)
|
|
{
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
S[] arr1 = [S(0), S(1), S(2)];
|
|
S[] arr2 = [];
|
|
S[] arr3 = [S(6), S(7), S(8)];
|
|
S elem = S(9);
|
|
S[] result = _d_arraycatnTX!(S[])(arr1, arr2, arr3, elem);
|
|
|
|
assert(counter == 7);
|
|
assert(result == [S(0), S(1), S(2), S(6), S(7), S(8), S(9)]);
|
|
}
|
|
|
|
// copy constructor
|
|
@safe unittest
|
|
{
|
|
int counter;
|
|
struct S
|
|
{
|
|
int val;
|
|
this(ref return scope S rhs)
|
|
{
|
|
val = rhs.val;
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
S[] arr1 = [S(0), S(1), S(2)];
|
|
S[] arr2 = [S(3), S(4), S(5)];
|
|
S[] arr3 = [S(6), S(7), S(8)];
|
|
S elem = S(9);
|
|
S[] result = _d_arraycatnTX!(S[])(arr1, elem, arr2, arr3);
|
|
|
|
assert(counter == 10);
|
|
assert(result == [S(0), S(1), S(2), S(9), S(3), S(4), S(5), S(6), S(7), S(8)]);
|
|
}
|
|
|
|
// throwing
|
|
@safe unittest
|
|
{
|
|
int counter;
|
|
bool didThrow;
|
|
struct S
|
|
{
|
|
int val;
|
|
this(this)
|
|
{
|
|
counter++;
|
|
if (counter == 4)
|
|
throw new Exception("");
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
S[] arr1 = [S(0), S(1), S(2)];
|
|
S[] arr2 = [S(3), S(4), S(5)];
|
|
_d_arraycatnTX!(S[])(arr1, arr2);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
didThrow = true;
|
|
}
|
|
|
|
assert(counter == 4);
|
|
assert(didThrow);
|
|
}
|
|
|
|
version (D_ProfileGC)
|
|
{
|
|
/**
|
|
* TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concatenation).
|
|
*/
|
|
Tret _d_arraycatnTXTrace(Tret, Tarr...)(scope auto ref Tarr froms, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted
|
|
{
|
|
version (D_TypeInfo)
|
|
{
|
|
import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;
|
|
mixin(TraceHook!(Tarr.stringof, "_d_arraycatnTX"));
|
|
|
|
import core.lifetime: forward;
|
|
return _d_arraycatnTX!Tret(forward!froms);
|
|
}
|
|
else
|
|
assert(0, "Cannot concatenate arrays if compiling without support for runtime type information!");
|
|
}
|
|
}
|