Fix SWIG's handling of qualified (e.g. const) variables of array type

This commit is contained in:
Karl Wette 2013-02-18 09:48:42 +01:00 committed by William S Fulton
commit ee2b46abe0
4 changed files with 153 additions and 0 deletions

View file

@ -5,6 +5,18 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.10 (in progress)
============================
2013-02-19: kwwette
Fix bug in SWIG's handling of qualified (e.g. const) variables of array type. Given the typedef
a(7).q(volatile).double myarray // typedef volatile double[7] myarray;
the type
q(const).myarray // const myarray
becomes
a(7).q(const volatile).double // const volatile double[7]
Previously, SwigType_typedef_resolve() produces the type
q(const).a(7).q(volatile).double // non-sensical type
which would never match %typemap declarations, whose types were parsed correctly.
Add typemap_array_qualifiers.i to the test suite which checks for the correct behaviour.
2013-02-18: wsfulton
Deprecate typedef names used as constructor and destructor names in %extend. The real
class/struct name should be used.

View file

@ -433,6 +433,7 @@ CPP_TEST_CASES += \
typedef_sizet \
typedef_struct \
typemap_arrays \
typemap_array_qualifiers \
typemap_delete \
typemap_directorout \
typemap_global_scope \

View file

@ -0,0 +1,79 @@
%module typemap_array_qualifiers
%define CLEAR_SWIGTYPE_TYPEMAPS
%typemap(in)
SWIGTYPE,
SWIGTYPE *,
SWIGTYPE *const,
SWIGTYPE *const&,
const SWIGTYPE *,
const SWIGTYPE *const,
const SWIGTYPE *const&,
const volatile SWIGTYPE *,
const volatile SWIGTYPE *const,
const volatile SWIGTYPE *const&,
SWIGTYPE [],
SWIGTYPE [ANY],
const SWIGTYPE [],
const SWIGTYPE [ANY],
const volatile SWIGTYPE [],
const volatile SWIGTYPE [ANY],
SWIGTYPE &,
const SWIGTYPE &,
const volatile SWIGTYPE &
{
%#error Incorrect typemap for $symname: $type
}
%enddef
%inline %{
typedef struct {
int a;
} SomeType;
typedef SomeType myarray[3];
typedef const SomeType myconstarray[4];
typedef volatile SomeType ** mycrazyarray[5];
typedef volatile SomeType (mycrazyfunc)(SomeType);
typedef volatile SomeType (*mycrazyfuncptr)(SomeType);
%}
CLEAR_SWIGTYPE_TYPEMAPS;
%typemap(in) SWIGTYPE [ANY] {
/* Correct typemap for $symname: $type */
}
%inline %{
void func1a(myarray x) {};
void func1b(volatile myarray x) {};
%}
CLEAR_SWIGTYPE_TYPEMAPS;
%typemap(in) const SWIGTYPE [ANY] {
/* Correct typemap for $symname: $type */
}
%typemap(in) const volatile SWIGTYPE [ANY] {
/* Correct typemap for $symname: $type */
}
%inline %{
void func2a(const myarray x) {};
void func2b(const myconstarray x) {};
void func2c(const volatile myconstarray x) {};
%}
CLEAR_SWIGTYPE_TYPEMAPS;
%typemap(in) volatile SWIGTYPE **const [ANY] {
/* Correct typemap for $symname: $type */
}
%typemap(in) volatile SWIGTYPE **const [ANY][ANY] {
/* Correct typemap for $symname: $type */
}
%inline %{
void func3a(const mycrazyarray x, const mycrazyarray y[7]) {};
%}
CLEAR_SWIGTYPE_TYPEMAPS;
%typemap(in) SWIGTYPE (*const) (ANY) {
/* Correct typemap for $symname: $type */
}
%inline %{
void func4a(mycrazyfunc *const x, const mycrazyfuncptr y) {};
%}

View file

@ -792,6 +792,67 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) {
goto return_result;
}
Delete(base);
/* If 'type' is an array, then the right-most qualifier in 'r' should
be added to 'type' after the array qualifier, so that given
a(7).q(volatile).double myarray // typedef volatile double[7] myarray;
the type
q(const).myarray // const myarray
becomes
a(7).q(const volatile).double // const volatile double[7]
and NOT
q(const).a(7).q(volatile).double // non-sensical type
*/
if (r && Len(r) && SwigType_isarray(type)) {
List *r_elem;
String *r_qual;
int r_sz;
r_elem = SwigType_split(r);
r_sz = Len(r_elem);
r_qual = Getitem(r_elem, r_sz-1);
if (SwigType_isqualifier(r_qual)) {
String *new_r;
String *new_type;
List *type_elem;
String *type_qual;
String *r_qual_arg;
int i, type_sz;
type_elem = SwigType_split(type);
type_sz = Len(type_elem);
i = 0;
for (i = 0; i < type_sz; ++i) {
String *e = Getitem(type_elem, i);
if (!SwigType_isarray(e))
break;
}
type_qual = Copy(Getitem(type_elem, i));
r_qual_arg = SwigType_parm(r_qual);
SwigType_add_qualifier(type_qual, r_qual_arg);
Delete(r_qual_arg);
Setitem(type_elem, i, type_qual);
new_r = NewStringEmpty();
for (i = 0; i < r_sz-1; ++i) {
Append(new_r, Getitem(r_elem, i));
}
new_type = NewStringEmpty();
for (i = 0; i < type_sz; ++i) {
Append(new_type, Getitem(type_elem, i));
}
#ifdef SWIG_DEBUG
Printf(stdout, "r+type='%s%s' new_r+new_type='%s%s'\n", r, type, new_r, new_type);
#endif
Delete(r);
r = new_r;
newtype = 1;
type = new_type;
Delete(type_elem);
}
Delete(r_elem);
}
Append(r, type);
if (newtype) {
Delete(type);