Fix missing constructor generation due to abstract class test failure

when a method is declared in the class along with a
using declaration and the using declaration is declared before
the method that implemented the pure virtual method, such as:

  struct ConcreteDerived : AbstractBase {
    ConcreteDerived() {} // was not wrapped
    using AbstractBase::f;
    virtual void f(int n) override {}
  };

SourceForge bug: https://sourceforge.net/p/swig/bugs/932/

check_implemented in allocate.cxx was correctly finding a
non-abstract method, however, Swig_symbol_clookup_local_check, was
using the using declaration node instead of using the node returned
by check_implemented. The checkfunc is now given more control by
returning the node to use rather than Swig_symbol_clookup_local_check
always using the head of the csym linked list.
This commit is contained in:
William S Fulton 2023-08-02 08:48:34 +01:00
parent 34e25241e7
commit 69d5373131
7 changed files with 105 additions and 40 deletions

View File

@ -7,6 +7,19 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress) Version 4.2.0 (in progress)
=========================== ===========================
2023-08-02: wsfulton
https://sourceforge.net/p/swig/bugs/932/
Fix missing constructor generation due to abstract class test
failure when a method is declared in the class along with a
using declaration and the using declaration is declared before
the method that implemented the pure virtual method, such as:
struct ConcreteDerived : AbstractBase {
ConcreteDerived() {} // was not wrapped
using AbstractBase::f;
virtual void f(int n) override {}
};
2023-08-02: olly 2023-08-02: olly
[PHP] Implement overloading between different integer types and [PHP] Implement overloading between different integer types and
between double and float. between double and float.

View File

@ -0,0 +1,31 @@
%module abstract_inherit_using
%inline %{
class AbstractBase
{
public:
virtual void f(int n) = 0;
void f(const char *another_representation_of_n) {}
virtual ~AbstractBase() {}
};
class ConcreteDerived1 : public AbstractBase
{
public:
ConcreteDerived1() {}
// Abstract test always worked
virtual void f(int n) {}
using AbstractBase::f;
};
class ConcreteDerived2 : public AbstractBase
{
public:
ConcreteDerived2() {}
// SWIG thought this class was abstract when using declaration was before method f and didn't generate constructor
using AbstractBase::f;
virtual void f(int n) {}
};
%}

View File

@ -0,0 +1,24 @@
import abstract_inherit_using.*;
public class abstract_inherit_using_runme {
static {
try {
System.loadLibrary("abstract_inherit_using");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[])
{
ConcreteDerived1 cd1 = new ConcreteDerived1();
cd1.f(1234);
cd1.f("one");
ConcreteDerived2 cd2 = new ConcreteDerived2();
cd2.f(1234);
cd2.f("one");
}
}

View File

@ -8,7 +8,12 @@
* *
* allocate.cxx * allocate.cxx
* *
* This module tries to figure out which classes and structures support * This module also has two main purposes modifying the parse tree.
*
* First, it is responsible for adding in using declarations from base class
* members into the parse tree.
*
* Second, after each class declaration, it analyses if the class/struct supports
* default constructors and destructors in C++. There are several rules that * default constructors and destructors in C++. There are several rules that
* define this behavior including pure abstract methods, private sections, * define this behavior including pure abstract methods, private sections,
* and non-default constructors in base classes. See the ARM or * and non-default constructors in base classes. See the ARM or
@ -17,9 +22,6 @@
* Once the analysis is complete, the non-explicit/implied default constructors * Once the analysis is complete, the non-explicit/implied default constructors
* and destructors are added to the parse tree. Implied copy constructors are * and destructors are added to the parse tree. Implied copy constructors are
* added too if requested via the copyctor feature. * added too if requested via the copyctor feature.
*
* This module also is responsible for adding in using declarations from base
* class members into the parse tree.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
#include "swigmod.h" #include "swigmod.h"
@ -37,7 +39,7 @@ void Wrapper_virtual_elimination_mode_set(int flag) {
extern "C" { extern "C" {
static String *search_decl = 0; /* Declarator being searched */ static String *search_decl = 0; /* Declarator being searched */
static int check_implemented(Node *n) { static Node *check_implemented(Node *n) {
String *decl; String *decl;
if (!n) if (!n)
return 0; return 0;
@ -51,7 +53,7 @@ extern "C" {
if (!GetFlag(n, "abstract")) { if (!GetFlag(n, "abstract")) {
Delete(decl1); Delete(decl1);
Delete(decl2); Delete(decl2);
return 1; return n;
} }
} }
Delete(decl1); Delete(decl1);

View File

@ -105,8 +105,8 @@ static int exportprimitive = 0; // -exportprimitive argument
static String *memberfunction_name = 0; static String *memberfunction_name = 0;
extern "C" { extern "C" {
static int has_classname(Node *class_node) { static Node *has_classname(Node *class_node) {
return Getattr(class_node, "guile:goopsclassname") ? 1 : 0; return Getattr(class_node, "guile:goopsclassname") ? class_node : 0;
} }
} }
@ -732,8 +732,7 @@ public:
if (goops) { if (goops) {
if (i < numreq) { if (i < numreq) {
if (strcmp("void", Char(pt)) != 0) { if (strcmp("void", Char(pt)) != 0) {
Node *class_node = Swig_symbol_clookup_check(pb, Getattr(n, "sym:symtab"), Node *class_node = Swig_symbol_clookup_check(pb, Getattr(n, "sym:symtab"), has_classname);
has_classname);
String *goopsclassname = !class_node ? NULL : Getattr(class_node, "guile:goopsclassname"); String *goopsclassname = !class_node ? NULL : Getattr(class_node, "guile:goopsclassname");
/* do input conversion */ /* do input conversion */
if (goopsclassname) { if (goopsclassname) {

View File

@ -234,11 +234,11 @@ extern "C" {
extern void Swig_symbol_conflict_warn(Node *n, Node *c, const String *symname, int inclass); extern void Swig_symbol_conflict_warn(Node *n, Node *c, const String *symname, int inclass);
extern void Swig_symbol_cadd(const_String_or_char_ptr symname, Node *n); extern void Swig_symbol_cadd(const_String_or_char_ptr symname, Node *n);
extern Node *Swig_symbol_clookup(const_String_or_char_ptr symname, Symtab *tab); extern Node *Swig_symbol_clookup(const_String_or_char_ptr symname, Symtab *tab);
extern Node *Swig_symbol_clookup_check(const_String_or_char_ptr symname, Symtab *tab, int (*check) (Node *)); extern Node *Swig_symbol_clookup_check(const_String_or_char_ptr symname, Symtab *tab, Node *(*checkfunc) (Node *));
extern Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n); extern Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n);
extern Symtab *Swig_symbol_cscope(const_String_or_char_ptr symname, Symtab *tab); extern Symtab *Swig_symbol_cscope(const_String_or_char_ptr symname, Symtab *tab);
extern Node *Swig_symbol_clookup_local(const_String_or_char_ptr symname, Symtab *tab); extern Node *Swig_symbol_clookup_local(const_String_or_char_ptr symname, Symtab *tab);
extern Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr symname, Symtab *tab, int (*check) (Node *)); extern Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr symname, Symtab *tab, Node *(*checkfunc) (Node *));
extern String *Swig_symbol_qualified(Node *n); extern String *Swig_symbol_qualified(Node *n);
extern Node *Swig_symbol_isoverloaded(Node *n); extern Node *Swig_symbol_isoverloaded(Node *n);
extern void Swig_symbol_remove(Node *n); extern void Swig_symbol_remove(Node *n);

View File

@ -495,7 +495,7 @@ void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *s) {
* *
* Inherit symbols from another scope. Primarily for C++ inheritance and * Inherit symbols from another scope. Primarily for C++ inheritance and
* for using directives, such as 'using namespace X;' * for using directives, such as 'using namespace X;'
* but not for using declarations, such as 'using A;'. * but not for using declarations, such as 'using X::A;'.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void Swig_symbol_inherit(Symtab *s) { void Swig_symbol_inherit(Symtab *s) {
@ -1019,12 +1019,12 @@ void Swig_symbol_conflict_warn(Node *n, Node *c, const String *symname, int incl
* *
* This function operates in the C namespace, not the target namespace. * This function operates in the C namespace, not the target namespace.
* *
* The check function is an optional callback that can be used to verify a particular * The checkfunc function is an optional callback that can be used to verify a particular
* symbol match. This is only used in some of the more exotic parts of SWIG. For instance, * symbol match. This is only used in some of the more exotic parts of SWIG. For instance,
* verifying that a class hierarchy implements all pure virtual methods. * verifying that a class hierarchy implements all pure virtual methods.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (Node *n)) { static Node *_symbol_lookup(const String *name, Symtab *symtab, Node *(*checkfunc) (Node *n)) {
Node *n; Node *n;
List *inherit; List *inherit;
Hash *sym = Getattr(symtab, "csymtab"); Hash *sym = Getattr(symtab, "csymtab");
@ -1039,17 +1039,13 @@ static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (No
#endif #endif
if (n) { if (n) {
/* if a check-function is defined. Call it to determine a match */ /* if checkfunc is defined. Call it to determine a match */
if (check) { if (checkfunc) {
int c = check(n); Node *cn = checkfunc(n);
if (c == 1) { if (cn) {
Setmark(symtab, 0); Setmark(symtab, 0);
return n; /* Note that checkfunc can return n != cn, where cn could be a node further down the csym linked list starting at n */
} return cn;
if (c < 0) {
/* Terminate the search right away */
Setmark(symtab, 0);
return 0;
} }
} else { } else {
Setmark(symtab, 0); Setmark(symtab, 0);
@ -1062,7 +1058,7 @@ static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (No
Setmark(symtab, 0); Setmark(symtab, 0);
dname = Swig_symbol_template_deftype(name, symtab); dname = Swig_symbol_template_deftype(name, symtab);
if (!Equal(dname, name)) { if (!Equal(dname, name)) {
n = _symbol_lookup(dname, symtab, check); n = _symbol_lookup(dname, symtab, checkfunc);
} }
Delete(dname); Delete(dname);
if (n) if (n)
@ -1075,7 +1071,7 @@ static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (No
int i, len; int i, len;
len = Len(inherit); len = Len(inherit);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
n = _symbol_lookup(name, Getitem(inherit, i), check); n = _symbol_lookup(name, Getitem(inherit, i), checkfunc);
if (n) { if (n) {
Setmark(symtab, 0); Setmark(symtab, 0);
return n; return n;
@ -1087,13 +1083,13 @@ static Node *_symbol_lookup(const String *name, Symtab *symtab, int (*check) (No
return 0; return 0;
} }
static Node *symbol_lookup(const_String_or_char_ptr name, Symtab *symtab, int (*check) (Node *n)) { static Node *symbol_lookup(const_String_or_char_ptr name, Symtab *symtab, Node *(*checkfunc) (Node *n)) {
Node *n = 0; Node *n = 0;
if (DohCheck(name)) { if (DohCheck(name)) {
n = _symbol_lookup(name, symtab, check); n = _symbol_lookup(name, symtab, checkfunc);
} else { } else {
String *sname = NewString(name); String *sname = NewString(name);
n = _symbol_lookup(sname, symtab, check); n = _symbol_lookup(sname, symtab, checkfunc);
Delete(sname); Delete(sname);
} }
return n; return n;
@ -1105,7 +1101,7 @@ static Node *symbol_lookup(const_String_or_char_ptr name, Symtab *symtab, int (*
* symbol_lookup_qualified() * symbol_lookup_qualified()
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symtab, const String *prefix, int local, int (*checkfunc) (Node *n)) { static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symtab, const String *prefix, int local, Node *(*checkfunc) (Node *n)) {
/* This is a little funky, we search by fully qualified names */ /* This is a little funky, we search by fully qualified names */
if (!symtab) if (!symtab)
@ -1269,7 +1265,7 @@ Node *Swig_symbol_clookup(const_String_or_char_ptr name, Symtab *n) {
* inheritance hierarchy. * inheritance hierarchy.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, int (*checkfunc) (Node *n)) { Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, Node *(*checkfunc) (Node *n)) {
Hash *hsym = 0; Hash *hsym = 0;
Node *s = 0; Node *s = 0;
@ -1321,8 +1317,7 @@ Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, int (*
} }
/* Check if s is a 'using' node */ /* Check if s is a 'using' node */
while (s && Checkattr(s, "nodeType", "using")) { while (s && Checkattr(s, "nodeType", "using")) {
Node *ss; Node *ss = Swig_symbol_clookup(Getattr(s, "uname"), Getattr(s, "sym:symtab"));
ss = Swig_symbol_clookup(Getattr(s, "uname"), Getattr(s, "sym:symtab"));
if (!ss && !checkfunc) { if (!ss && !checkfunc) {
SWIG_WARN_NODE_BEGIN(s); SWIG_WARN_NODE_BEGIN(s);
Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname"))); Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(s, "uname")));
@ -1390,7 +1385,7 @@ Node *Swig_symbol_clookup_local(const_String_or_char_ptr name, Symtab *n) {
* Swig_symbol_clookup_local_check() * Swig_symbol_clookup_local_check()
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n, int (*checkfunc) (Node *)) { Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n, Node *(*checkfunc) (Node *)) {
Hash *hsym; Hash *hsym;
Node *s = 0; Node *s = 0;
@ -1439,7 +1434,8 @@ Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n,
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_symbol_clookup_no_inherit() * Swig_symbol_clookup_no_inherit()
* *
* Symbol lookup like Swig_symbol_clookup but does not follow using declarations. * Symbol lookup like Swig_symbol_clookup but does not follow using directives.
* Using declarations are followed.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n) { Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n) {
@ -1662,12 +1658,12 @@ static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
} }
static int symbol_no_constructor(Node *n) { static Node *symbol_no_constructor(Node *n) {
return !Checkattr(n, "nodeType", "constructor"); return Checkattr(n, "nodeType", "constructor") ? 0 : n;
} }
static int symbol_is_template(Node *n) { static Node *symbol_is_template(Node *n) {
return Checkattr(n, "nodeType", "template"); return Checkattr(n, "nodeType", "template") ? n : 0;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------