xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/libdruntime/core/internal/array/capacity.d (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /**
2  This module contains support for controlling dynamic arrays' capacity and length
3 
4   Copyright: Copyright Digital Mars 2000 - 2019.
5   License: Distributed under the
6        $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7      (See accompanying file LICENSE)
8   Source: $(DRUNTIMESRC core/internal/_array/_capacity.d)
9 */
10 module core.internal.array.capacity;
11 
12 // HACK: `nothrow` and `pure` is faked.
13 private extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) nothrow pure;
14 private extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) nothrow pure;
15 
16 /*
17  * This template is needed because there need to be a `_d_arraysetlengthTTrace!Tarr` instance for every
18  * `_d_arraysetlengthT!Tarr`. By wrapping both of these functions inside of this template we force the
19  * compiler to create a instance of both function for every type that is used.
20  */
21 
22 /// Implementation of `_d_arraysetlengthT` and `_d_arraysetlengthTTrace`
23 template _d_arraysetlengthTImpl(Tarr : T[], T)
24 {
25     import core.internal.array.utils : _d_HookTraceImpl;
26 
27     private enum errorMessage = "Cannot resize arrays if compiling without support for runtime type information!";
28 
29     /**
30      * Resize dynamic array
31      * Params:
32      *  arr = the array that will be resized, taken as a reference
33      *  newlength = new length of array
34      * Returns:
35      *  The new length of the array
36      * Bugs:
37      *   The safety level of this function is faked. It shows itself as `@trusted pure nothrow` to not break existing code.
38      */
_d_arraysetlengthT(return scope ref Tarr arr,size_t newlength)39     size_t _d_arraysetlengthT(return scope ref Tarr arr, size_t newlength) @trusted pure nothrow
40     {
41         pragma(inline, false);
42         version (D_TypeInfo)
43         {
44             auto ti = typeid(Tarr);
45 
46             static if (__traits(isZeroInit, T))
47                 ._d_arraysetlengthT(ti, newlength, cast(void[]*)&arr);
48             else
49                 ._d_arraysetlengthiT(ti, newlength, cast(void[]*)&arr);
50 
51             return arr.length;
52         }
53         else
54             assert(0, errorMessage);
55     }
56 
57     /**
58     * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity).
59     * Bugs:
60     *  This function template was ported from a much older runtime hook that bypassed safety,
61     *  purity, and throwabilty checks. To prevent breaking existing code, this function template
62     *  is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations.
63     */
64     alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage);
65 }
66 
67 @safe unittest
68 {
69     struct S
70     {
71         float f = 1.0;
72     }
73 
74     int[] arr;
75     _d_arraysetlengthTImpl!(typeof(arr))._d_arraysetlengthT(arr, 16);
76     assert(arr.length == 16);
77     foreach (int i; arr)
78         assert(i == int.init);
79 
80     shared S[] arr2;
81     _d_arraysetlengthTImpl!(typeof(arr2))._d_arraysetlengthT(arr2, 16);
82     assert(arr2.length == 16);
83     foreach (s; arr2)
84         assert(s == S.init);
85 }
86