Fix regression wrapping default const bool argument

We need to strip qualifiers before checking the type is `bool`.

This mainly affects Python.  In Ruby there's equivalent code, but
it is only use to generate documentation comments.

Fixes #3052
This commit is contained in:
Olly Betts 2024-10-19 15:40:18 +13:00
parent e528260b83
commit c1e0a68f86
5 changed files with 55 additions and 24 deletions

View File

@ -1,11 +1,19 @@
%module default_arg_values
%{
%inline %{
#ifdef SWIG
// Some compilers warn about 'float v = NULL', so only SWIG sees this peculiarity
// Bad Python wrappers were being generated when NULL used for primitive type
# define NULL_FOR_FLOAT NULL
#else
# define NULL_FOR_FLOAT 0
#endif
struct Display {
// Some compilers warn about 'float v = NULL', so only SWIG sees this peculiarity
// Bad Python wrappers were being generated when NULL used for primitive type
float draw1(float v = 0) { return v; }
float draw2(float *v = 0) { return v ? *v : 0; }
float draw1(float v = NULL_FOR_FLOAT) { return v; }
float draw2(float *v = NULL_FOR_FLOAT) { return v ? *v : 0; }
int draw3(int index = 0, const bool interpolate = true) { return interpolate ? index : -index; }
bool bool0(bool x = 0) { return x; }
bool bool1(bool x = 1) { return x; }
@ -14,17 +22,5 @@ struct Display {
bool mybool1(mybool x = 1) { return x; }
};
float* createPtr(float v) { static float val; val = v; return &val; }
%}
struct Display {
// Bad Python wrappers were being generated when NULL used for primitive type
float draw1(float v = NULL) { return v; }
float draw2(float *v = NULL) { return v ? *v : 0; }
bool bool0(bool x = 0) { return x; }
bool bool1(bool x = 1) { return x; }
typedef bool mybool;
bool mybool0(mybool x = 0) { return x; }
bool mybool1(mybool x = 1) { return x; }
};
float* createPtr(float v) { static float val; val = v; return &val; }

View File

@ -15,6 +15,9 @@ if d.draw2() != 0:
if d.draw2(p) != 123:
raise RuntimeError
if d.draw3() != 0:
raise RuntimeError
if d.bool0() != False or type(d.bool0()) != type(False):
raise RuntimeError

View File

@ -0,0 +1,26 @@
#!/usr/bin/env ruby
require 'swig_assert'
require 'default_arg_values'
d = Default_arg_values::Display.new
raise RuntimeError if d.draw1() != 0
raise RuntimeError if d.draw1(12) != 12
p = Default_arg_values::createPtr(123)
raise RuntimeError if d.draw2() != 0
raise RuntimeError if d.draw2(p) != 123
raise RuntimeError if d.draw3() != 0
raise RuntimeError unless d.bool0() === false
raise RuntimeError unless d.bool1() === true
raise RuntimeError unless d.mybool0() === false
raise RuntimeError unless d.mybool1() === true

View File

@ -2146,22 +2146,24 @@ public:
// FIXME: This needs more careful testing.
// return NewStringf("'%(escape)s'", stringval);
}
SwigType *resolved_type = SwigType_typedef_resolve_all(type);
SwigType *unqualified_type = SwigType_strip_qualifiers(resolved_type);
if (numval) {
SwigType *resolved_type = SwigType_typedef_resolve_all(type);
if (Equal(resolved_type, "bool")) {
if (Equal(unqualified_type, "bool")) {
Delete(resolved_type);
Delete(unqualified_type);
return NewString(*Char(numval) == '0' ? "False" : "True");
}
String *result = convertIntegerValue(numval, resolved_type);
String *result = convertIntegerValue(numval, unqualified_type);
Delete(resolved_type);
Delete(unqualified_type);
return result;
}
SwigType *resolved_type = SwigType_typedef_resolve_all(type);
String *result = convertDoubleValue(v);
if (!result) {
if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
result = SwigType_ispointer(resolved_type) ? NewString("None") : NewString("0");
result = SwigType_ispointer(unqualified_type) ? NewString("None") : NewString("0");
// This could also be an enum type, default value of which could be
// representable in Python if it doesn't include any scope (which could,
// but currently is not, translated).
@ -2175,6 +2177,7 @@ public:
}
Delete(resolved_type);
Delete(unqualified_type);
return result;
}

View File

@ -777,11 +777,14 @@ private:
}
if (numval) {
SwigType *resolved_type = SwigType_typedef_resolve_all(type);
if (Equal(resolved_type, "bool")) {
SwigType *unqualified_type = SwigType_strip_qualifiers(resolved_type);
if (Equal(unqualified_type, "bool")) {
Delete(resolved_type);
Delete(unqualified_type);
return NewString(*Char(numval) == '0' ? "false" : "true");
}
Delete(resolved_type);
Delete(unqualified_type);
if (SwigType_ispointer(type) && Equal(v, "0"))
return NewString("None");
return Copy(v);