1387 lines
25 KiB
D
1387 lines
25 KiB
D
// RUNNABLE_PHOBOS_TEST
|
|
// PERMUTE_ARGS: -fPIC
|
|
|
|
/* Test associative arrays */
|
|
|
|
extern(C) int printf(const char*, ...);
|
|
extern(C) int memcmp(const void *s1, const void *s2, size_t n);
|
|
|
|
import core.memory; // for GC.collect
|
|
import std.random; // for uniform random numbers
|
|
|
|
/************************************************/
|
|
|
|
int nametable[char[]];
|
|
|
|
void insert(string name, int value)
|
|
{
|
|
nametable[name] = value;
|
|
}
|
|
|
|
int retrieve(string name)
|
|
{
|
|
return nametable[name];
|
|
}
|
|
|
|
void test1()
|
|
{ int v;
|
|
|
|
printf("test1.a\n");
|
|
insert("hello", 1);
|
|
printf("test1.b\n");
|
|
insert("world", 2);
|
|
printf("test1.c\n");
|
|
v = retrieve("hello");
|
|
assert(v == 1);
|
|
v = retrieve("world");
|
|
assert(v == 2);
|
|
v = retrieve("world");
|
|
assert(v == 2);
|
|
|
|
nametable.rehash;
|
|
v = retrieve("world");
|
|
assert(v == 2);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
|
|
void test2()
|
|
{
|
|
int[string] aa;
|
|
string[] keys;
|
|
int[] values;
|
|
|
|
printf("test2()\n");
|
|
|
|
/*************/
|
|
|
|
assert(aa == null);
|
|
assert(aa.length == 0);
|
|
|
|
keys = aa.keys;
|
|
assert(keys.length == 0);
|
|
|
|
values = aa.values;
|
|
assert(values.length == 0);
|
|
|
|
aa.rehash;
|
|
assert(aa.length == 0);
|
|
|
|
/*************/
|
|
|
|
aa["hello"] = 3;
|
|
assert(aa["hello"] == 3);
|
|
aa["hello"]++;
|
|
assert(aa["hello"] == 4);
|
|
|
|
assert(aa.length == 1);
|
|
|
|
keys = aa.keys;
|
|
assert(keys.length == 1);
|
|
assert(memcmp(keys[0].ptr, cast(char*)"hello", 5) == 0);
|
|
|
|
values = aa.values;
|
|
assert(values.length == 1);
|
|
assert(values[0] == 4);
|
|
|
|
aa.rehash;
|
|
assert(aa.length == 1);
|
|
assert(aa["hello"] == 4);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test4()
|
|
{
|
|
int[const(ubyte)[]] b;
|
|
const(ubyte)[] x;
|
|
b[x] = 3;
|
|
assert(b[x] == 3);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test5()
|
|
{
|
|
int[immutable(short)[]] b;
|
|
immutable(short)[] x;
|
|
b[x] = 3;
|
|
assert(b[x] == 3);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test6()
|
|
{
|
|
int[const(int)[]] b;
|
|
const(int)[] x;
|
|
b[x] = 3;
|
|
assert(b[x] == 3);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test7()
|
|
{
|
|
int[immutable(uint)[]] b;
|
|
immutable(uint)[] x;
|
|
b[x] = 3;
|
|
assert(b[x] == 3);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test8()
|
|
{
|
|
int[immutable(long)[]] b;
|
|
immutable(long)[] x;
|
|
b[x] = 3;
|
|
assert(b[x] == 3);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test9()
|
|
{
|
|
int[immutable(ulong)[]] b;
|
|
immutable(ulong)[] x;
|
|
b[x] = 3;
|
|
assert(b[x] == 3);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
class A10 {}
|
|
|
|
int[immutable(A10)[]] foo10;
|
|
|
|
void test10()
|
|
{
|
|
auto key = new immutable(A10)[2];
|
|
|
|
cast()(key[0]) = new A10();
|
|
foo10[key] = 0;
|
|
assert(key in foo10);
|
|
assert(!(key !in foo10));
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
struct Value
|
|
{
|
|
uint x,y,z,t;
|
|
}
|
|
|
|
struct Key
|
|
{
|
|
int a,b,c,d;
|
|
|
|
static int hash, cmp, equals;
|
|
|
|
size_t toHash() const
|
|
{
|
|
hash = 1;
|
|
return a + b + c + d;
|
|
}
|
|
|
|
int opCmp(ref const Key s) const
|
|
{
|
|
cmp = 1;
|
|
int x;
|
|
|
|
x = a - s.a;
|
|
if (x == 0)
|
|
{ x = b - s.b;
|
|
if (x == 0)
|
|
{ x = c - s.c;
|
|
if (x == 0)
|
|
x = d - s.d;
|
|
}
|
|
}
|
|
return x;
|
|
}
|
|
|
|
bool opEquals(ref const Key s) const
|
|
{
|
|
printf("opEquals()\n");
|
|
equals = 1;
|
|
return (a == s.a && b == s.b && c == s.c && d == s.d);
|
|
}
|
|
}
|
|
|
|
void test11()
|
|
{
|
|
Value[Key] table;
|
|
|
|
Value* p;
|
|
Value v;
|
|
Value r;
|
|
Key k;
|
|
|
|
v.x = 7;
|
|
v.y = 8;
|
|
v.z = 9;
|
|
v.t = 10;
|
|
|
|
k.a = 1;
|
|
k.b = 2;
|
|
k.c = 3;
|
|
k.d = 4;
|
|
|
|
p = k in table;
|
|
assert(!p);
|
|
|
|
table[k] = v;
|
|
p = k in table;
|
|
assert(p);
|
|
|
|
table.rehash;
|
|
p = k in table;
|
|
assert(p);
|
|
|
|
r = table[k];
|
|
assert(v == r);
|
|
|
|
table.remove(k);
|
|
assert(!(k in table));
|
|
|
|
printf("Key.hash = %d\n", Key.hash);
|
|
assert(Key.hash == 1);
|
|
printf("Key.cmp = %d\n", Key.cmp);
|
|
printf("Key.equals = %d\n", Key.equals);
|
|
assert(Key.cmp == 1 && !Key.equals || !Key.cmp && Key.equals == 1);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
struct S12
|
|
{
|
|
byte number;
|
|
char[] description;
|
|
char[] font_face;
|
|
byte font_size;
|
|
ushort flags;
|
|
int colour_back;
|
|
int colour_fore;
|
|
byte charset;
|
|
}
|
|
|
|
void test12()
|
|
{
|
|
S12[] x;
|
|
printf("size %d\n",S12.sizeof);
|
|
printf("align %d\n",S12.alignof);
|
|
printf("offset %d\n",S12.description.offsetof);
|
|
|
|
for (int i=0;i<3;i++) {
|
|
S12 s;
|
|
s.font_face="font face".dup;
|
|
x ~= s;
|
|
}
|
|
|
|
/* works fine
|
|
S12 s;
|
|
s.font_face="font face".dup;
|
|
x ~= s;
|
|
s.font_face="font face".dup;
|
|
x ~= s;
|
|
s.font_face="font face".dup;
|
|
x ~= s;
|
|
s.font_face="font face".dup;
|
|
x ~= s;
|
|
*/
|
|
GC.collect();
|
|
printf("%.*s\n",x[0].font_face.length,x[0].font_face.ptr);
|
|
printf("%.*s\n",x[1].font_face.length,x[1].font_face.ptr);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
void test13()
|
|
{
|
|
int[string] array;
|
|
array["eins"]=1;
|
|
array["zwei"]=2;
|
|
array["drei"]=3;
|
|
|
|
assert(array.length==3);
|
|
|
|
int[string] rehashed=array.rehash;
|
|
assert(rehashed is array);
|
|
|
|
string[] key = array.keys;
|
|
assert(key.length==3);
|
|
|
|
bool have[3];
|
|
|
|
assert(!have[0]);
|
|
assert(!have[1]);
|
|
assert(!have[2]);
|
|
|
|
foreach(string value; key){
|
|
switch(value){
|
|
case "eins":{
|
|
have[0]=true;
|
|
break;
|
|
}case "zwei":{
|
|
have[1]=true;
|
|
break;
|
|
}case "drei":{
|
|
have[2]=true;
|
|
break;
|
|
}default:{
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
assert(have[0]);
|
|
assert(have[1]);
|
|
assert(have[2]);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test14()
|
|
{
|
|
int[char[]] aa;
|
|
|
|
aa["hello"] = 3;
|
|
assert(aa["hello"] == 3);
|
|
assert("hello" in aa);
|
|
//delete aa["hello"];
|
|
aa.remove("hello");
|
|
assert(!("hello" in aa));
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
class SomeClass
|
|
{
|
|
this(char value)
|
|
{
|
|
printf("class created\n");
|
|
_value = value;
|
|
}
|
|
|
|
~this()
|
|
{
|
|
printf("class killed (%d)\n", _value);
|
|
}
|
|
|
|
char value()
|
|
{
|
|
return _value;
|
|
}
|
|
|
|
private
|
|
{
|
|
char _value;
|
|
}
|
|
}
|
|
|
|
char[] allChars = [ 'a', 'b', 'c', 'e', 'z', 'q', 'x' ];
|
|
|
|
SomeClass[char] _chars;
|
|
|
|
void _realLoad()
|
|
{
|
|
printf("Loading...\n");
|
|
foreach(char ch; allChars)
|
|
{
|
|
_chars[ch] = new SomeClass(ch);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void test15()
|
|
{
|
|
_realLoad();
|
|
int j;
|
|
|
|
for (int i = 0; i < 10000; i++)
|
|
{
|
|
foreach(char ch; allChars)
|
|
{
|
|
SomeClass obj = _chars[ch];
|
|
j += obj.value;
|
|
}
|
|
GC.collect();
|
|
}
|
|
printf("j = %d\n", j);
|
|
assert(j == 7500000);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
void test16()
|
|
{
|
|
int[int] aa;
|
|
|
|
Random gen;
|
|
for (int i = 0; i < 50000; i++)
|
|
{
|
|
int key = uniform(0, int.max, gen);
|
|
int value = uniform(0, int.max, gen);
|
|
|
|
aa[key] = value;
|
|
}
|
|
|
|
int[] keys = aa.keys;
|
|
assert(keys.length == aa.length);
|
|
|
|
int j;
|
|
foreach (k; keys)
|
|
{
|
|
assert(k in aa);
|
|
j += aa[k];
|
|
}
|
|
printf("test16 = %d\n", j);
|
|
|
|
int m;
|
|
foreach (k, v; aa)
|
|
{
|
|
assert(k in aa);
|
|
assert(aa[k] == v);
|
|
m += v;
|
|
}
|
|
assert(j == m);
|
|
|
|
m = 0;
|
|
foreach (v; aa)
|
|
{
|
|
m += v;
|
|
}
|
|
assert(j == m);
|
|
|
|
int[] values = aa.values;
|
|
assert(values.length == aa.length);
|
|
|
|
foreach(k; keys)
|
|
{
|
|
aa.remove(k);
|
|
}
|
|
assert(aa.length == 0);
|
|
|
|
for (int i = 0; i < 1000; i++)
|
|
{
|
|
int key2 = uniform(0, int.max, gen);
|
|
int value2 = uniform(0, int.max, gen);
|
|
|
|
aa[key2] = value2;
|
|
}
|
|
foreach(k; aa)
|
|
{
|
|
if (k < 1000)
|
|
break;
|
|
}
|
|
foreach(k, v; aa)
|
|
{
|
|
if (k < 1000)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void dummy17()
|
|
{
|
|
}
|
|
|
|
int bb17[string];
|
|
|
|
int foo17()
|
|
{
|
|
foreach(string s, int i; bb17)
|
|
{
|
|
dummy17();
|
|
}
|
|
|
|
bb17["a"] = 1;
|
|
|
|
foreach(int b; bb17)
|
|
{
|
|
try{
|
|
throw new Error("foo");
|
|
}catch(Error e){
|
|
assert(e);
|
|
return 0;
|
|
}catch(Throwable){
|
|
assert(0);
|
|
}
|
|
assert(0);
|
|
}
|
|
|
|
assert(0);
|
|
}
|
|
|
|
void test17()
|
|
{
|
|
int i = foo17();
|
|
printf("foo17 = %d\n", i);
|
|
assert(i == 0);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test18()
|
|
{
|
|
int[uint] aa;
|
|
|
|
aa[1236448822] = 0;
|
|
aa[2716102924] = 1;
|
|
aa[ 315901071] = 2;
|
|
|
|
aa.remove(1236448822);
|
|
printf("%d\n", aa[2716102924]);
|
|
assert(aa[2716102924] == 1);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
void test19()
|
|
{
|
|
immutable(char[5])[int] aa = ([3:"hello", 4:"betty"]);
|
|
|
|
assert(aa[3] == "hello");
|
|
assert(aa[4] == "betty");
|
|
|
|
auto keys = aa.keys;
|
|
printf("%d\n", keys[0]);
|
|
printf("%d\n", keys[1]);
|
|
|
|
auto vs = aa.values;
|
|
printf("%.*s\n", vs[0].length, vs[0].ptr);
|
|
printf("%.*s\n", vs[1].length, vs[1].ptr);
|
|
|
|
string aavalue_typeid = typeid(typeof(aa.values)).toString();
|
|
printf("%.*s\n", aavalue_typeid.length, aavalue_typeid.ptr);
|
|
|
|
printf("%.*s\n", aa[3].length, aa[3].ptr);
|
|
printf("%.*s\n", aa[4].length, aa[4].ptr);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test20()
|
|
{
|
|
string[int] aa = ([3:"hello", 4:"betty"]);
|
|
|
|
assert(aa[3] == "hello");
|
|
assert(aa[4] == "betty");
|
|
|
|
auto keys = aa.keys;
|
|
printf("%d\n", keys[0]);
|
|
printf("%d\n", keys[1]);
|
|
|
|
auto values = aa.values;
|
|
printf("%.*s\n", values[0].length, values[0].ptr);
|
|
printf("%.*s\n", values[1].length, values[1].ptr);
|
|
|
|
string aavalue_typeid = typeid(typeof(aa.values)).toString();
|
|
printf("%.*s\n", aavalue_typeid.length, aavalue_typeid.ptr);
|
|
|
|
printf("%.*s\n", aa[3].length, aa[3].ptr);
|
|
printf("%.*s\n", aa[4].length, aa[4].ptr);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test21()
|
|
{
|
|
ushort[20] key = 23;
|
|
int[ushort[20]] aa;
|
|
aa[key] = 42;
|
|
auto x = aa[key];
|
|
assert(x == 42);
|
|
printf("foo\n");
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test22()
|
|
{
|
|
int[string] stopWords = [ "abc"[]:1 ];
|
|
assert("abc"[] in stopWords);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test23()
|
|
{
|
|
uint[char[]][] fractal;
|
|
fractal.length = 10;
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test24()
|
|
{
|
|
int[string] x;
|
|
char[] y;
|
|
if (y in x)
|
|
{
|
|
int z = x[y];
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test25()
|
|
{
|
|
string[string] aa;
|
|
foreach (k,v; aa)
|
|
{
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
class Tag
|
|
{
|
|
string[string] attr;
|
|
}
|
|
|
|
void foo26(const(Tag) tag_)
|
|
{
|
|
foreach(k,v;tag_.attr) { }
|
|
}
|
|
|
|
void test26()
|
|
{
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test27()
|
|
{
|
|
int[int] s;
|
|
s = s.init;
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test28()
|
|
{
|
|
auto a1 = [ 1:10.0, 2:20, 3:15 ];
|
|
auto a2 = [ 1:10.0, 2:20, 3:15 ];
|
|
assert(a1 !is a2);
|
|
assert(a1 == a2);
|
|
a2[7] = 23;
|
|
assert(a1 != a2);
|
|
a2.remove(7);
|
|
assert(a1 == a2);
|
|
a1.rehash;
|
|
assert(a1 == a2);
|
|
a2[2] = 18;
|
|
assert(a1 != a2);
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test29()
|
|
{
|
|
auto gammaFunc = [-1.5:2.363, -0.5:-3.545, 0.5:1.772];
|
|
|
|
// write all keys
|
|
foreach (k; gammaFunc.byKey()) {
|
|
printf("%f\n", k);
|
|
}
|
|
|
|
// write all values
|
|
foreach (v; gammaFunc.byValue()) {
|
|
printf("%f\n", v);
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
string toString(int value)
|
|
{
|
|
char[] result = new char[12];
|
|
|
|
uint ndigits = 0;
|
|
do
|
|
{
|
|
const c = cast(char) ((value % 10) + '0');
|
|
value /= 10;
|
|
ndigits++;
|
|
result[$ - ndigits] = c;
|
|
}
|
|
while (value);
|
|
return cast(string) result[$ - ndigits .. $];
|
|
}
|
|
|
|
void test30()
|
|
{
|
|
int[string] aa;
|
|
for(int i = 0; i < 100000; i++)
|
|
{
|
|
string s = toString(i);
|
|
aa[s] = i;
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test31()
|
|
{
|
|
int[int] test;
|
|
test[0] = 0;
|
|
test[1] = 1;
|
|
test[2] = 2;
|
|
|
|
bool flag = false;
|
|
foreach( k, v; test){
|
|
//printf("loop: %d %d\n", k, v);
|
|
assert(!flag);
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
void test32()
|
|
{
|
|
uint[ushort] aa;
|
|
aa[1] = 1;
|
|
aa[2] = 2;
|
|
aa[3] = 3;
|
|
aa[4] = 4;
|
|
aa[5] = 5;
|
|
foreach(v; aa)
|
|
{
|
|
printf("%x\n", v);
|
|
assert(v >= 1 && v <= 5);
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
template ICE3996(T : V[K], K, V) {}
|
|
|
|
struct Bug3996 {}
|
|
|
|
static assert(!is( ICE3996!(Bug3996) ));
|
|
|
|
/************************************************/
|
|
|
|
void bug4826c(T)(int[int] value, T x) {}
|
|
|
|
void test4826c()
|
|
{
|
|
AssociativeArray!(int, int) z;
|
|
bug4826c(z,1);
|
|
}
|
|
|
|
/************************************************/
|
|
// 5131
|
|
|
|
struct ICE5131
|
|
{
|
|
this(int n) {}
|
|
ICE5131 opAssign(int x) { return this; }
|
|
}
|
|
|
|
void test5131()
|
|
{
|
|
ICE5131[string] a;
|
|
a["ICE?"] = 1; // call ctor
|
|
a["ICE?"] = 1; // call opAssign
|
|
}
|
|
|
|
/************************************************/
|
|
// 6178
|
|
|
|
bool test6178a()
|
|
{
|
|
// AA value setting through identity opAssign
|
|
|
|
int assign = 0;
|
|
struct S
|
|
{
|
|
int value = 10;
|
|
|
|
void opAssign(S rhs)
|
|
{
|
|
++assign;
|
|
assert(value == 10);
|
|
}
|
|
}
|
|
|
|
int count = 0;
|
|
int makeKey() { return ++count; }
|
|
|
|
S[int] aa;
|
|
assert(aa.length == 0);
|
|
|
|
aa[makeKey()] = S();
|
|
assert(assign == 0);
|
|
assert(aa.length == 1 && 1 in aa);
|
|
|
|
aa[1] = S();
|
|
assert(assign == 1);
|
|
assert(aa.length == 1 && 1 in aa);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test6178b()
|
|
{
|
|
// AA value setting through implicit ctor call + non-identity opAssign
|
|
|
|
int ctor = 0;
|
|
int assign = 0;
|
|
struct S
|
|
{
|
|
int value = 10;
|
|
|
|
@disable this();
|
|
|
|
this(int n)
|
|
{
|
|
++ctor;
|
|
assert(value == 10);
|
|
value = 20;
|
|
}
|
|
void opAssign(int rhs)
|
|
{
|
|
++assign;
|
|
assert(value == 20);
|
|
assert(rhs == 30);
|
|
value = rhs;
|
|
}
|
|
}
|
|
|
|
int count = 0;
|
|
int makeKey() { return ++count; }
|
|
|
|
S[int] aa;
|
|
assert(aa.length == 0);
|
|
|
|
aa[makeKey()] = 20;
|
|
assert(assign == 0 && ctor == 1 && count == 1);
|
|
assert(aa.length == 1 && (1 in aa));
|
|
|
|
aa[1] = 30;
|
|
assert(assign == 1 && ctor == 1);
|
|
assert(aa.length == 1 && 1 in aa);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test6178c()
|
|
{
|
|
// AA value setting through non-identity opAssign
|
|
|
|
struct S
|
|
{
|
|
//this(int) {}
|
|
// not possible to perform implicit ctor call
|
|
void opAssign(int) {}
|
|
}
|
|
|
|
S[int] aa;
|
|
assert(aa.length == 0);
|
|
|
|
if (!__ctfe)
|
|
{
|
|
// currently CTFE does not support throwing RangeError
|
|
import core.exception : RangeError;
|
|
try { aa[1] = 1; assert(0); } catch (RangeError) {}
|
|
|
|
// The above line is exactly same as:
|
|
try { aa[1].opAssign(1); assert(0); } catch (RangeError) {}
|
|
}
|
|
assert(aa.length == 0);
|
|
|
|
aa[1] = S();
|
|
aa[1] = 1;
|
|
assert(aa.length == 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test6178d()
|
|
{
|
|
// AA value setting through implicit ctor call + alias this
|
|
|
|
int ctor;
|
|
struct S
|
|
{
|
|
this(int n) { ++ctor; value = n; }
|
|
|
|
int value;
|
|
alias value this;
|
|
}
|
|
|
|
S[int] aa;
|
|
assert(ctor == 0);
|
|
assert(aa.length == 0);
|
|
|
|
aa[1] = 0; // implicit ctor call + blit assign
|
|
assert(aa[1].value == 0 && ctor == 1);
|
|
assert(aa.length == 1);
|
|
|
|
aa[1] = 1; // set through alias this
|
|
assert(aa[1].value == 1 && ctor == 1);
|
|
assert(aa.length == 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test6178e()
|
|
{
|
|
// AA value setting through alias this
|
|
|
|
struct S
|
|
{
|
|
int value;
|
|
alias value this;
|
|
}
|
|
|
|
S[int] aa;
|
|
assert(aa.length == 0);
|
|
|
|
if (!__ctfe)
|
|
{
|
|
// currently CTFE does not support throwing RangeError
|
|
import core.exception : RangeError;
|
|
try { aa[1] = 1; assert(0); } catch (RangeError) {}
|
|
|
|
// The above line is exactly same as:
|
|
try { aa[1].value = 1; assert(0); } catch (RangeError) {}
|
|
}
|
|
assert(aa.length == 0);
|
|
|
|
aa[1] = S(0); // construct + blit assign
|
|
assert(aa[1].value == 0 && aa.length == 1);
|
|
|
|
aa[1] = 1; // set through alias this
|
|
assert(aa[1].value == 1 && aa.length == 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
void test6178()
|
|
{
|
|
static assert(test6178a()); // ctfe check
|
|
test6178a(); // runtime test
|
|
|
|
static assert(test6178b());
|
|
test6178b();
|
|
|
|
static assert(test6178c());
|
|
test6178c();
|
|
|
|
static assert(test6178d());
|
|
test6178d();
|
|
|
|
static assert(test6178e());
|
|
test6178e();
|
|
}
|
|
|
|
void test6178x()
|
|
{
|
|
return; // depends on AA implementation
|
|
static int ctor, cpctor, dtor;
|
|
|
|
static struct S
|
|
{
|
|
this(int) { ++ctor; printf("ctor\n"); }
|
|
this(this) { ++cpctor; printf("cpctor\n"); }
|
|
~this() { ++dtor; printf("dtor\n"); }
|
|
}
|
|
static struct X
|
|
{
|
|
this(int) {}
|
|
void opAssign(int) {}
|
|
}
|
|
|
|
X[S] aa1;
|
|
S[int] aa2;
|
|
|
|
{
|
|
auto value = S(1);
|
|
assert(ctor==1 && cpctor==0 && dtor==0);
|
|
|
|
ref getRef(ref S s = value) { return s; }
|
|
auto getVal() { return value; }
|
|
|
|
aa1[value] = 10;
|
|
assert(ctor==1 && cpctor==1 && dtor==0); //call copy ctor when we putting 'value' to aa1
|
|
|
|
aa1[getRef()] = 20;
|
|
assert(ctor==1 && cpctor==1 && dtor==0); //copy ctor wasn't called because we didn't create a new entry in aa, using an existing key
|
|
|
|
aa1[getVal()] = 20;
|
|
assert(ctor==1 && cpctor==2 && dtor==1); //call copy ctor and dtor, because we pass key by value
|
|
|
|
aa2[1] = value;
|
|
assert(ctor==1 && cpctor==3 && dtor==1); //call copy ctor when we putting `value` to aa2[1]
|
|
|
|
aa2[2] = getRef();
|
|
assert(ctor==1 && cpctor==4 && dtor==1); //call copy ctor when we putting `value` to aa2[2]
|
|
}
|
|
assert(ctor==1 && cpctor==4 && dtor==2); //We've got 3 "S" instances that aren't destroyed yet: the key in aa1, aa2[1], aa2[2].
|
|
assert(ctor + cpctor - aa2.length - aa1.length == dtor);
|
|
}
|
|
|
|
/************************************************/
|
|
// 10595
|
|
|
|
struct S10595
|
|
{
|
|
bool b = true;
|
|
|
|
bool test()
|
|
{
|
|
if (!b) // note: must be a check, not 'return b;'
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
struct Wrap10595
|
|
{
|
|
int i;
|
|
alias i this;
|
|
S10595 s;
|
|
}
|
|
|
|
void test10595()
|
|
{
|
|
{
|
|
Wrap10595[int] wrap;
|
|
|
|
wrap[0] = Wrap10595();
|
|
wrap[0].i = 0;
|
|
|
|
assert(wrap[0].s.test()); // ok
|
|
}
|
|
|
|
{
|
|
Wrap10595[int] wrap;
|
|
|
|
wrap[0] = Wrap10595();
|
|
wrap[0] = 0; // note: using 'alias this' to assign
|
|
|
|
assert(wrap[0].s.test()); // failure
|
|
}
|
|
}
|
|
|
|
/************************************************/
|
|
// 10970
|
|
|
|
struct RefCounted10970(T) //if (!is(T == class))
|
|
{
|
|
struct RefCountedStore
|
|
{
|
|
}
|
|
RefCountedStore _refCounted;
|
|
|
|
this(this) {}
|
|
|
|
~this() {}
|
|
}
|
|
|
|
struct Array10970(T) if (!is(T : const(bool)))
|
|
{
|
|
struct Payload
|
|
{
|
|
}
|
|
RefCounted10970!Payload _data;
|
|
}
|
|
|
|
class C10970
|
|
{
|
|
this(string name)
|
|
{
|
|
m[name] = Arr();
|
|
}
|
|
|
|
alias Array10970!C10970 Arr;
|
|
Arr[string] m;
|
|
}
|
|
|
|
void test10970()
|
|
{
|
|
C10970 c = new C10970("test");
|
|
}
|
|
|
|
/************************************************/
|
|
// 6433
|
|
|
|
void test6433()
|
|
{
|
|
int[int] aa;
|
|
static assert(aa.sizeof != 0);
|
|
static assert(aa.alignof != 0);
|
|
static assert(is(typeof(aa.init) == int[int]));
|
|
static assert(typeof(aa).mangleof == "Hii");
|
|
static assert(typeof(aa).stringof == "int[int]");
|
|
static struct AA { int[int] aa; }
|
|
static assert(AA.aa.offsetof == 0);
|
|
|
|
aa = aa.init;
|
|
aa[0] = 1;
|
|
assert(aa.length == 1 && aa[0] == 1);
|
|
}
|
|
|
|
/************************************************/
|
|
// 6612
|
|
|
|
void test6612()
|
|
{
|
|
auto aa1 = [1: 2]; // OK
|
|
auto aa2 = [4: 5]; // OK
|
|
int[int[int]] aa3 = [aa1:3, aa2:6]; // OK
|
|
int[int[int]] aa4 = [[1:2]:3, [4:5]:6]; // error
|
|
int[int[string]] aa5 = [["a":1]:2, ["b":3]:4];
|
|
}
|
|
|
|
/************************************************/
|
|
// 7365
|
|
|
|
struct TickDuration
|
|
{
|
|
bool opEquals(ref const TickDuration rhs) const
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void test7365()
|
|
{
|
|
TickDuration[Object] aa;
|
|
aa.keys;
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
enum aa5520 = [5 : "hello"];
|
|
|
|
void test5520()
|
|
{
|
|
auto a = aa5520.values;
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
enum size_t N6655 = 1;
|
|
int[bar6655.length] foo6655;
|
|
int[N6655] bar6655;
|
|
|
|
/************************************************/
|
|
|
|
struct ChunkLoc {}
|
|
|
|
ChunkLoc Get()
|
|
{
|
|
return ChunkLoc();
|
|
}
|
|
|
|
void test6799()
|
|
{
|
|
int[ChunkLoc] aa;
|
|
aa.remove(Get());
|
|
}
|
|
|
|
/************************************************/
|
|
// 11359
|
|
|
|
void test11359()
|
|
{
|
|
class Bar {}
|
|
static Bar[string] aa;
|
|
static ref fun() { return aa; }
|
|
|
|
string key = "test";
|
|
|
|
fun[key] = new Bar;
|
|
assert(aa.length == 1);
|
|
Bar bar = fun[key];
|
|
}
|
|
|
|
/************************************************/
|
|
// 11730
|
|
|
|
struct SysTime11730
|
|
{
|
|
ref SysTime11730 opAssign(SysTime11730 rhs)
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
struct Nullable11730(T)
|
|
{
|
|
T _value;
|
|
|
|
void opAssign()(T value)
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
@property ref inout(T) get() inout
|
|
{
|
|
assert(0);
|
|
}
|
|
alias get this;
|
|
}
|
|
|
|
void test11730()
|
|
{
|
|
Nullable11730!SysTime11730[string] map;
|
|
map["foo"] = Nullable11730!SysTime11730();
|
|
}
|
|
|
|
/************************************************/
|
|
// 14089
|
|
|
|
struct S14089
|
|
{
|
|
int num;
|
|
S14089 opAssign(S14089 val) { return this; }
|
|
}
|
|
|
|
void test14089()
|
|
{
|
|
S14089[int] aa;
|
|
S14089 b = aa[1] = S14089(0);
|
|
assert(aa[1].num == 0);
|
|
assert(b.num == 0);
|
|
}
|
|
|
|
/************************************************/
|
|
// 14144
|
|
|
|
struct JSON14144
|
|
{
|
|
union
|
|
{
|
|
double _floating;
|
|
}
|
|
|
|
this(typeof(null))
|
|
{
|
|
}
|
|
|
|
@trusted pure nothrow typeof(null) opAssign(typeof(null) nothing)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
void test14144()
|
|
{
|
|
JSON14144[string] x;
|
|
x["wat"] = null;
|
|
assert(x.length == 1);
|
|
assert("wat" in x);
|
|
}
|
|
|
|
/************************************************/
|
|
// 14321
|
|
|
|
void test14321()
|
|
{
|
|
struct Foo
|
|
{
|
|
static char[8] buf;
|
|
static char[] op;
|
|
|
|
this(int id) { buf[op.length] = 'c'; op = buf[0..op.length + 1]; }
|
|
this(this) { buf[op.length] = 'p'; op = buf[0..op.length + 1]; }
|
|
~this() { buf[op.length] = 'd'; op = buf[0..op.length + 1]; }
|
|
}
|
|
Foo[string] foos;
|
|
assert(Foo.op == "");
|
|
foos["test"] = Foo(42); // initialization
|
|
assert(Foo.op == "c");
|
|
foos["test"] = Foo(42); // assignment
|
|
assert(Foo.op == "ccd");
|
|
|
|
struct Bar
|
|
{
|
|
static char[8] buf;
|
|
static char[] op;
|
|
|
|
int id;
|
|
//this(int id) { op ~= "c"; }
|
|
this(this) { buf[op.length] = 'p'; op = buf[0..op.length + 1]; }
|
|
~this() { buf[op.length] = 'd'; op = buf[0..op.length + 1]; }
|
|
}
|
|
Bar[string] bars;
|
|
assert(Bar.op == "");
|
|
bars["test"] = Bar(42); // initialization
|
|
assert(Bar.op == "");
|
|
bars["test"] = Bar(42); // assignment
|
|
assert(Bar.op == "d");
|
|
}
|
|
|
|
/************************************************/
|
|
|
|
int main()
|
|
{
|
|
printf("before test 1\n"); test1();
|
|
printf("before test 2\n"); test2();
|
|
printf("before test 4\n"); test4();
|
|
printf("before test 5\n"); test5();
|
|
printf("before test 6\n"); test6();
|
|
printf("before test 7\n"); test7();
|
|
printf("before test 8\n"); test8();
|
|
printf("before test 9\n"); test9();
|
|
printf("before test 10\n"); test10();
|
|
printf("before test 11\n"); test11();
|
|
printf("before test 12\n"); test12();
|
|
printf("before test 13\n"); test13();
|
|
printf("before test 14\n"); test14();
|
|
printf("before test 15\n"); test15();
|
|
printf("before test 16\n"); test16();
|
|
printf("before test 17\n"); test17();
|
|
printf("before test 18\n"); test18();
|
|
printf("before test 19\n"); test19();
|
|
printf("before test 20\n"); test20();
|
|
printf("before test 21\n"); test21();
|
|
printf("before test 22\n"); test22();
|
|
printf("before test 23\n"); test23();
|
|
printf("before test 24\n"); test24();
|
|
printf("before test 25\n"); test25();
|
|
printf("before test 26\n"); test26();
|
|
printf("before test 27\n"); test27();
|
|
printf("before test 28\n"); test28();
|
|
printf("before test 29\n"); test29();
|
|
printf("before test 30\n"); test30();
|
|
printf("before test 31\n"); test31();
|
|
printf("before test 32\n"); test32();
|
|
|
|
test4826c();
|
|
test5131();
|
|
test6178();
|
|
test6178x();
|
|
test10595();
|
|
test10970();
|
|
test6433();
|
|
test6612();
|
|
test7365();
|
|
test5520();
|
|
test6799();
|
|
test11359();
|
|
test11730();
|
|
test14089();
|
|
test14321();
|
|
|
|
printf("Success\n");
|
|
return 0;
|
|
}
|