[D] Fix occasional undefined behaviour with inheritance hierarchies

Particularly when using virtual inheritance as the pointers weren't
correctly upcast from derived class to base class when stored in the
base's proxy class.

Fixes commented out test code in cpp11_std_unique_ptr_runme
and li_std_auto_ptr_runme D tests.
This commit is contained in:
William S Fulton 2022-08-05 19:36:54 +01:00
commit 910fd1e3cf
8 changed files with 73 additions and 12 deletions

View file

@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
2022-08-05: wsfulton
[D] Fix occasional undefined behaviour with inheritance hierarchies, particularly
when using virtual inheritance as the pointers weren't correctly upcast from derived
class to base class when stored in the base's proxy class.
2022-08-05: wsfulton
[D] Add support for std::unique_ptr in std_unique_ptr.i.
Add support for std::auto_ptr in std_auto_ptr.i.

View file

@ -10,6 +10,7 @@
%inline %{
#include <memory>
#include <string>
//#include <iostream>
#include "swig_examples_lock.h"
class Klass {
@ -53,8 +54,18 @@ struct KlassInheritance : virtual Klass {
}
};
std::string useKlassRawPtr(Klass* k) {
// std::cout << "useKlassRawPtr " << std::hex << (Klass*)k << std::endl;
std::string s(k->getLabel());
// std::cout << "useKlassRawPtr string: " << s << std::endl;
return s;
}
std::string takeKlassUniquePtr(std::unique_ptr<Klass> k) {
return std::string(k->getLabel());
// std::cout << "takeKlassUniquePtr " << std::hex << (Klass*)k.get() << std::endl;
std::string s(k->getLabel());
// std::cout << "takeKlassUniquePtr string: " << s << std::endl;
return s;
}
bool is_nullptr(Klass *p) {

View file

@ -13,6 +13,16 @@ void checkCount(int expected_count) {
}
void main() {
// Test raw pointer handling involving virtual inheritance
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
string s = useKlassRawPtr(kini);
if (s != "KlassInheritanceInput")
throw new Exception("Incorrect string: " ~ s);
}
checkCount(0);
// unique_ptr as input
{
scope Klass kin = new Klass("KlassInput");
@ -65,7 +75,6 @@ void main() {
}
checkCount(0);
/*
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
@ -77,7 +86,6 @@ void main() {
throw new Exception("is_nullptr failed");
} // dispose should not fail, even though already deleted
checkCount(0);
*/
// unique_ptr as output
Klass k1 = makeKlassUniquePtr("first");

View file

@ -13,6 +13,16 @@ void checkCount(int expected_count) {
}
void main() {
// Test raw pointer handling involving virtual inheritance
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
string s = useKlassRawPtr(kini);
if (s != "KlassInheritanceInput")
throw new Exception("Incorrect string: " ~ s);
}
checkCount(0);
// unique_ptr as input
{
scope Klass kin = new Klass("KlassInput");
@ -65,7 +75,6 @@ void main() {
}
checkCount(0);
/*
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
@ -77,7 +86,6 @@ void main() {
throw new Exception("is_nullptr failed");
} // dispose should not fail, even though already deleted
checkCount(0);
*/
// unique_ptr as output
Klass k1 = makeKlassUniquePtr("first");

View file

@ -13,6 +13,16 @@ void checkCount(int expected_count) {
}
void main() {
// Test raw pointer handling involving virtual inheritance
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
string s = useKlassRawPtr(kini);
if (s != "KlassInheritanceInput")
throw new Exception("Incorrect string: " ~ s);
}
checkCount(0);
// auto_ptr as input
{
scope Klass kin = new Klass("KlassInput");
@ -65,7 +75,6 @@ void main() {
}
checkCount(0);
/*
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
@ -77,7 +86,6 @@ void main() {
throw new Exception("is_nullptr failed");
} // dispose should not fail, even though already deleted
checkCount(0);
*/
// auto_ptr as output
Klass k1 = makeKlassAutoPtr("first");

View file

@ -13,6 +13,17 @@ void checkCount(int expected_count) {
}
void main() {
// Test raw pointer handling involving virtual inheritance
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
string s = useKlassRawPtr(kini);
checkCount(1);
if (s != "KlassInheritanceInput")
throw new Exception("Incorrect string: " ~ s);
}
checkCount(0);
// auto_ptr as input
{
scope Klass kin = new Klass("KlassInput");
@ -65,7 +76,6 @@ void main() {
}
checkCount(0);
/*
{
scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
@ -77,7 +87,6 @@ void main() {
throw new Exception("is_nullptr failed");
} // dispose should not fail, even though already deleted
checkCount(0);
*/
// auto_ptr as output
Klass k1 = makeKlassAutoPtr("first");

View file

@ -15,6 +15,7 @@
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD)
%include "std_string.i"
//#include <iostream>
%include "std_auto_ptr.i"
%auto_ptr(Klass)
@ -100,10 +101,21 @@ struct KlassInheritance : virtual Klass {
}
};
std::string takeKlassAutoPtr(std::auto_ptr<Klass> k) {
return std::string(k->getLabel());
std::string useKlassRawPtr(Klass* k) {
// std::cout << "useKlassRawPtr " << std::hex << (Klass*)k << std::endl;
std::string s(k->getLabel());
// std::cout << "useKlassRawPtr string: " << s << std::endl;
return s;
}
std::string takeKlassAutoPtr(std::auto_ptr<Klass> k) {
// std::cout << "takeKlassAutoPtr " << std::hex << (Klass*)k.get() << std::endl;
std::string s(k->getLabel());
// std::cout << "takeKlassAutoPtr string: " << s << std::endl;
return s;
}
bool is_nullptr(Klass *p) {
return p == 0;
}

View file

@ -3402,7 +3402,7 @@ private:
} else {
Printv(upcasts_code,
"SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name,
"(", baseclassname, " *objectRef) {\n",
"(", classname, " *objectRef) {\n",
" return (", baseclassname, " *)objectRef;\n"
"}\n",
"\n", NIL);