rice 4.11.3 → 4.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/include/rice/rice.hpp +3 -2
- data/lib/rice/version.rb +1 -1
- data/rice/detail/Wrapper.ipp +3 -2
- data/test/test_Ownership.cpp +58 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '07196451c8152b8110d5a2aa17d9d1073c846139a8e08d3fe71217095c3386d6'
|
|
4
|
+
data.tar.gz: d0a84860a008461a29396679953abe8377f24b92ee9085ed84820dd946065390
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d560e79db1a4645bd6d1084e0df00a44d79795b14d963292e731912c1bcabf29578846ff18a2bf8f8cdb171419c1b13be66b358582328ff5e4d18c61aee8731
|
|
7
|
+
data.tar.gz: bfa6478914622bf559db804f3ccb10fd51c39973ff7032a07d2ced37c7d5fbbacd3b9417ed4399499f97f209ec115daecabd7e9ab75a145dfaba9c6c2d94478e
|
data/CHANGELOG.md
CHANGED
data/include/rice/rice.hpp
CHANGED
|
@@ -10283,8 +10283,9 @@ namespace Rice::detail
|
|
|
10283
10283
|
if constexpr (is_complete_v<T>)
|
|
10284
10284
|
{
|
|
10285
10285
|
// is_abstract_v requires a complete type, so nest inside is_complete_v.
|
|
10286
|
-
// Deleting an abstract class through a non-virtual destructor is UB
|
|
10287
|
-
if
|
|
10286
|
+
// Deleting an abstract class through a non-virtual destructor is UB,
|
|
10287
|
+
// but it is safe if the destructor is virtual.
|
|
10288
|
+
if constexpr (std::is_destructible_v<T> && (!std::is_abstract_v<T> || std::has_virtual_destructor_v<T>))
|
|
10288
10289
|
{
|
|
10289
10290
|
if (this->isOwner_)
|
|
10290
10291
|
{
|
data/lib/rice/version.rb
CHANGED
data/rice/detail/Wrapper.ipp
CHANGED
|
@@ -122,8 +122,9 @@ namespace Rice::detail
|
|
|
122
122
|
if constexpr (is_complete_v<T>)
|
|
123
123
|
{
|
|
124
124
|
// is_abstract_v requires a complete type, so nest inside is_complete_v.
|
|
125
|
-
// Deleting an abstract class through a non-virtual destructor is UB
|
|
126
|
-
if
|
|
125
|
+
// Deleting an abstract class through a non-virtual destructor is UB,
|
|
126
|
+
// but it is safe if the destructor is virtual.
|
|
127
|
+
if constexpr (std::is_destructible_v<T> && (!std::is_abstract_v<T> || std::has_virtual_destructor_v<T>))
|
|
127
128
|
{
|
|
128
129
|
if (this->isOwner_)
|
|
129
130
|
{
|
data/test/test_Ownership.cpp
CHANGED
|
@@ -188,6 +188,36 @@ namespace
|
|
|
188
188
|
static inline MyCopyableClass* instance_ = nullptr;
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
// Abstract class with virtual destructor - deletion through base pointer is safe
|
|
192
|
+
class AbstractVirtualDtor
|
|
193
|
+
{
|
|
194
|
+
public:
|
|
195
|
+
static inline int destructorCalls = 0;
|
|
196
|
+
|
|
197
|
+
static void reset()
|
|
198
|
+
{
|
|
199
|
+
destructorCalls = 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
virtual ~AbstractVirtualDtor()
|
|
203
|
+
{
|
|
204
|
+
destructorCalls++;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
virtual int compute() const = 0;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
class ConcreteChild : public AbstractVirtualDtor
|
|
211
|
+
{
|
|
212
|
+
public:
|
|
213
|
+
int compute() const override { return 42; }
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
AbstractVirtualDtor* createChild()
|
|
217
|
+
{
|
|
218
|
+
return new ConcreteChild();
|
|
219
|
+
}
|
|
220
|
+
|
|
191
221
|
class OwnerBox;
|
|
192
222
|
|
|
193
223
|
class AliasBox
|
|
@@ -327,6 +357,14 @@ SETUP(Ownership)
|
|
|
327
357
|
.define_constructor(Constructor<SharedFactory>())
|
|
328
358
|
.define_method("create_owned", &SharedFactory::createOwned, Return().takeOwnership())
|
|
329
359
|
.define_method("get_borrowed", &SharedFactory::getBorrowed);
|
|
360
|
+
|
|
361
|
+
define_class<AbstractVirtualDtor>("AbstractVirtualDtor")
|
|
362
|
+
.define_method("compute", &AbstractVirtualDtor::compute);
|
|
363
|
+
|
|
364
|
+
define_class<ConcreteChild, AbstractVirtualDtor>("ConcreteChild");
|
|
365
|
+
|
|
366
|
+
define_module("AbstractVirtualDtorTest")
|
|
367
|
+
.define_module_function("create_child", &createChild, Return().takeOwnership());
|
|
330
368
|
}
|
|
331
369
|
|
|
332
370
|
TEARDOWN(Ownership)
|
|
@@ -541,3 +579,23 @@ TESTCASE(MultipleOwnerReferences)
|
|
|
541
579
|
result = m.module_eval(code);
|
|
542
580
|
ASSERT_EQUAL(Qfalse, result.value());
|
|
543
581
|
}
|
|
582
|
+
|
|
583
|
+
TESTCASE(AbstractVirtualDestructor)
|
|
584
|
+
{
|
|
585
|
+
AbstractVirtualDtor::reset();
|
|
586
|
+
|
|
587
|
+
Module m = define_module("TestingModule");
|
|
588
|
+
|
|
589
|
+
std::string code = R"(child = AbstractVirtualDtorTest.create_child
|
|
590
|
+
child.compute)";
|
|
591
|
+
|
|
592
|
+
Object result = m.module_eval(code);
|
|
593
|
+
ASSERT_EQUAL(detail::To_Ruby<int>().convert(42), result.value());
|
|
594
|
+
|
|
595
|
+
// Force GC to clean up the object - destructor should be called
|
|
596
|
+
// since AbstractVirtualDtor has a virtual destructor
|
|
597
|
+
rb_gc_start();
|
|
598
|
+
rb_gc_start();
|
|
599
|
+
|
|
600
|
+
ASSERT_EQUAL(1, AbstractVirtualDtor::destructorCalls);
|
|
601
|
+
}
|