46 changes: 38 additions & 8 deletions src/nogc.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

module ddmd.nogc;

import ddmd.aggregate;
import ddmd.apply;
import ddmd.declaration;
import ddmd.dscope;
Expand Down Expand Up @@ -71,7 +72,8 @@ public:
return;
if (f.setGC())
{
e.error("array literal in @nogc function %s may cause GC allocation", f.toChars());
e.error("array literal in @nogc %s '%s' may cause GC allocation",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -84,7 +86,8 @@ public:
return;
if (f.setGC())
{
e.error("associative array literal in @nogc function %s may cause GC allocation", f.toChars());
e.error("associative array literal in @nogc %s '%s' may cause GC allocation",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -104,7 +107,8 @@ public:
return;
if (f.setGC())
{
e.error("cannot use 'new' in @nogc function %s", f.toChars());
e.error("cannot use 'new' in @nogc %s '%s'",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -119,9 +123,31 @@ public:
if (v && v.onstack)
return; // delete for scope allocated class object
}

Type tb = e.e1.type.toBasetype();
AggregateDeclaration ad = null;
switch (tb.ty)
{
case Tclass:
ad = (cast(TypeClass)tb).sym;
break;

case Tpointer:
tb = (cast(TypePointer)tb).next.toBasetype();
if (tb.ty == Tstruct)
ad = (cast(TypeStruct)tb).sym;
break;

default:
break;
}
if (ad && ad.aggDelete)
return;

if (f.setGC())
{
e.error("cannot use 'delete' in @nogc function %s", f.toChars());
e.error("cannot use 'delete' in @nogc %s '%s'",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -135,7 +161,8 @@ public:
{
if (f.setGC())
{
e.error("indexing an associative array in @nogc function %s may cause GC allocation", f.toChars());
e.error("indexing an associative array in @nogc %s '%s' may cause GC allocation",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -149,7 +176,8 @@ public:
{
if (f.setGC())
{
e.error("setting 'length' in @nogc function %s may cause GC allocation", f.toChars());
e.error("setting 'length' in @nogc %s '%s' may cause GC allocation",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -161,7 +189,8 @@ public:
{
if (f.setGC())
{
e.error("cannot use operator ~= in @nogc function %s", f.toChars());
e.error("cannot use operator ~= in @nogc %s '%s'",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand All @@ -172,7 +201,8 @@ public:
{
if (f.setGC())
{
e.error("cannot use operator ~ in @nogc function %s", f.toChars());
e.error("cannot use operator ~ in @nogc %s '%s'",
f.kind(), f.toPrettyChars());
err = true;
return;
}
Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/diag10319.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ fail_compilation/diag10319.d(25): Error: pure function 'D main' cannot call impu
fail_compilation/diag10319.d(25): Error: safe function 'D main' cannot call system function 'diag10319.foo'
fail_compilation/diag10319.d(26): Error: pure function 'D main' cannot call impure function 'diag10319.bar!int.bar'
fail_compilation/diag10319.d(26): Error: safe function 'D main' cannot call system function 'diag10319.bar!int.bar'
fail_compilation/diag10319.d(25): Error: 'diag10319.foo' is not nothrow
fail_compilation/diag10319.d(26): Error: 'diag10319.bar!int.bar' is not nothrow
fail_compilation/diag10319.d(25): Error: function 'diag10319.foo' is not nothrow
fail_compilation/diag10319.d(26): Error: function 'diag10319.bar!int.bar' is not nothrow
fail_compilation/diag10319.d(23): Error: function 'D main' is nothrow yet may throw
---
*/
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/diag7050a.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag7050a.d(5): Error: safe function 'diag7050a.foo' cannot call system function 'diag7050a.Foo.this'
fail_compilation/diag7050a.d(5): Error: safe function 'diag7050a.foo' cannot call system constructor 'diag7050a.Foo.this'
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/diag7050c.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag7050c.d(6): Error: safe function 'diag7050c.B.~this' cannot call system function 'diag7050c.A.~this'
fail_compilation/diag7050c.d(6): Error: safe destructor 'diag7050c.B.~this' cannot call system destructor 'diag7050c.A.~this'
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/diag9148.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ TEST_OUTPUT:
---
fail_compilation/diag9148.d(19): Error: pure function 'diag9148.test9148a.foo' cannot access mutable static data 'g'
fail_compilation/diag9148.d(23): Error: pure function 'diag9148.test9148a.bar' cannot access mutable static data 'g'
fail_compilation/diag9148.d(24): Error: pure immutable nested function 'diag9148.test9148a.bar' cannot access mutable data 'x'
fail_compilation/diag9148.d(24): Error: pure immutable function 'diag9148.test9148a.bar' cannot access mutable data 'x'
fail_compilation/diag9148.d(31): Error: pure function 'diag9148.test9148a.S.foo' cannot access mutable static data 'g'
fail_compilation/diag9148.d(35): Error: pure function 'diag9148.test9148a.S.bar' cannot access mutable static data 'g'
fail_compilation/diag9148.d(36): Error: pure immutable member function 'diag9148.test9148a.S.bar' cannot access mutable data 'x'
fail_compilation/diag9148.d(36): Error: pure immutable function 'diag9148.test9148a.S.bar' cannot access mutable data 'x'
---
*/
void test9148a() pure
Expand Down
8 changes: 4 additions & 4 deletions test/fail_compilation/fail10254.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail10254.d(18): Error: pure function 'fail10254.foo' cannot call impure function 'fail10254.C.this'
fail_compilation/fail10254.d(18): Error: safe function 'fail10254.foo' cannot call system function 'fail10254.C.this'
fail_compilation/fail10254.d(19): Error: pure function 'fail10254.foo' cannot call impure function 'fail10254.S.this'
fail_compilation/fail10254.d(19): Error: safe function 'fail10254.foo' cannot call system function 'fail10254.S.this'
fail_compilation/fail10254.d(18): Error: pure function 'fail10254.foo' cannot call impure constructor 'fail10254.C.this'
fail_compilation/fail10254.d(18): Error: safe function 'fail10254.foo' cannot call system constructor 'fail10254.C.this'
fail_compilation/fail10254.d(19): Error: pure function 'fail10254.foo' cannot call impure constructor 'fail10254.S.this'
fail_compilation/fail10254.d(19): Error: safe function 'fail10254.foo' cannot call system constructor 'fail10254.S.this'
---
*/

Expand Down
12 changes: 6 additions & 6 deletions test/fail_compilation/fail10964.d
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail10964.d(28): Error: 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(29): Error: 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(30): Error: 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(33): Error: 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(34): Error: 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(35): Error: 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(28): Error: function 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(29): Error: function 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(30): Error: function 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(33): Error: function 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(34): Error: function 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(35): Error: function 'fail10964.S.__postblit' is not nothrow
fail_compilation/fail10964.d(22): Error: function 'fail10964.foo' is nothrow yet may throw
---
*/
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail11375.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail11375.d(17): Error: constructor this is not nothrow
fail_compilation/fail11375.d(17): Error: constructor 'fail11375.D!().D.this' is not nothrow
fail_compilation/fail11375.d(15): Error: function 'D main' is nothrow yet may throw
---
*/
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail12908.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail12908.d(14): Error: pure function 'fail12908.main.__foreachbody1' cannot call impure function 'fail12908.g'
fail_compilation/fail12908.d(14): Error: pure delegate 'fail12908.main.__foreachbody1' cannot call impure function 'fail12908.g'
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail12932.d
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail12932.d(11): Error: array literal in @nogc function foo may cause GC allocation
fail_compilation/fail12932.d(15): Error: array literal in @nogc function foo may cause GC allocation
fail_compilation/fail12932.d(11): Error: array literal in @nogc function 'fail12932.foo' may cause GC allocation
fail_compilation/fail12932.d(15): Error: array literal in @nogc function 'fail12932.foo' may cause GC allocation
---
*/

Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail13120.d
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail13120.d(13): Error: pure function 'fail13120.g1.__foreachbody2' cannot call impure function 'fail13120.f1'
fail_compilation/fail13120.d(13): Error: @nogc function 'fail13120.g1.__foreachbody2' cannot call non-@nogc function 'fail13120.f1'
fail_compilation/fail13120.d(13): Error: pure delegate 'fail13120.g1.__foreachbody2' cannot call impure function 'fail13120.f1'
fail_compilation/fail13120.d(13): Error: @nogc delegate 'fail13120.g1.__foreachbody2' cannot call non-@nogc function 'fail13120.f1'
---
*/
void f1() {}
Expand Down
50 changes: 26 additions & 24 deletions test/fail_compilation/fail14407.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import imports.a14407;
/*
TEST_OUTPUT:
---
fail_compilation/fail14407.d(22): Deprecation: class imports.a14407.C is deprecated
fail_compilation/fail14407.d(22): Deprecation: allocator imports.a14407.C.new is deprecated
fail_compilation/fail14407.d(22): Error: pure function 'fail14407.testC' cannot call impure function 'imports.a14407.C.new'
fail_compilation/fail14407.d(22): Error: safe function 'fail14407.testC' cannot call system function 'imports.a14407.C.new'
fail_compilation/fail14407.d(22): Error: @nogc function 'fail14407.testC' cannot call non-@nogc function 'imports.a14407.C.new'
fail_compilation/fail14407.d(22): Error: class imports.a14407.C member new is not accessible
fail_compilation/fail14407.d(22): Error: pure function 'fail14407.testC' cannot call impure function 'imports.a14407.C.this'
fail_compilation/fail14407.d(22): Error: safe function 'fail14407.testC' cannot call system function 'imports.a14407.C.this'
fail_compilation/fail14407.d(22): Error: @nogc function 'fail14407.testC' cannot call non-@nogc function 'imports.a14407.C.this'
fail_compilation/fail14407.d(22): Error: class imports.a14407.C member this is not accessible
fail_compilation/fail14407.d(22): Error: constructor this is not nothrow
fail_compilation/fail14407.d(20): Error: function 'fail14407.testC' is nothrow yet may throw
fail_compilation/fail14407.d(23): Deprecation: class imports.a14407.C is deprecated
fail_compilation/fail14407.d(23): Deprecation: allocator imports.a14407.C.new is deprecated
fail_compilation/fail14407.d(23): Error: pure function 'fail14407.testC' cannot call impure allocator 'imports.a14407.C.new'
fail_compilation/fail14407.d(23): Error: safe function 'fail14407.testC' cannot call system allocator 'imports.a14407.C.new'
fail_compilation/fail14407.d(23): Error: @nogc function 'fail14407.testC' cannot call non-@nogc allocator 'imports.a14407.C.new'
fail_compilation/fail14407.d(23): Error: class imports.a14407.C member new is not accessible
fail_compilation/fail14407.d(23): Error: pure function 'fail14407.testC' cannot call impure constructor 'imports.a14407.C.this'
fail_compilation/fail14407.d(23): Error: safe function 'fail14407.testC' cannot call system constructor 'imports.a14407.C.this'
fail_compilation/fail14407.d(23): Error: @nogc function 'fail14407.testC' cannot call non-@nogc constructor 'imports.a14407.C.this'
fail_compilation/fail14407.d(23): Error: class imports.a14407.C member this is not accessible
fail_compilation/fail14407.d(23): Error: allocator 'imports.a14407.C.new' is not nothrow
fail_compilation/fail14407.d(23): Error: constructor 'imports.a14407.C.this' is not nothrow
fail_compilation/fail14407.d(21): Error: function 'fail14407.testC' is nothrow yet may throw
---
*/
void testC() pure nothrow @safe @nogc
Expand All @@ -25,18 +26,19 @@ void testC() pure nothrow @safe @nogc
/*
TEST_OUTPUT:
---
fail_compilation/fail14407.d(44): Deprecation: struct imports.a14407.S is deprecated
fail_compilation/fail14407.d(44): Deprecation: allocator imports.a14407.S.new is deprecated
fail_compilation/fail14407.d(44): Error: pure function 'fail14407.testS' cannot call impure function 'imports.a14407.S.new'
fail_compilation/fail14407.d(44): Error: safe function 'fail14407.testS' cannot call system function 'imports.a14407.S.new'
fail_compilation/fail14407.d(44): Error: @nogc function 'fail14407.testS' cannot call non-@nogc function 'imports.a14407.S.new'
fail_compilation/fail14407.d(44): Error: struct imports.a14407.S member new is not accessible
fail_compilation/fail14407.d(44): Error: pure function 'fail14407.testS' cannot call impure function 'imports.a14407.S.this'
fail_compilation/fail14407.d(44): Error: safe function 'fail14407.testS' cannot call system function 'imports.a14407.S.this'
fail_compilation/fail14407.d(44): Error: @nogc function 'fail14407.testS' cannot call non-@nogc function 'imports.a14407.S.this'
fail_compilation/fail14407.d(44): Error: struct imports.a14407.S member this is not accessible
fail_compilation/fail14407.d(44): Error: constructor this is not nothrow
fail_compilation/fail14407.d(42): Error: function 'fail14407.testS' is nothrow yet may throw
fail_compilation/fail14407.d(46): Deprecation: struct imports.a14407.S is deprecated
fail_compilation/fail14407.d(46): Deprecation: allocator imports.a14407.S.new is deprecated
fail_compilation/fail14407.d(46): Error: pure function 'fail14407.testS' cannot call impure allocator 'imports.a14407.S.new'
fail_compilation/fail14407.d(46): Error: safe function 'fail14407.testS' cannot call system allocator 'imports.a14407.S.new'
fail_compilation/fail14407.d(46): Error: @nogc function 'fail14407.testS' cannot call non-@nogc allocator 'imports.a14407.S.new'
fail_compilation/fail14407.d(46): Error: struct imports.a14407.S member new is not accessible
fail_compilation/fail14407.d(46): Error: pure function 'fail14407.testS' cannot call impure constructor 'imports.a14407.S.this'
fail_compilation/fail14407.d(46): Error: safe function 'fail14407.testS' cannot call system constructor 'imports.a14407.S.this'
fail_compilation/fail14407.d(46): Error: @nogc function 'fail14407.testS' cannot call non-@nogc constructor 'imports.a14407.S.this'
fail_compilation/fail14407.d(46): Error: struct imports.a14407.S member this is not accessible
fail_compilation/fail14407.d(46): Error: allocator 'imports.a14407.S.new' is not nothrow
fail_compilation/fail14407.d(46): Error: constructor 'imports.a14407.S.this' is not nothrow
fail_compilation/fail14407.d(44): Error: function 'fail14407.testS' is nothrow yet may throw
---
*/
void testS() pure nothrow @safe @nogc
Expand Down
149 changes: 149 additions & 0 deletions test/fail_compilation/fail14486.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// REQUIRED_ARGS: -o-

class C0a { }
class C1a { ~this() {} }
class C2a { ~this() {} @nogc pure @safe delete(void* p) {} }
class C3a { @nogc pure @safe ~this() {} delete(void* p) {} }
class C4a { @nogc pure @safe ~this() {} @nogc pure @safe delete(void* p) {} }

class C0b { }
class C1b { ~this() {} }
class C2b { ~this() {} nothrow delete(void* p) {} }
class C3b { nothrow ~this() {} delete(void* p) {} }
class C4b { nothrow ~this() {} nothrow delete(void* p) {} }

struct S0a { }
struct S1a { ~this() {} }
struct S2a { ~this() {} @nogc pure @safe delete(void* p) {} }
struct S3a { @nogc pure @safe ~this() {} delete(void* p) {} }
struct S4a { @nogc pure @safe ~this() {} @nogc pure @safe delete(void* p) {} }

struct S0b { }
struct S1b { ~this() {} }
struct S2b { ~this() {} nothrow delete(void* p) {} }
struct S3b { nothrow ~this() {} delete(void* p) {} }
struct S4b { nothrow ~this() {} nothrow delete(void* p) {} }

/*
TEST_OUTPUT:
---
fail_compilation/fail14486.d(44): Error: cannot use 'delete' in @nogc function 'fail14486.test1a'
fail_compilation/fail14486.d(45): Error: pure function 'fail14486.test1a' cannot call impure destructor 'fail14486.C1a.~this'
fail_compilation/fail14486.d(45): Error: safe function 'fail14486.test1a' cannot call system destructor 'fail14486.C1a.~this'
fail_compilation/fail14486.d(45): Error: @nogc function 'fail14486.test1a' cannot call non-@nogc destructor 'fail14486.C1a.~this'
fail_compilation/fail14486.d(46): Error: pure function 'fail14486.test1a' cannot call impure destructor 'fail14486.C2a.~this'
fail_compilation/fail14486.d(46): Error: safe function 'fail14486.test1a' cannot call system destructor 'fail14486.C2a.~this'
fail_compilation/fail14486.d(46): Error: @nogc function 'fail14486.test1a' cannot call non-@nogc destructor 'fail14486.C2a.~this'
fail_compilation/fail14486.d(47): Error: pure function 'fail14486.test1a' cannot call impure deallocator 'fail14486.C3a.delete'
fail_compilation/fail14486.d(47): Error: safe function 'fail14486.test1a' cannot call system deallocator 'fail14486.C3a.delete'
fail_compilation/fail14486.d(47): Error: @nogc function 'fail14486.test1a' cannot call non-@nogc deallocator 'fail14486.C3a.delete'
---
*/
void test1a() @nogc pure @safe
{
C0a c0; delete c0; // error
C1a c1; delete c1; // error
C2a c2; delete c2; // error
C3a c3; delete c3; // error
C4a c4; delete c4; // no error
}

/*
TEST_OUTPUT:
---
fail_compilation/fail14486.d(63): Error: destructor 'fail14486.C1b.~this' is not nothrow
fail_compilation/fail14486.d(64): Error: destructor 'fail14486.C2b.~this' is not nothrow
fail_compilation/fail14486.d(65): Error: deallocator 'fail14486.C3b.delete' is not nothrow
fail_compilation/fail14486.d(60): Error: function 'fail14486.test1b' is nothrow yet may throw
---
*/
void test1b() nothrow
{
C0b c0; delete c0; // no error
C1b c1; delete c1; // error
C2b c2; delete c2; // error
C3b c3; delete c3; // error
C4b c4; delete c4; // no error
}

/*
TEST_OUTPUT:
---
fail_compilation/fail14486.d(86): Error: cannot use 'delete' in @nogc function 'fail14486.test2a'
fail_compilation/fail14486.d(87): Error: pure function 'fail14486.test2a' cannot call impure destructor 'fail14486.S1a.~this'
fail_compilation/fail14486.d(87): Error: safe function 'fail14486.test2a' cannot call system destructor 'fail14486.S1a.~this'
fail_compilation/fail14486.d(87): Error: @nogc function 'fail14486.test2a' cannot call non-@nogc destructor 'fail14486.S1a.~this'
fail_compilation/fail14486.d(88): Error: pure function 'fail14486.test2a' cannot call impure destructor 'fail14486.S2a.~this'
fail_compilation/fail14486.d(88): Error: safe function 'fail14486.test2a' cannot call system destructor 'fail14486.S2a.~this'
fail_compilation/fail14486.d(88): Error: @nogc function 'fail14486.test2a' cannot call non-@nogc destructor 'fail14486.S2a.~this'
fail_compilation/fail14486.d(89): Error: pure function 'fail14486.test2a' cannot call impure deallocator 'fail14486.S3a.delete'
fail_compilation/fail14486.d(89): Error: safe function 'fail14486.test2a' cannot call system deallocator 'fail14486.S3a.delete'
fail_compilation/fail14486.d(89): Error: @nogc function 'fail14486.test2a' cannot call non-@nogc deallocator 'fail14486.S3a.delete'
---
*/
void test2a() @nogc pure @safe
{
S0a* s0; delete s0; // error
S1a* s1; delete s1; // error
S2a* s2; delete s2; // error
S3a* s3; delete s3; // error
S4a* s4; delete s4; // no error
}

/*
TEST_OUTPUT:
---
fail_compilation/fail14486.d(105): Error: destructor 'fail14486.S1b.~this' is not nothrow
fail_compilation/fail14486.d(106): Error: destructor 'fail14486.S2b.~this' is not nothrow
fail_compilation/fail14486.d(107): Error: deallocator 'fail14486.S3b.delete' is not nothrow
fail_compilation/fail14486.d(102): Error: function 'fail14486.test2b' is nothrow yet may throw
---
*/
void test2b() nothrow
{
S0b* s0; delete s0; // no error
S1b* s1; delete s1; // error
S2b* s2; delete s2; // error
S3b* s3; delete s3; // error
S4b* s4; delete s4; // no error
}

/*
TEST_OUTPUT:
---
fail_compilation/fail14486.d(127): Error: cannot use 'delete' in @nogc function 'fail14486.test3a'
fail_compilation/fail14486.d(128): Error: pure function 'fail14486.test3a' cannot call impure destructor 'fail14486.S1a.~this'
fail_compilation/fail14486.d(128): Error: safe function 'fail14486.test3a' cannot call system destructor 'fail14486.S1a.~this'
fail_compilation/fail14486.d(128): Error: @nogc function 'fail14486.test3a' cannot call non-@nogc destructor 'fail14486.S1a.~this'
fail_compilation/fail14486.d(129): Error: pure function 'fail14486.test3a' cannot call impure destructor 'fail14486.S2a.~this'
fail_compilation/fail14486.d(129): Error: safe function 'fail14486.test3a' cannot call system destructor 'fail14486.S2a.~this'
fail_compilation/fail14486.d(129): Error: @nogc function 'fail14486.test3a' cannot call non-@nogc destructor 'fail14486.S2a.~this'
fail_compilation/fail14486.d(130): Error: cannot use 'delete' in @nogc function 'fail14486.test3a'
fail_compilation/fail14486.d(131): Error: cannot use 'delete' in @nogc function 'fail14486.test3a'
---
*/
void test3a() @nogc pure @safe
{
S0a[] a0; delete a0; // error
S1a[] a1; delete a1; // error
S2a[] a2; delete a2; // error
S3a[] a3; delete a3; // error
S4a[] a4; delete a4; // error
}

/*
TEST_OUTPUT:
---
fail_compilation/fail14486.d(145): Error: destructor 'fail14486.S1b.~this' is not nothrow
fail_compilation/fail14486.d(146): Error: destructor 'fail14486.S2b.~this' is not nothrow
fail_compilation/fail14486.d(142): Error: function 'fail14486.test3b' is nothrow yet may throw
---
*/
void test3b() nothrow
{
S0b[] a0; delete a0; // no error
S1b[] a1; delete a1; // error
S2b[] a2; delete a2; // error
S3b[] a3; delete a3; // no error
S4b[] a4; delete a4; // no error
}
2 changes: 1 addition & 1 deletion test/fail_compilation/fail349.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail349.d(15): Error: 'fail349.bug6109throwing' is not nothrow
fail_compilation/fail349.d(15): Error: function 'fail349.bug6109throwing' is not nothrow
fail_compilation/fail349.d(13): Error: function 'fail349.bug6109noThrow' is nothrow yet may throw
---
*/
Expand Down
4 changes: 2 additions & 2 deletions test/fail_compilation/fail4082.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail4082.d(14): Error: 'fail4082.Foo.~this' is not nothrow
fail_compilation/fail4082.d(14): Error: destructor 'fail4082.Foo.~this' is not nothrow
fail_compilation/fail4082.d(12): Error: function 'fail4082.test1' is nothrow yet may throw
---
*/
Expand All @@ -21,7 +21,7 @@ NEXT:
/*
TEST_OUTPUT:
---
fail_compilation/fail4082.d(32): Error: 'fail4082.Bar.~this' is not nothrow
fail_compilation/fail4082.d(32): Error: destructor 'fail4082.Bar.~this' is not nothrow
fail_compilation/fail4082.d(32): Error: function 'fail4082.test2' is nothrow yet may throw
---
*/
Expand Down
20 changes: 10 additions & 10 deletions test/fail_compilation/fail7848.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ TEST_OUTPUT:
fail_compilation/fail7848.d(35): Error: pure function 'fail7848.C.__unittestL33_$n$' cannot call impure function 'fail7848.func'
fail_compilation/fail7848.d(35): Error: safe function 'fail7848.C.__unittestL33_$n$' cannot call system function 'fail7848.func'
fail_compilation/fail7848.d(35): Error: @nogc function 'fail7848.C.__unittestL33_$n$' cannot call non-@nogc function 'fail7848.func'
fail_compilation/fail7848.d(35): Error: 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(35): Error: function 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(33): Error: function 'fail7848.C.__unittestL33_$n$' is nothrow yet may throw
fail_compilation/fail7848.d(40): Error: pure function 'fail7848.C.__invariant2' cannot call impure function 'fail7848.func'
fail_compilation/fail7848.d(40): Error: safe function 'fail7848.C.__invariant2' cannot call system function 'fail7848.func'
fail_compilation/fail7848.d(40): Error: @nogc function 'fail7848.C.__invariant2' cannot call non-@nogc function 'fail7848.func'
fail_compilation/fail7848.d(40): Error: 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(40): Error: function 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(38): Error: function 'fail7848.C.__invariant2' is nothrow yet may throw
fail_compilation/fail7848.d(45): Error: pure function 'fail7848.C.new' cannot call impure function 'fail7848.func'
fail_compilation/fail7848.d(45): Error: safe function 'fail7848.C.new' cannot call system function 'fail7848.func'
fail_compilation/fail7848.d(45): Error: @nogc function 'fail7848.C.new' cannot call non-@nogc function 'fail7848.func'
fail_compilation/fail7848.d(45): Error: 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(45): Error: pure allocator 'fail7848.C.new' cannot call impure function 'fail7848.func'
fail_compilation/fail7848.d(45): Error: safe allocator 'fail7848.C.new' cannot call system function 'fail7848.func'
fail_compilation/fail7848.d(45): Error: @nogc allocator 'fail7848.C.new' cannot call non-@nogc function 'fail7848.func'
fail_compilation/fail7848.d(45): Error: function 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(43): Error: allocator 'fail7848.C.new' is nothrow yet may throw
fail_compilation/fail7848.d(51): Error: pure function 'fail7848.C.delete' cannot call impure function 'fail7848.func'
fail_compilation/fail7848.d(51): Error: safe function 'fail7848.C.delete' cannot call system function 'fail7848.func'
fail_compilation/fail7848.d(51): Error: @nogc function 'fail7848.C.delete' cannot call non-@nogc function 'fail7848.func'
fail_compilation/fail7848.d(51): Error: 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(51): Error: pure deallocator 'fail7848.C.delete' cannot call impure function 'fail7848.func'
fail_compilation/fail7848.d(51): Error: safe deallocator 'fail7848.C.delete' cannot call system function 'fail7848.func'
fail_compilation/fail7848.d(51): Error: @nogc deallocator 'fail7848.C.delete' cannot call non-@nogc function 'fail7848.func'
fail_compilation/fail7848.d(51): Error: function 'fail7848.func' is not nothrow
fail_compilation/fail7848.d(49): Error: deallocator 'fail7848.C.delete' is nothrow yet may throw
---
*/
Expand Down
36 changes: 18 additions & 18 deletions test/fail_compilation/nogc1.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ struct S5 { @nogc new(size_t); }
/*
TEST_OUTPUT:
---
fail_compilation/nogc1.d(27): Error: cannot use 'new' in @nogc function testNew
fail_compilation/nogc1.d(29): Error: cannot use 'new' in @nogc function testNew
fail_compilation/nogc1.d(30): Error: cannot use 'new' in @nogc function testNew
fail_compilation/nogc1.d(32): Error: cannot use 'new' in @nogc function testNew
fail_compilation/nogc1.d(33): Error: @nogc function 'nogc1.testNew' cannot call non-@nogc function 'nogc1.S2.this'
fail_compilation/nogc1.d(34): Error: cannot use 'new' in @nogc function testNew
fail_compilation/nogc1.d(35): Error: @nogc function 'nogc1.testNew' cannot call non-@nogc function 'nogc1.S4.new'
fail_compilation/nogc1.d(38): Error: cannot use 'new' in @nogc function testNew
fail_compilation/nogc1.d(27): Error: cannot use 'new' in @nogc function 'nogc1.testNew'
fail_compilation/nogc1.d(29): Error: cannot use 'new' in @nogc function 'nogc1.testNew'
fail_compilation/nogc1.d(30): Error: cannot use 'new' in @nogc function 'nogc1.testNew'
fail_compilation/nogc1.d(32): Error: cannot use 'new' in @nogc function 'nogc1.testNew'
fail_compilation/nogc1.d(33): Error: @nogc function 'nogc1.testNew' cannot call non-@nogc constructor 'nogc1.S2.this'
fail_compilation/nogc1.d(34): Error: cannot use 'new' in @nogc function 'nogc1.testNew'
fail_compilation/nogc1.d(35): Error: @nogc function 'nogc1.testNew' cannot call non-@nogc allocator 'nogc1.S4.new'
fail_compilation/nogc1.d(38): Error: cannot use 'new' in @nogc function 'nogc1.testNew'
---
*/
@nogc void testNew()
Expand All @@ -41,13 +41,13 @@ fail_compilation/nogc1.d(38): Error: cannot use 'new' in @nogc function testNew
/*
TEST_OUTPUT:
---
fail_compilation/nogc1.d(55): Error: cannot use 'new' in @nogc function testNewScope
fail_compilation/nogc1.d(57): Error: cannot use 'new' in @nogc function testNewScope
fail_compilation/nogc1.d(58): Error: cannot use 'new' in @nogc function testNewScope
fail_compilation/nogc1.d(60): Error: cannot use 'new' in @nogc function testNewScope
fail_compilation/nogc1.d(61): Error: @nogc function 'nogc1.testNewScope' cannot call non-@nogc function 'nogc1.S2.this'
fail_compilation/nogc1.d(62): Error: cannot use 'new' in @nogc function testNewScope
fail_compilation/nogc1.d(63): Error: @nogc function 'nogc1.testNewScope' cannot call non-@nogc function 'nogc1.S4.new'
fail_compilation/nogc1.d(55): Error: cannot use 'new' in @nogc function 'nogc1.testNewScope'
fail_compilation/nogc1.d(57): Error: cannot use 'new' in @nogc function 'nogc1.testNewScope'
fail_compilation/nogc1.d(58): Error: cannot use 'new' in @nogc function 'nogc1.testNewScope'
fail_compilation/nogc1.d(60): Error: cannot use 'new' in @nogc function 'nogc1.testNewScope'
fail_compilation/nogc1.d(61): Error: @nogc function 'nogc1.testNewScope' cannot call non-@nogc constructor 'nogc1.S2.this'
fail_compilation/nogc1.d(62): Error: cannot use 'new' in @nogc function 'nogc1.testNewScope'
fail_compilation/nogc1.d(63): Error: @nogc function 'nogc1.testNewScope' cannot call non-@nogc allocator 'nogc1.S4.new'
---
*/
@nogc void testNewScope()
Expand All @@ -72,9 +72,9 @@ fail_compilation/nogc1.d(63): Error: @nogc function 'nogc1.testNewScope' cannot
/*
TEST_OUTPUT:
---
fail_compilation/nogc1.d(82): Error: cannot use 'delete' in @nogc function testDelete
fail_compilation/nogc1.d(83): Error: cannot use 'delete' in @nogc function testDelete
fail_compilation/nogc1.d(84): Error: cannot use 'delete' in @nogc function testDelete
fail_compilation/nogc1.d(82): Error: cannot use 'delete' in @nogc function 'nogc1.testDelete'
fail_compilation/nogc1.d(83): Error: cannot use 'delete' in @nogc function 'nogc1.testDelete'
fail_compilation/nogc1.d(84): Error: cannot use 'delete' in @nogc function 'nogc1.testDelete'
---
*/
@nogc void testDelete(int* p, Object o, S1* s)
Expand Down
34 changes: 17 additions & 17 deletions test/fail_compilation/nogc2.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/nogc2.d(21): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(22): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(23): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(25): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(26): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(27): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(28): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(29): Error: cannot use operator ~ in @nogc function testCat
fail_compilation/nogc2.d(21): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(22): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(23): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(25): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(26): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(27): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(28): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
fail_compilation/nogc2.d(29): Error: cannot use operator ~ in @nogc function 'nogc2.testCat'
---
*/
@nogc void testCat(int[] a, string s)
Expand All @@ -38,9 +38,9 @@ fail_compilation/nogc2.d(29): Error: cannot use operator ~ in @nogc function tes
/*
TEST_OUTPUT:
---
fail_compilation/nogc2.d(48): Error: cannot use operator ~= in @nogc function testCatAssign
fail_compilation/nogc2.d(50): Error: cannot use operator ~= in @nogc function testCatAssign
fail_compilation/nogc2.d(51): Error: cannot use operator ~= in @nogc function testCatAssign
fail_compilation/nogc2.d(48): Error: cannot use operator ~= in @nogc function 'nogc2.testCatAssign'
fail_compilation/nogc2.d(50): Error: cannot use operator ~= in @nogc function 'nogc2.testCatAssign'
fail_compilation/nogc2.d(51): Error: cannot use operator ~= in @nogc function 'nogc2.testCatAssign'
---
*/
@nogc void testCatAssign(int[] a, string s)
Expand All @@ -58,8 +58,8 @@ fail_compilation/nogc2.d(51): Error: cannot use operator ~= in @nogc function te
/*
TEST_OUTPUT:
---
fail_compilation/nogc2.d(70): Error: array literal in @nogc function testArray may cause GC allocation
fail_compilation/nogc2.d(71): Error: array literal in @nogc function testArray may cause GC allocation
fail_compilation/nogc2.d(70): Error: array literal in @nogc function 'nogc2.testArray' may cause GC allocation
fail_compilation/nogc2.d(71): Error: array literal in @nogc function 'nogc2.testArray' may cause GC allocation
---
*/
@nogc void testArray()
Expand All @@ -76,8 +76,8 @@ fail_compilation/nogc2.d(71): Error: array literal in @nogc function testArray m
/*
TEST_OUTPUT:
---
fail_compilation/nogc2.d(87): Error: associative array literal in @nogc function testAssocArray may cause GC allocation
fail_compilation/nogc2.d(88): Error: associative array literal in @nogc function testAssocArray may cause GC allocation
fail_compilation/nogc2.d(87): Error: associative array literal in @nogc function 'nogc2.testAssocArray' may cause GC allocation
fail_compilation/nogc2.d(88): Error: associative array literal in @nogc function 'nogc2.testAssocArray' may cause GC allocation
---
*/
@nogc void testAssocArray()
Expand All @@ -93,8 +93,8 @@ fail_compilation/nogc2.d(88): Error: associative array literal in @nogc function
/*
TEST_OUTPUT:
---
fail_compilation/nogc2.d(102): Error: indexing an associative array in @nogc function testIndex may cause GC allocation
fail_compilation/nogc2.d(103): Error: indexing an associative array in @nogc function testIndex may cause GC allocation
fail_compilation/nogc2.d(102): Error: indexing an associative array in @nogc function 'nogc2.testIndex' may cause GC allocation
fail_compilation/nogc2.d(103): Error: indexing an associative array in @nogc function 'nogc2.testIndex' may cause GC allocation
---
*/
@nogc void testIndex(int[int] aa)
Expand Down
6 changes: 3 additions & 3 deletions test/fail_compilation/nogc3.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/nogc3.d(16): Error: setting 'length' in @nogc function testArrayLength may cause GC allocation
fail_compilation/nogc3.d(17): Error: setting 'length' in @nogc function testArrayLength may cause GC allocation
fail_compilation/nogc3.d(18): Error: setting 'length' in @nogc function testArrayLength may cause GC allocation
fail_compilation/nogc3.d(16): Error: setting 'length' in @nogc function 'nogc3.testArrayLength' may cause GC allocation
fail_compilation/nogc3.d(17): Error: setting 'length' in @nogc function 'nogc3.testArrayLength' may cause GC allocation
fail_compilation/nogc3.d(18): Error: setting 'length' in @nogc function 'nogc3.testArrayLength' may cause GC allocation
---
*/
@nogc void testArrayLength(int[] a)
Expand Down
51 changes: 33 additions & 18 deletions test/runnable/testdstress.d
Original file line number Diff line number Diff line change
Expand Up @@ -622,33 +622,48 @@ void test29()
}

/* ================================ */
// Test for FinalizeError - it will be thrown if an Exception is thrown
// during the class object finalization.

int status30;

class C30
{
this(){
status30++;
}

~this(){
status30--;
throw new Exception("E2");
}
this()
{
status30++;
}

~this()
{
status30--;
throw new Exception("E2");
}
}

void test30()
{
try{
scope C30 m = new C30();
assert(status30 == 1);
delete m;
}catch(Error e){
assert(status30 == 0);
status30--;
}

assert(status30 == -1);
try
{
//scope C30 m = new C30();
// It will insert one more `delete m` for the scope destruction, and it will be
// called during stack unwinding.
// Instead use bare memory chunk on stack to construct dummy class instance.
void[__traits(classInstanceSize, C30)] payload = typeid(C30).init[];
C30 m = cast(C30)payload.ptr;
m.__ctor();

assert(status30 == 1);

delete m; // _d_callfinalizer
}
catch (Error e) // FinalizeError
{
assert(status30 == 0);
status30--;
}

assert(status30 == -1);
}

/* ================================ */
Expand Down