blob: 7d15b54a213de0ad5abfee4bfcb7e7cd279b83e5 [file] [log] [blame]
alias noreturn = typeof(*null);
extern (C) noreturn exit();
/*****************************************/
bool testf(int i)
{
return i && assert(0);
}
bool testt(int i)
{
return i || assert(0);
}
int testa(int i)
{
if (i && exit())
return i + 1;
return i - 1;
}
int testb(int i)
{
if (i || exit())
return i + 1;
return i - 1;
}
void test1()
{
assert(testf(0) == false);
assert(testt(1) == true);
assert(testa(0) == -1);
assert(testb(3) == 4);
}
/*****************************************/
noreturn exit1() { assert(0); }
noreturn exit2() { assert(0); }
int heli1(int i)
{
return i ? exit1() : i - 1;
}
int heli2(int i)
{
return i ? i - 1 : exit1();
}
noreturn heli3(int i)
{
return i ? exit1() : exit2();
}
void test2()
{
assert(heli1(0) == -1);
assert(heli2(1) == 0);
}
/*****************************************/
struct BasicStruct
{
int firstInt;
noreturn noRet;
long lastLong;
}
struct AlignedStruct
{
int firstInt;
align(16) noreturn noRet;
long lastLong;
}
void takeBasic(BasicStruct bs)
{
assert(bs.firstInt == 13);
assert(bs.lastLong == 42);
assert(&bs.noRet == (&bs.firstInt + 1));
}
void takeAligned(AlignedStruct as)
{
assert(as.firstInt == 99);
assert(as.lastLong == 0xDEADBEEF);
assert(&as.noRet == &as.lastLong);
}
void test3()
{
{
BasicStruct bs;
bs.firstInt = 13;
bs.lastLong = 42;
takeBasic(bs);
}
{
AlignedStruct as;
as.firstInt = 99;
as.lastLong = 0xDEADBEEF;
takeAligned(as);
}
}
/*****************************************/
Exception collectException(void function() f)
{
try
{
f();
return null;
}
catch (Exception e)
return e;
}
int return_()
{
return throw new Exception("Return");
}
void ternary(int i)
{
i > 0 ? i++ : throw new Exception("Ternary");
}
void call()
{
ternary(throw new Exception("Call"));
}
void arrayLiteral()
{
int[] arr = [
1,
throw new Exception("ArrayLiteral"),
2
];
}
void assocArrayLiteral()
{
int[string] arr = [
"A": 1,
"B": throw new Exception("AssocArrayLiteral"),
"C": 2
];
}
void testThrowExpression()
{
Exception ae = collectException({ return_(); });
assert(ae);
ae = collectException({ ternary(1); });
assert(!ae);
ae = collectException({ ternary(-1); });
assert(ae);
ae = collectException(&call);
assert(ae);
assert(ae.msg == "Call");
ae = collectException(&arrayLiteral);
assert(ae);
ae = collectException(&assocArrayLiteral);
assert(ae);
}
/*****************************************/
/// Verify that throws does not screw with side effects
void testThrowSideEffect()
{
static void foo(bool, void*, int) {}
bool b;
int i;
try
{
foo(b = true, throw new Exception(""), i++);
assert(false);
}
catch (Exception) {}
assert(b == true);
assert(i == 0);
}
/// Verify that throws does not screw with dtors
void testThrowDtor()
{
static struct S
{
__gshared int destructed;
int id;
~this()
{
assert(!(destructed & id));
destructed |= id;
}
string getMessage()
{
// Force runtime dependency
return destructed ? "Already destructed" : "Valid";
}
}
static void fooD(S, int, S) {}
bool caught;
try
{
fooD(S(1), throw new Exception(S(2).getMessage()), S(4));
assert(false);
}
catch (Exception e)
{
caught = true;
assert(e.msg == "Valid");
}
assert(caught);
assert(S.destructed == (1 | 2));
static void fooC(S, int, S) {}
caught = false;
S.destructed = 0;
try
{
fooC(S(1), throw new Exception(S(2).getMessage()), S(4));
assert(false);
}
catch (Exception e)
{
caught = true;
assert(e.msg == "Valid");
}
assert(caught);
assert(S.destructed == (1 | 2));
}
/*****************************************/
int main()
{
test1();
test2();
test3();
testThrowExpression();
testThrowSideEffect();
testThrowDtor();
return 0;
}