Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 9a084ed

Browse files
authored
Merge pull request #3284 from n8sh/issue-21417
core.stdcpp.new_.cpp_delete unnecessarily requires destruction to be @nogc merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
2 parents 8ba7ecb + 1d4a1dd commit 9a084ed

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

src/core/stdcpp/new_.d

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ module core.stdcpp.new_;
1414
import core.stdcpp.xutility : __cpp_sized_deallocation, __cpp_aligned_new;
1515
import core.stdcpp.exception : exception;
1616

17-
@nogc:
18-
1917
// TODO: this really should come from __traits(getTargetInfo, "defaultNewAlignment")
2018
version (D_LP64)
2119
enum size_t __STDCPP_DEFAULT_NEW_ALIGNMENT__ = 16;
@@ -69,12 +67,13 @@ void cpp_delete(T)(T* ptr) if (!is(T == class))
6967
void cpp_delete(T)(T instance) if (is(T == class))
7068
{
7169
destroy!false(instance);
72-
__cpp_delete(instance);
70+
__cpp_delete(cast(void*) instance);
7371
}
7472

7573

7674
// raw C++ functions
7775
extern(C++):
76+
@nogc:
7877

7978
/// Binding for ::operator new(std::size_t count)
8079
pragma(mangle, __new_mangle)

test/stdcpp/src/new_test.d

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,106 @@ unittest
3232
s.c = cast(MyStruct*)__cpp_new(MyStruct.sizeof);
3333
cpp_delete(s);
3434
}
35+
36+
@nogc unittest
37+
{
38+
// Test cpp_new and cpp_delete for a struct infer @nogc.
39+
import core.stdcpp.new_: cpp_new, cpp_delete;
40+
extern(C++) static struct MyStructNoGC
41+
{
42+
__gshared int numDeleted;
43+
int x = 3;
44+
this(int x) @nogc { this.x = x; }
45+
~this() @nogc { ++numDeleted; }
46+
}
47+
48+
MyStructNoGC* c1 = cpp_new!MyStructNoGC(4);
49+
assert(c1.x == 4);
50+
assert(MyStructNoGC.numDeleted == 0);
51+
cpp_delete(c1);
52+
assert(MyStructNoGC.numDeleted == 1);
53+
}
54+
55+
/+
56+
// BUG: @nogc not being applied to __xdtor for extern(C++) class.
57+
extern(C++) class MyClassNoGC
58+
{
59+
__gshared int numDeleted;
60+
int x = 3;
61+
this(int x) @nogc { this.x = x; }
62+
~this() @nogc { ++numDeleted; }
63+
}
64+
65+
@nogc unittest
66+
{
67+
// Test cpp_new and cpp_delete for a class infer @nogc.
68+
import core.stdcpp.new_: cpp_new, cpp_delete;
69+
70+
MyClassNoGC c1 = cpp_new!MyClassNoGC(4);
71+
assert(c1.x == 4);
72+
assert(MyClassNoGC.numDeleted == 0);
73+
cpp_delete(c1);
74+
assert(MyClassNoGC.numDeleted == 1);
75+
}
76+
+/
77+
78+
unittest
79+
{
80+
import core.stdcpp.new_: cpp_new, cpp_delete;
81+
82+
// Test cpp_new & cpp_delete are callable with a struct whose destructor
83+
// is not @nogc.
84+
{
85+
extern(C++) static struct MyStructGC
86+
{
87+
__gshared int numDeleted;
88+
int x = 5;
89+
this(int x)
90+
{
91+
if (x == int.min)
92+
throw new Exception("forbidden number");
93+
this.x = x;
94+
}
95+
~this()
96+
{
97+
if (++numDeleted < 0)
98+
throw new Exception("overflow in dtor");
99+
}
100+
}
101+
static assert(!is(typeof(() @nogc => cpp_new!MyStructGC(6))));
102+
MyStructGC* c2 = cpp_new!MyStructGC(6);
103+
assert(c2.x == 6);
104+
static assert(!is(typeof(() @nogc => cpp_delete(c2))));
105+
assert(MyStructGC.numDeleted == 0);
106+
cpp_delete(c2);
107+
assert(MyStructGC.numDeleted == 1);
108+
}
109+
110+
// Test cpp_new & cpp_delete are callable with a class whose destructor
111+
// is not @nogc.
112+
{
113+
extern(C++) static class MyClassGC
114+
{
115+
__gshared int numDeleted;
116+
int x = 5;
117+
this(int x)
118+
{
119+
if (x == int.min)
120+
throw new Exception("forbidden number x");
121+
this.x = x;
122+
}
123+
~this()
124+
{
125+
if (++numDeleted < 0)
126+
throw new Exception("overflow in dtor for x");
127+
}
128+
}
129+
static assert(!is(typeof(() @nogc => cpp_new!MyClassGC(6))));
130+
MyClassGC c2 = cpp_new!MyClassGC(6);
131+
assert(c2.x == 6);
132+
static assert(!is(typeof(() @nogc => cpp_delete(c2))));
133+
assert(MyClassGC.numDeleted == 0);
134+
cpp_delete(c2);
135+
assert(MyClassGC.numDeleted == 1);
136+
}
137+
}

0 commit comments

Comments
 (0)