867 lines
13 KiB
D
867 lines
13 KiB
D
|
// PERMUTE_ARGS: -O -fPIC
|
||
|
|
||
|
extern(C) int printf(const char*, ...);
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
class Abc : Exception
|
||
|
{
|
||
|
this()
|
||
|
{
|
||
|
super("");
|
||
|
}
|
||
|
int i;
|
||
|
}
|
||
|
|
||
|
int y;
|
||
|
|
||
|
alias int boo;
|
||
|
|
||
|
void foo(int x)
|
||
|
{
|
||
|
y = cast(boo)1;
|
||
|
L6:
|
||
|
try
|
||
|
{
|
||
|
printf("try 1\n");
|
||
|
y += 4;
|
||
|
if (y == 5)
|
||
|
goto L6;
|
||
|
y += 3;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
y += 5;
|
||
|
printf("finally 1\n");
|
||
|
}
|
||
|
try
|
||
|
{
|
||
|
printf("try 2\n");
|
||
|
y = 1;
|
||
|
if (y == 4)
|
||
|
goto L6;
|
||
|
y++;
|
||
|
}
|
||
|
catch (Abc c)
|
||
|
{
|
||
|
printf("catch 2\n");
|
||
|
y = 2 + c.i;
|
||
|
}
|
||
|
y++;
|
||
|
printf("done\n");
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
|
||
|
class IntException : Exception
|
||
|
{
|
||
|
this(int i)
|
||
|
{
|
||
|
m_i = i;
|
||
|
super("");
|
||
|
}
|
||
|
|
||
|
int getValue()
|
||
|
{
|
||
|
return m_i;
|
||
|
}
|
||
|
|
||
|
int m_i;
|
||
|
}
|
||
|
|
||
|
|
||
|
void test2()
|
||
|
{
|
||
|
int cIterations = 10;
|
||
|
|
||
|
int i;
|
||
|
long total_x = 0;
|
||
|
long total_nox = 0;
|
||
|
|
||
|
for(int WARMUPS = 2; WARMUPS-- > 0; )
|
||
|
{
|
||
|
for(total_x = 0, i = 0; i < cIterations; ++i)
|
||
|
{
|
||
|
total_nox += fn2_nox();
|
||
|
}
|
||
|
printf("foo\n");
|
||
|
|
||
|
for(total_nox = 0, i = 0; i < cIterations; ++i)
|
||
|
{
|
||
|
printf("i = %d\n", i);
|
||
|
try
|
||
|
{
|
||
|
int z = 1;
|
||
|
|
||
|
throw new IntException(z);
|
||
|
}
|
||
|
catch(IntException x)
|
||
|
{
|
||
|
printf("catch, i = %d\n", i);
|
||
|
total_x += x.getValue();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf("iterations %d totals: %ld, %ld\n", cIterations, total_x, total_nox);
|
||
|
}
|
||
|
|
||
|
int fn2_nox()
|
||
|
{
|
||
|
return 47;
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
void test3()
|
||
|
{
|
||
|
static int x;
|
||
|
try
|
||
|
{
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
printf("a\n");
|
||
|
assert(x == 0);
|
||
|
x++;
|
||
|
}
|
||
|
printf("--\n");
|
||
|
assert(x == 1);
|
||
|
try
|
||
|
{
|
||
|
printf("tb\n");
|
||
|
assert(x == 1);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
printf("b\n");
|
||
|
assert(x == 1);
|
||
|
x++;
|
||
|
}
|
||
|
assert(x == 2);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
class Tester
|
||
|
{
|
||
|
this(void delegate() dg_) { dg = dg_; }
|
||
|
void delegate() dg;
|
||
|
void stuff() { dg(); }
|
||
|
}
|
||
|
|
||
|
void test4()
|
||
|
{
|
||
|
printf("Starting test\n");
|
||
|
|
||
|
int a = 0;
|
||
|
int b = 0;
|
||
|
int c = 0;
|
||
|
int d = 0;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
a++;
|
||
|
throw new Exception("test1");
|
||
|
a++;
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
auto es = e.toString();
|
||
|
printf("%.*s\n", es.length, es.ptr);
|
||
|
b++;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
c++;
|
||
|
}
|
||
|
|
||
|
printf("initial test.\n");
|
||
|
|
||
|
assert(a == 1);
|
||
|
assert(b == 1);
|
||
|
assert(c == 1);
|
||
|
|
||
|
printf("pass\n");
|
||
|
|
||
|
Tester t = new Tester(
|
||
|
delegate void()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
a++;
|
||
|
throw new Exception("test2");
|
||
|
a++;
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
b++;
|
||
|
throw e;
|
||
|
b++;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
try
|
||
|
{
|
||
|
c++;
|
||
|
t.stuff();
|
||
|
c++;
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
d++;
|
||
|
string es = e.toString;
|
||
|
printf("%.*s\n", es.length, es.ptr);
|
||
|
}
|
||
|
|
||
|
assert(a == 2);
|
||
|
assert(b == 2);
|
||
|
assert(c == 2);
|
||
|
assert(d == 1);
|
||
|
|
||
|
|
||
|
int q0 = 0;
|
||
|
int q1 = 0;
|
||
|
int q2 = 0;
|
||
|
int q3 = 0;
|
||
|
|
||
|
Tester t2 = new Tester(
|
||
|
delegate void()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
q0++;
|
||
|
throw new Exception("test3");
|
||
|
q0++;
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
printf("Never called.\n");
|
||
|
q1++;
|
||
|
throw e;
|
||
|
q1++;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
try
|
||
|
{
|
||
|
q2++;
|
||
|
t2.stuff();
|
||
|
q2++;
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
q3++;
|
||
|
string es = e.toString;
|
||
|
printf("%.*s\n", es.length, es.ptr);
|
||
|
}
|
||
|
|
||
|
assert(q0 == 1);
|
||
|
assert(q1 == 1);
|
||
|
assert(q2 == 1);
|
||
|
assert(q3 == 1);
|
||
|
|
||
|
printf("Passed!\n");
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
void test5()
|
||
|
{
|
||
|
char[] result;
|
||
|
int i = 3;
|
||
|
while(i--)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
printf("i: %d\n", i);
|
||
|
result ~= 't';
|
||
|
if (i == 1)
|
||
|
continue;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
printf("finally\n");
|
||
|
result ~= cast(char)('a' + i);
|
||
|
}
|
||
|
}
|
||
|
printf("--- %.*s", result.length, result.ptr);
|
||
|
if (result != "tctbta")
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
void test6()
|
||
|
{
|
||
|
char[] result;
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
printf("one\n");
|
||
|
result ~= 'a';
|
||
|
break;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
printf("two\n");
|
||
|
result ~= 'b';
|
||
|
}
|
||
|
}
|
||
|
printf("three\n");
|
||
|
result ~= 'c';
|
||
|
if (result != "abc")
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
string a7;
|
||
|
|
||
|
void doScan(int i)
|
||
|
{
|
||
|
a7 ~= "a";
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
a7 ~= "b";
|
||
|
return;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
a7 ~= "c";
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
a7 ~= "d";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void test7()
|
||
|
{
|
||
|
doScan(0);
|
||
|
assert(a7 == "abcd");
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************
|
||
|
* Exception chaining tests. See also test4.d
|
||
|
****************************************************/
|
||
|
int result1513;
|
||
|
|
||
|
void bug1513a()
|
||
|
{
|
||
|
throw new Exception("d");
|
||
|
}
|
||
|
|
||
|
void bug1513b()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
bug1513a();
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
result1513 |=4;
|
||
|
throw new Exception("f");
|
||
|
}
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
assert(e.msg == "d");
|
||
|
assert(e.next.msg == "f");
|
||
|
assert(!e.next.next);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void bug1513c()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
throw new Exception("a");
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
result1513 |= 1;
|
||
|
throw new Exception("b");
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
bug1513b();
|
||
|
result1513 |= 2;
|
||
|
throw new Exception("c");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void bug1513()
|
||
|
{
|
||
|
result1513 = 0;
|
||
|
try
|
||
|
{
|
||
|
bug1513c();
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
assert(result1513 == 7);
|
||
|
assert(e.msg == "a");
|
||
|
assert(e.next.msg == "b");
|
||
|
assert(e.next.next.msg == "c");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void collideone()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
throw new Exception("x");
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
throw new Exception("y");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void doublecollide()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
throw new Exception("p");
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
throw new Exception("q");
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
collideone();
|
||
|
}
|
||
|
}
|
||
|
catch(Exception e)
|
||
|
{
|
||
|
assert(e.msg == "p");
|
||
|
assert(e.next.msg == "q");
|
||
|
assert(e.next.next.msg == "x");
|
||
|
assert(e.next.next.next.msg == "y");
|
||
|
assert(!e.next.next.next.next);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void collidetwo()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
throw new Exception("p2");
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
throw new Exception("q2");
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
collideone();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void collideMixed()
|
||
|
{
|
||
|
int works = 6;
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
throw new Exception("e");
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
throw new Error("t");
|
||
|
}
|
||
|
}
|
||
|
catch(Exception f)
|
||
|
{ // Doesn't catch, because Error is chained to it.
|
||
|
works += 2;
|
||
|
}
|
||
|
}
|
||
|
catch(Error z)
|
||
|
{
|
||
|
works += 4;
|
||
|
assert(z.msg=="t"); // Error comes first
|
||
|
assert(z.next is null);
|
||
|
assert(z.bypassedException.msg == "e");
|
||
|
}
|
||
|
assert(works == 10);
|
||
|
}
|
||
|
|
||
|
class AnotherException : Exception
|
||
|
{
|
||
|
this(string s)
|
||
|
{
|
||
|
super(s);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void multicollide()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
throw new Exception("m2");
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
throw new AnotherException("n2");
|
||
|
}
|
||
|
}
|
||
|
catch(AnotherException s)
|
||
|
{ // Not caught -- we needed to catch the root cause "m2", not
|
||
|
// just the collateral "n2" (which would leave m2 uncaught).
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
collidetwo();
|
||
|
}
|
||
|
}
|
||
|
catch(Exception f)
|
||
|
{
|
||
|
assert(f.msg == "m2");
|
||
|
assert(f.next.msg == "n2");
|
||
|
Throwable e = f.next.next;
|
||
|
assert(e.msg == "p2");
|
||
|
assert(e.next.msg == "q2");
|
||
|
assert(e.next.next.msg == "x");
|
||
|
assert(e.next.next.next.msg == "y");
|
||
|
assert(!e.next.next.next.next);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
void use9568(char [] x, char [] y) {}
|
||
|
|
||
|
int bug9568()
|
||
|
{
|
||
|
try
|
||
|
return 7;
|
||
|
finally
|
||
|
use9568(null,null);
|
||
|
}
|
||
|
|
||
|
void test9568()
|
||
|
{
|
||
|
assert( bug9568() == 7 );
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
version (DigitalMars)
|
||
|
{
|
||
|
void test8a()
|
||
|
{
|
||
|
int a;
|
||
|
goto L2; // L2 is not addressable.
|
||
|
|
||
|
try {
|
||
|
a += 2;
|
||
|
}
|
||
|
catch (Exception) {
|
||
|
a += 3;
|
||
|
L2: ;
|
||
|
a += 100;
|
||
|
}
|
||
|
assert(a == 100);
|
||
|
}
|
||
|
|
||
|
void test8b()
|
||
|
{
|
||
|
int a;
|
||
|
goto L2; // L2 is not addressable.
|
||
|
|
||
|
try {
|
||
|
}
|
||
|
catch (Exception) {
|
||
|
a += 3;
|
||
|
L2: ;
|
||
|
a += 100;
|
||
|
}
|
||
|
assert(a == 100);
|
||
|
}
|
||
|
|
||
|
void test8c()
|
||
|
{
|
||
|
int a;
|
||
|
goto L2; // L2 is not addressable.
|
||
|
|
||
|
try
|
||
|
static assert(true);
|
||
|
catch (Exception) {
|
||
|
a += 3;
|
||
|
L2: ;
|
||
|
a += 100;
|
||
|
}
|
||
|
assert(a == 100);
|
||
|
}
|
||
|
|
||
|
void test8()
|
||
|
{
|
||
|
test8a();
|
||
|
test8b();
|
||
|
test8c();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
uint foo9(uint i)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
++i;
|
||
|
return 3;
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
debug printf("Exception happened\n");
|
||
|
}
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
void test9()
|
||
|
{
|
||
|
assert(foo9(7) == 3);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
// 10964
|
||
|
|
||
|
void test10964()
|
||
|
{
|
||
|
static struct S
|
||
|
{
|
||
|
this(this)
|
||
|
{
|
||
|
throw new Exception("BOOM!");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
S ss;
|
||
|
S[1] sa;
|
||
|
int result;
|
||
|
|
||
|
result = 0;
|
||
|
try
|
||
|
{
|
||
|
ss = ss;
|
||
|
}
|
||
|
catch (Exception e) result = 1;
|
||
|
catch (Error e) result = 2;
|
||
|
catch (Throwable e) result = 3;
|
||
|
assert(result == 1);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
sa = ss;
|
||
|
}
|
||
|
catch (Exception e) result = 1;
|
||
|
catch (Error e) result = 2;
|
||
|
catch (Throwable e) result = 3;
|
||
|
assert(result == 1);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
sa = sa;
|
||
|
}
|
||
|
catch (Exception e) result = 1;
|
||
|
catch (Error e) result = 2;
|
||
|
catch (Throwable e) result = 3;
|
||
|
assert(result == 1);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
alias Action = void delegate();
|
||
|
|
||
|
class A10
|
||
|
{
|
||
|
invariant()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public Action foo(Action a)
|
||
|
{
|
||
|
synchronized
|
||
|
{
|
||
|
B10 elements = new B10;
|
||
|
Action[] actions = [a];
|
||
|
|
||
|
elements.bar(actions);
|
||
|
|
||
|
if (actions.length > 1)
|
||
|
elements.bar(actions);
|
||
|
return actions[0];
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class B10
|
||
|
{
|
||
|
public bool bar(ref Action[])
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class D10
|
||
|
{
|
||
|
void baz()
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void test12989()
|
||
|
{
|
||
|
auto a = new A10;
|
||
|
auto d = new D10;
|
||
|
|
||
|
assert(a.foo(&d.baz) == &d.baz);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
int bar10(int c)
|
||
|
{
|
||
|
if (c <= 0xFFFF)
|
||
|
{
|
||
|
L3:
|
||
|
return 3;
|
||
|
}
|
||
|
throw new Exception("msg");
|
||
|
goto L3;
|
||
|
}
|
||
|
|
||
|
void test10()
|
||
|
{
|
||
|
int x;
|
||
|
try
|
||
|
{
|
||
|
bar10(0x110000);
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
printf("caught\n");
|
||
|
x = 1;
|
||
|
}
|
||
|
assert(x == 1);
|
||
|
printf("test10 success\n");
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
class ParseException : Exception
|
||
|
{
|
||
|
@safe pure nothrow this( string msg )
|
||
|
{
|
||
|
super( msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class OverflowException : Exception
|
||
|
{
|
||
|
@safe pure nothrow this( string msg )
|
||
|
{
|
||
|
super( msg );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void test11()
|
||
|
{
|
||
|
int x;
|
||
|
try
|
||
|
{
|
||
|
printf("test11()\n");
|
||
|
throw new ParseException("msg");
|
||
|
}
|
||
|
catch( OverflowException e )
|
||
|
{
|
||
|
printf( "catch OverflowException\n" );
|
||
|
}
|
||
|
catch( ParseException e )
|
||
|
{
|
||
|
printf( "catch ParseException: %.*s\n", cast(int) e.msg.length, e.msg.ptr );
|
||
|
x = 1;
|
||
|
}
|
||
|
assert(x == 1);
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
// https://issues.dlang.org/show_bug.cgi?id=17481
|
||
|
|
||
|
class C17481
|
||
|
{
|
||
|
synchronized void trigger(){ new ubyte[1]; }
|
||
|
}
|
||
|
|
||
|
void test17481()
|
||
|
{
|
||
|
auto k = new shared C17481;
|
||
|
k.trigger;
|
||
|
}
|
||
|
|
||
|
/****************************************************/
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
printf("start\n");
|
||
|
foo(3);
|
||
|
test2();
|
||
|
test3();
|
||
|
test4();
|
||
|
test5();
|
||
|
test6();
|
||
|
test7();
|
||
|
|
||
|
bug1513();
|
||
|
doublecollide();
|
||
|
collideMixed();
|
||
|
multicollide();
|
||
|
test9568();
|
||
|
|
||
|
version(DigitalMars) test8();
|
||
|
test9();
|
||
|
test10964();
|
||
|
test12989();
|
||
|
test10();
|
||
|
test11();
|
||
|
test17481();
|
||
|
|
||
|
printf("finish\n");
|
||
|
return 0;
|
||
|
}
|