Skip to content

Commit

Permalink
fix issue 18937 - [REG 2.080.0] std.experimental.allocator: compiling…
Browse files Browse the repository at this point in the history
… `make` needs an unreasonable amount of memory for structs that contain static arrays
  • Loading branch information
aG0aep6G committed Jun 3, 2018
1 parent 300bb9c commit 86af9e6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
39 changes: 29 additions & 10 deletions std/experimental/allocator/common.d
Expand Up @@ -772,18 +772,23 @@ private template isAllZeroBits(T, T value)
else static if (is(typeof(value is 0)))
enum isAllZeroBits = value is 0;
else static if (isStaticArray!(typeof(value)))
enum isAllZeroBits = ()
{
alias E = typeof(value[0]);
static if (value.length == 0)
enum isAllZeroBits = true;
else static if (!isAllZeroBits!(E, value[0]))
enum isAllZeroBits = false;
else static if (value.length == 1 || value == T.init)
enum isAllZeroBits = .isAllZeroBits!(E, value[0]);
else
{
bool b = true;
// Use index so this works when T.length is 0.
static foreach (i; 0 .. T.length)
{
b &= isAllZeroBits!(typeof(value[i]), value[i]);
if (b == false) return b;
}
enum tail = value[1 .. $];
enum n = tail.length / 2;
enum isAllZeroBits = .isAllZeroBits!(E[n], tail[0 .. n]) &&
.isAllZeroBits!(E[tail.length - n], tail[n .. $]);
}

return b;
}();
}
else static if (is(typeof(value) == struct) || is(typeof(value) == union))
enum isAllZeroBits = ()
{
Expand Down Expand Up @@ -822,6 +827,20 @@ private template isAllZeroBits(T, T value)
static assert(isAllZeroBits!(Object, null));
}

@nogc nothrow pure @safe unittest // large static arrays
{
import std.meta: Repeat;
enum n = 16 * 1024;

static assert(isAllZeroBits!(ubyte[n], (ubyte[n]).init));
static assert(!isAllZeroBits!(ubyte[n], [Repeat!(n, 1)]));
static assert(!isAllZeroBits!(ubyte[n], [1, Repeat!(n - 1, 0)]));
static assert(!isAllZeroBits!(ubyte[n], [Repeat!(n - 1, 0), 1]));

static assert(!isAllZeroBits!(char[n], (char[n]).init));
static assert(isAllZeroBits!(char[n], [Repeat!(n, 0)]));
}

/+
Is the representation of T.init known at compile time to consist of nothing but
zero bits? Padding between a struct's fields is not considered.
Expand Down
16 changes: 16 additions & 0 deletions std/experimental/allocator/package.d
Expand Up @@ -1378,6 +1378,22 @@ nothrow @safe @nogc unittest
"Don't allow zero-ctor-args `make` for structs with `@disable this();`");
}

@safe unittest // issue 18937
{
static struct S
{
ubyte[16 * 1024] data;
}

static struct SomeAllocator
{
ubyte[] allocate(size_t) { return []; }
void deallocate(void[]) {}
}

auto x = SomeAllocator().make!S();
}

private void fillWithMemcpy(T)(scope void[] array, auto ref T filler) nothrow
if (T.sizeof == 1)
{
Expand Down

0 comments on commit 86af9e6

Please sign in to comment.