Unwrap director classes only when returning a pointer or reference to an object

This involves properly counting the number of references and pointers in the return
type of a function and only generate unwrapping code if this number is 1.
For template instances some post-processing code is added to fix the 'decl' and
'type' attributes of functions if changed in an unfavorable way during template
expansion.
This commit fixes swig#1811.
This commit is contained in:
Thomas Reitmayr 2020-06-09 21:58:47 +02:00
commit 01277d700c
9 changed files with 369 additions and 6 deletions

View file

@ -141,6 +141,8 @@ extern "C" {
extern List *SwigType_split(const SwigType *t);
extern String *SwigType_pop(SwigType *t);
extern void SwigType_push(SwigType *t, String *s);
extern SwigType *SwigType_last(SwigType *t);
extern int SwigType_refptr_count_return(const SwigType *t);
extern List *SwigType_parmlist(const SwigType *p);
extern String *SwigType_parm(const SwigType *p);
extern String *SwigType_str(const SwigType *s, const_String_or_char_ptr id);

View file

@ -208,6 +208,90 @@ SwigType *SwigType_pop(SwigType *t) {
return result;
}
/* -----------------------------------------------------------------------------
* SwigType_last()
*
* Return the last element of the given (partial) type.
* For example:
* t: q(const).p.
* result: p.
* ----------------------------------------------------------------------------- */
SwigType *SwigType_last(SwigType *t) {
SwigType *result;
char *c;
char *last;
int sz = 0;
if (!t)
return 0;
/* Find the last element */
c = Char(t);
last = 0;
while (*c) {
last = c;
sz = element_size(c);
c = c + sz;
if (*c == '.') {
c++;
sz++;
}
}
/* Extract the last element */
if (last) {
result = NewStringWithSize(last, sz);
} else {
result = 0;
}
return result;
}
/* -----------------------------------------------------------------------------
* SwigType_refptr_count_return()
*
* Returns the number of pointer and reference indirections found in the given
* type. For functions this concerns the return type.
* For example:
* r.p. => 2
* q(const).p. => 1
* r.f(int).p.p. => 2
* f().p.q(const).p. => 2
* ----------------------------------------------------------------------------- */
int SwigType_refptr_count_return(const SwigType *t) {
char *c;
char *last;
int sz;
int result = 0;
if (!t)
return 0;
c = Char(t);
last = c;
while (*c) {
last = c;
sz = element_size(c);
c = c + sz;
if (*(c-1) == '.') {
if (((last[0] == 'p') || (last[0] == 'r')) && (last[1] == '.')) {
result++;
} else if (strncmp(last, "f(", 2) == 0) {
/* restart counter if this is a function type */
result = 0;
}
}
if (*c == '.') {
c++;
}
}
return result;
}
/* -----------------------------------------------------------------------------
* SwigType_parm()
*