diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 99fea03ed..1316876f8 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -393,6 +393,7 @@ CPP_TEST_CASES += \ template_default \ template_default2 \ template_default_arg \ + template_default_arg_overloaded \ template_default_arg_virtual_destructor \ template_default_class_parms \ template_default_class_parms_typedef \ diff --git a/Examples/test-suite/python/template_default_arg_overloaded_runme.py b/Examples/test-suite/python/template_default_arg_overloaded_runme.py new file mode 100644 index 000000000..22d46b39d --- /dev/null +++ b/Examples/test-suite/python/template_default_arg_overloaded_runme.py @@ -0,0 +1,47 @@ +from template_default_arg_overloaded import * + +def check(expected, got): + if expected != got: + raise RuntimeError("Expected: " + str(expected) + " got: " + str(got)) + + +pl = PropertyList() +check(1, pl.setInt("int", 10)) +check(1, pl.setInt("int", 10, False)) + +check(2, pl.set("int", pl)) +check(2, pl.set("int", pl, False)) + +check(3, pl.setInt("int", 10, "int")) +check(3, pl.setInt("int", 10, "int", False)) + + +pl = PropertyListGlobal() +check(1, pl.setIntGlobal("int", 10)) +check(1, pl.setIntGlobal("int", 10, False)) + +check(2, pl.set("int", pl)) +check(2, pl.set("int", pl, False)) + +check(3, pl.setIntGlobal("int", 10, "int")) +check(3, pl.setIntGlobal("int", 10, "int", False)) + + +check(1, GoopIntGlobal(10)) +check(1, GoopIntGlobal(10, True)) + +check(2, goopGlobal(3)) +check(2, goopGlobal()) + +check(3, GoopIntGlobal("int", False)) +check(3, GoopIntGlobal("int")) + + +check(1, GoopInt(10)) +check(1, GoopInt(10, True)) + +check(2, goop(3)) +check(2, goop()) + +check(3, GoopInt("int", False)) +check(3, GoopInt("int")) diff --git a/Examples/test-suite/template_default_arg_overloaded.i b/Examples/test-suite/template_default_arg_overloaded.i new file mode 100644 index 000000000..ef8320692 --- /dev/null +++ b/Examples/test-suite/template_default_arg_overloaded.i @@ -0,0 +1,67 @@ +%module template_default_arg_overloaded + +// Github issue #529 + +%include + +%inline %{ +#include + +namespace lsst { +namespace daf { +namespace bass { + +class PropertyList { +public: + PropertyList(void) {}; + + virtual ~PropertyList(void) {}; + + template int set(std::string const& name1, T const& value1, bool inPlace1=true) { return 1; } + + int set(std::string const& name2, PropertyList const& value2, bool inPlace2=true) { return 2; } + + template int set(std::string const& name3, T const& value3, std::string const& comment3, bool inPlace3=true) { return 3; } +}; + +}}} // namespace lsst::daf::bass + +// As above but in global namespace +class PropertyListGlobal { +public: + PropertyListGlobal(void) {}; + + virtual ~PropertyListGlobal(void) {}; + + template int set(std::string const& name1, T const& value1, bool inPlace1=true) { return 1; } + + int set(std::string const& name2, PropertyListGlobal const& value2, bool inPlace2=true) { return 2; } + + template int set(std::string const& name3, T const& value3, std::string const& comment3, bool inPlace3=true) { return 3; } +}; + +%} + +%template(setInt) lsst::daf::bass::PropertyList::set; +%template(setIntGlobal) PropertyListGlobal::set; + + +// Global functions +%inline %{ +template int goopGlobal(T i1, bool b1 = true) { return 1; } +int goopGlobal(short s2 = 0) { return 2; } +template int goopGlobal(const char *s3, bool b3 = true) { return 3; } +%} + +// Global functions in a namespace +%inline %{ +namespace lsst { +template int goop(T i1, bool b1 = true) { return 1; } +int goop(short s2 = 0) { return 2; } +template int goop(const char *s3, bool b3 = true) { return 3; } +} +%} + +%template(GoopIntGlobal) goopGlobal; +%template(GoopInt) lsst::goop; + diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index d0f1c8250..621d43421 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -142,6 +142,11 @@ static Node *copy_node(Node *n) { Setattr(nn, key, k.item); continue; } + /* defaultargs will be patched back in later */ + if (strcmp(ckey,"defaultargs") == 0) { + Setattr(nn, "needs_defaultargs", "1"); + continue; + } /* Looks okay. Just copy the data using Copy */ ci = Copy(k.item); Setattr(nn, key, ci); @@ -652,6 +657,25 @@ static void add_symbols_copy(Node *n) { } } +static void update_defaultargs(Node *n) { + if (n) { + Node *firstdefaultargs = n; + update_defaultargs(firstChild(n)); + n = nextSibling(n); + while (n) { + update_defaultargs(firstChild(n)); + assert(!Getattr(n, "defaultargs")); + if (Getattr(n, "needs_defaultargs")) { + Setattr(n, "defaultargs", firstdefaultargs); + Delattr(n, "needs_defaultargs"); + } else { + firstdefaultargs = n; + } + n = nextSibling(n); + } + } +} + /* Check a set of declarations to see if any are pure-abstract */ static List *pure_abstracts(Node *n) { @@ -2573,6 +2597,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va { Node *nn = n; Node *linklistend = 0; + Node *linkliststart = 0; while (nn) { Node *templnode = 0; if (Strcmp(nodeType(nn),"template") == 0) { @@ -2654,7 +2679,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va } templnode = copy_node(nn); - update_nested_classes(templnode); /* update classes nested withing template */ + update_nested_classes(templnode); /* update classes nested within template */ /* We need to set the node name based on name used to instantiate */ Setattr(templnode,"name",tname); Delete(tname); @@ -2771,6 +2796,8 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va } /* all the overloaded templated functions are added into a linked list */ + if (!linkliststart) + linkliststart = templnode; if (nscope_inner) { /* non-global namespace */ if (templnode) { @@ -2791,6 +2818,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va } nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions. If a templated class there will never be a sibling. */ } + update_defaultargs(linkliststart); } Swig_symbol_setscope(tscope); Delete(Namespaceprefix);