diff --git a/CHANGES.current b/CHANGES.current index 71394e26f..ab958c625 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,6 +4,29 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.5 (in progress) =========================== + +2011-09-13: wsfulton + Add warnings for badly named destructors, eg: + + struct KStruct { + ~NOT_KStruct() {} + }; + + cpp_extend_destructors.i:92: Warning 521: Illegal destructor name ~NOT_KStruct. Ignored. + +2011-09-13: wsfulton + Fix %extend and destructors for templates. The destructor in %extend was not always wrapped, + for example: + + %extend FooT { + ~FooT() { delete $self; } // was not wrapped as expected + }; + template class FooT {}; + %template(FooTi) FooT; + +2011-09-13: wsfulton + Fix special variables such as "$decl" and "$fulldecl" in destructors to include the ~ character. + 2011-09-10: talby [perl5] SF bug #1481958 - Improve range checking for integer types. Enhance li_typemaps_runme.pl diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 60552b97a..8d155ec99 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -501,7 +501,7 @@ example.i(4) : Syntax error in input.
  • 501. Overloaded declaration ignored. decl. Previous declaration is decl.
  • 502. Overloaded constructor ignored. decl. Previous declaration is decl.
  • 503. Can't wrap 'identifier' unless renamed to a valid identifier. -
  • 504. Function name must have a return type. +
  • 504. Function name must have a return type. Ignored.
  • 505. Variable length arguments discarded.
  • 506. Can't wrap varargs with keyword arguments enabled.
  • 507. Adding native function name not supported (ignored). @@ -518,6 +518,7 @@ example.i(4) : Syntax error in input.
  • 518. Portability warning: File file1 will be overwritten by file2 on case insensitive filesystems such as Windows' FAT32 and NTFS unless the class/module name is renamed.
  • 519. %template() contains no name. Template method ignored: declaration
  • 520. Base/Derived class 'classname1' of 'classname2' is not similarly marked as a smart pointer. +
  • 521. Illegal destructor name name. Ignored.

    14.9.6 Language module specific (700-899)

    diff --git a/Examples/test-suite/errors/cpp_extend_destructors.i b/Examples/test-suite/errors/cpp_extend_destructors.i new file mode 100644 index 000000000..56b46f9c9 --- /dev/null +++ b/Examples/test-suite/errors/cpp_extend_destructors.i @@ -0,0 +1,104 @@ +%module xxx + +///////////////////////////// +%extend AStruct { + ~AStruct() {} +} +struct AStruct { + ~AStruct() {} +}; + +///////////////////////////// +struct BStruct { + ~BStruct() {} + ~BStruct() {} +}; + +///////////////////////////// +struct CStruct { +}; + +%extend CStruct { + ~NOT_CStruct() { + delete $self; + } +} + +%extend DStruct { + ~NOT_DStruct() { + delete $self; + } +} + +struct DStruct { +}; + +///////////////////////////// +struct EStruct { + ~EStruct() {} +}; + +%extend EStruct { + ~NOT_EStruct() { + delete $self; + } +} + +%extend FStruct { + ~NOT_FStruct() { + delete $self; + } +} + +struct FStruct { + ~FStruct() {} +}; + +///////////////////////////// +struct GStruct { +}; + +%extend GStruct { + ~GStruct() {} + ~NOT_GStruct() { + delete $self; + } +} + +%extend HStruct { + ~HStruct() {} + ~NOT_HStruct() { + delete $self; + } +} + +struct HStruct { +}; + +///////////////////////////// +struct IStruct { + ~IStruct() {} + ~NOT_IStruct() {} +}; + +struct JStruct { + ~JStruct() {} + ~NOT_JStruct() {} + ~JStruct() {} +}; + +///////////////////////////// +struct KStruct { + ~NOT_KStruct() {} +}; + +///////////////////////////// +template +struct LStruct { + ~LStruct() {} + ~NOT_LStruct() {} + ~LStruct() {} +}; +%template(LStructInt) LStruct; +%template(LStructShort) LStruct; + diff --git a/Examples/test-suite/errors/expected.log b/Examples/test-suite/errors/expected.log index 9e4052bea..2779469ca 100644 --- a/Examples/test-suite/errors/expected.log +++ b/Examples/test-suite/errors/expected.log @@ -209,6 +209,27 @@ Doc/Manual/Typemaps.html for complete details. cpp_bad_extern.i:5: Warning 313: Unrecognized extern type "INTERCAL". cpp_bad_extern.i:7: Warning 313: Unrecognized extern type "INTERCAL". +:::::::::::::::::::::::::::::::: cpp_extend_destructors.i ::::::::::::::::::::::::::::::::::: +cpp_extend_destructors.i:8: Warning 302: Identifier '~AStruct' redefined by %extend (ignored), +cpp_extend_destructors.i:5: Warning 302: %extend definition of '~AStruct'. +cpp_extend_destructors.i:14: Warning 302: Identifier '~BStruct' redefined (ignored), +cpp_extend_destructors.i:13: Warning 302: previous definition of '~BStruct'. +cpp_extend_destructors.i:87: Warning 302: Identifier '~JStruct' redefined (ignored), +cpp_extend_destructors.i:85: Warning 302: previous definition of '~JStruct'. +cpp_extend_destructors.i:100: Warning 302: Identifier '~LStruct' redefined (ignored), +cpp_extend_destructors.i:98: Warning 302: previous definition of '~LStruct'. +cpp_extend_destructors.i:24: Warning 521: Illegal destructor name ~NOT_CStruct. Ignored. +cpp_extend_destructors.i:30: Warning 521: Illegal destructor name ~NOT_DStruct. Ignored. +cpp_extend_destructors.i:44: Warning 521: Illegal destructor name ~NOT_EStruct. Ignored. +cpp_extend_destructors.i:50: Warning 521: Illegal destructor name ~NOT_FStruct. Ignored. +cpp_extend_destructors.i:65: Warning 521: Illegal destructor name ~NOT_GStruct. Ignored. +cpp_extend_destructors.i:72: Warning 521: Illegal destructor name ~NOT_HStruct. Ignored. +cpp_extend_destructors.i:81: Warning 521: Illegal destructor name ~NOT_IStruct. Ignored. +cpp_extend_destructors.i:86: Warning 521: Illegal destructor name ~NOT_JStruct. Ignored. +cpp_extend_destructors.i:92: Warning 521: Illegal destructor name ~NOT_KStruct. Ignored. +cpp_extend_destructors.i:99: Warning 521: Illegal destructor name ~NOT_LStruct< int >. Ignored. +cpp_extend_destructors.i:99: Warning 521: Illegal destructor name ~NOT_LStruct< short >. Ignored. + :::::::::::::::::::::::::::::::: cpp_extend_redefine.i ::::::::::::::::::::::::::::::::::: cpp_extend_redefine.i:9: Warning 302: Identifier 'bar' redefined by %extend (ignored), cpp_extend_redefine.i:5: Warning 302: %extend definition of 'bar'. diff --git a/Examples/test-suite/errors/make.sh b/Examples/test-suite/errors/make.sh index 009b581c1..44d58a344 100755 --- a/Examples/test-suite/errors/make.sh +++ b/Examples/test-suite/errors/make.sh @@ -63,6 +63,7 @@ swig_typemap_old # Files run in C++ mode CPPFILES=' cpp_bad_extern +cpp_extend_destructors cpp_extend_redefine cpp_extend_undefined cpp_inline_namespace diff --git a/Examples/test-suite/extend_constructor_destructor.i b/Examples/test-suite/extend_constructor_destructor.i index dbb47245d..08a9dc2bf 100644 --- a/Examples/test-suite/extend_constructor_destructor.i +++ b/Examples/test-suite/extend_constructor_destructor.i @@ -20,20 +20,21 @@ namespace Space { typedef struct { int ivar; } DStruct; + } typedef struct tagEStruct { int ivar; } EStruct; +namespace Space { + template + struct FFStruct { + int ivar; + }; +} %} -%extend Junk { -void thingy() {} -} -%inline %{ -struct Junk {}; -%} namespace Space { %extend tagAStruct { @@ -103,3 +104,22 @@ namespace Space { } } +namespace Space { +%extend FFStruct { + FFStruct(int ivar0) { + Space::FFStruct *s = new Space::FFStruct(); + s->ivar = ivar0; + global = ivar0; + return s; + } + ~FFStruct() { + global = -$self->ivar; + delete $self; + } +} + +} + +%template(FStruct) Space::FFStruct; +%template(GStruct) Space::FFStruct; + diff --git a/Examples/test-suite/java/extend_constructor_destructor_runme.java b/Examples/test-suite/java/extend_constructor_destructor_runme.java index 270bc17e1..de1515839 100644 --- a/Examples/test-suite/java/extend_constructor_destructor_runme.java +++ b/Examples/test-suite/java/extend_constructor_destructor_runme.java @@ -20,6 +20,12 @@ public class extend_constructor_destructor_runme { checkGlobal(30); DStruct d = new DStruct(40); checkGlobal(40); + EStruct e = new EStruct(50); + checkGlobal(50); + FStruct f = new FStruct(60); + checkGlobal(60); + GStruct g = new GStruct(70); + checkGlobal(70); a.delete(); checkGlobal(-10); @@ -29,6 +35,12 @@ public class extend_constructor_destructor_runme { checkGlobal(-30); d.delete(); checkGlobal(-40); + e.delete(); + checkGlobal(-50); + f.delete(); + checkGlobal(-60); + g.delete(); + checkGlobal(-70); } public static void checkGlobal(int val) { diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 9f1df25d2..1aae86fdd 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -195,6 +195,7 @@ #define WARN_LANG_PORTABILITY_FILENAME 518 #define WARN_LANG_TEMPLATE_METHOD_IGNORE 519 #define WARN_LANG_SMARTPTR_MISSING 520 +#define WARN_LANG_ILLEGAL_DESTRUCTOR 521 /* -- Reserved (600-799) -- */ diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index 563680a10..81a732638 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -936,6 +936,9 @@ Allocate(): } else if (cplus_mode == PROTECTED) { Setattr(inclass, "allocate:default_base_destructor", "1"); } + } else { + Setattr(inclass, "allocate:has_destructor", "1"); + Setattr(inclass, "allocate:default_destructor", "1"); } return SWIG_OK; } diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 44a9d2edc..0fc214694 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -2609,17 +2609,18 @@ int Language::constructorDeclaration(Node *n) { } } } else { - if (name && (!Equal(Swig_scopename_last(name), Swig_scopename_last(ClassName))) && !(Getattr(n, "template"))) { - bool illegal_method = true; + String *expected_name = ClassName; + if (name && (!Equal(Swig_scopename_last(name), Swig_scopename_last(expected_name))) && !(Getattr(n, "template"))) { + bool illegal_name = true; if (Extend) { // SWIG extension - allow typedef names as constructor name in %extend - an unnamed struct declared with a typedef can thus be given a 'constructor'. SwigType *name_resolved = SwigType_typedef_resolve_all(name); - SwigType *classname_resolved = SwigType_typedef_resolve_all(ClassName); - illegal_method = !Equal(name_resolved, classname_resolved); + SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name); + illegal_name = !Equal(name_resolved, expected_name_resolved); Delete(name_resolved); - Delete(classname_resolved); + Delete(expected_name_resolved); } - if (illegal_method) { + if (illegal_name) { Swig_warning(WARN_LANG_RETURN_TYPE, input_file, line_number, "Function %s must have a return type. Ignored.\n", SwigType_namestr(name)); Swig_restore(n); return SWIG_NOWRAP; @@ -2727,24 +2728,12 @@ int Language::destructorDeclaration(Node *n) { if (ImportMode) return SWIG_NOWRAP; - if (Extend) { - /* extend destructor can be safely ignored if there is already one */ - if (Getattr(CurrentClass, "has_destructor")) { - return SWIG_NOWRAP; - } - } - Swig_save("destructorDeclaration", n, "name", "sym:name", NIL); - char *c = GetChar(n, "name"); - if (c && (*c == '~')) - Setattr(n, "name", c + 1); - - c = GetChar(n, "sym:name"); - if (c && (*c == '~')) + char *c = GetChar(n, "sym:name"); + if (c && (*c == '~')) { Setattr(n, "sym:name", c + 1); - - /* Name adjustment for %name */ + } String *name = Getattr(n, "name"); String *symname = Getattr(n, "sym:name"); @@ -2753,10 +2742,33 @@ int Language::destructorDeclaration(Node *n) { Setattr(n, "sym:name", ClassPrefix); } + String *expected_name = NewString(ClassName); + Replace(expected_name, "~", "", DOH_REPLACE_FIRST); + String *actual_name = NewString(name); + Replace(actual_name, "~", "", DOH_REPLACE_FIRST); + if (name && (!Equal(Swig_scopename_last(actual_name), Swig_scopename_last(expected_name))) && !(Getattr(n, "template"))) { + bool illegal_name = true; + if (Extend) { + // SWIG extension - allow typedef names as destructor name in %extend - an unnamed struct declared with a typedef can thus be given a 'destructor'. + SwigType *name_resolved = SwigType_typedef_resolve_all(actual_name); + SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name); + illegal_name = !Equal(name_resolved, expected_name_resolved); + Delete(name_resolved); + Delete(expected_name_resolved); + } + + if (illegal_name) { + Swig_warning(WARN_LANG_ILLEGAL_DESTRUCTOR, input_file, line_number, "Illegal destructor name %s. Ignored.\n", SwigType_namestr(name)); + Swig_restore(n); + Delete(expected_name); + return SWIG_NOWRAP; + } + } destructorHandler(n); Setattr(CurrentClass, "has_destructor", "1"); Swig_restore(n); + Delete(expected_name); return SWIG_OK; }