1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// PERMUTE_ARGS:
struct Field
{
this(this) @safe @nogc pure nothrow {}
}
struct Counter
{
static size_t cnt;
this(this) @safe @nogc nothrow { ++cnt; }
}
struct Foo
{
this(this) @safe @nogc pure nothrow {}
Field field;
}
void test1() @safe @nogc pure nothrow
{
Foo foo;
foo.__xpostblit();
}
static assert(__traits(hasMember, Foo, "__xpostblit"));
//
struct FieldPostblit
{
Counter counter;
}
struct AggrPostblit
{
static size_t cnt;
this(this) @safe @nogc nothrow { ++cnt; }
}
struct MixedPostblit
{
static size_t cnt;
Counter counter;
this(this) @safe @nogc nothrow { ++cnt; }
}
struct SNoPostblit {}
class CNoPostblit {}
static assert(!__traits(hasMember, SNoPostblit, "__xpostblit"));
static assert(!__traits(hasMember, CNoPostblit, "__xpostblit"));
void test2() @safe @nogc nothrow
{
FieldPostblit a;
assert(Counter.cnt == 0);
a.__xpostblit();
assert(Counter.cnt == 1);
AggrPostblit b;
assert(AggrPostblit.cnt == 0);
b.__xpostblit();
assert(AggrPostblit.cnt == 1);
Counter.cnt = 0;
MixedPostblit c;
assert(MixedPostblit.cnt == 0);
assert(Counter.cnt == 0);
c.__xpostblit();
assert(MixedPostblit.cnt == 1);
assert(Counter.cnt == 1);
}
/****************************************************************
This test is intended to verify the exception safety of field
postblits
*/
string trace = "";
struct FieldThrow
{
string name;
this(string n)
{
name = n;
}
bool throwExcept;
this(this)
{
if (throwExcept)
{
throw new Exception("");
}
}
~this() { trace ~= name ~ ".dtor"; }
}
struct S
{
auto f1 = FieldThrow("f1");
FieldThrow[2] f2f3= [FieldThrow("f2"), FieldThrow("f3")];
auto f4 = FieldThrow("f4");
}
void test3()
{
trace = "";
S s1;
// Cause `s1.f4`'s postblit to throw
s1.f4.throwExcept = true;
try
{
// `s`'s postblit will be a combination of `f1`, `f2f3`, and `f4`'s
// postblit in that order. However, `f4`'s postblit will throw,
// causing `s1.f2f3` and `s1.f1`'s destructors to execute in that
// order
S s2 = s1;
}
catch(Exception ex){ }
// Confirm the field destructors were called and were called in the
// corrrect order
assert(trace == "f3.dtor" ~ "f2.dtor" ~ "f1.dtor");
}
/****************************************************************************/
void main()
{
test1();
test2();
test3();
}
|