From c3d652c785328e67d14141266e4ae6198124cc95 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Fri, 22 Feb 2019 06:28:53 -0700 Subject: [PATCH 1/6] Fix the handling of director classes with final methods Generated SwigDirector_* classes were attempting to override methods marked as final. In addition, give a warning if the destructor of a director class is final. Closes #564. --- CHANGES.current | 3 ++ Doc/Manual/Warnings.html | 1 + Examples/test-suite/cpp11_final_directors.i | 18 +++++++ .../python/cpp11_final_directors_runme.py | 11 ++++ Source/CParse/parser.y | 51 ++++++++++++++++--- Source/Include/swigwarn.h | 1 + Source/Modules/lang.cxx | 9 +++- 7 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 Examples/test-suite/cpp11_final_directors.i create mode 100644 Examples/test-suite/python/cpp11_final_directors_runme.py diff --git a/CHANGES.current b/CHANGES.current index 492dffa6a..5bf15a778 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2019-02-22: ZackerySpytz + #1483 Fix compilation failures when a director class has final methods. + 2019-02-21: wsfulton #1240 Suppress Java 9 deprecation warnings on finalize method. diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index bff20801e..8b2ab2b95 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -535,6 +535,7 @@ example.i(4) : Syntax error in input(1).
  • 522. Use of an illegal constructor name 'name' in %extend is deprecated, the constructor name should be 'name'.
  • 523. Use of an illegal destructor name 'name' in %extend is deprecated, the destructor name should be 'name'.
  • 524. Experimental target language. Target language language specified by lang is an experimental language. Please read about SWIG experimental languages, htmllink. +
  • 525. The director base class 'name' or the destructor of director base class 'name' is marked as final.

    18.9.6 Doxygen comments (560-599)

    diff --git a/Examples/test-suite/cpp11_final_directors.i b/Examples/test-suite/cpp11_final_directors.i new file mode 100644 index 000000000..d724543ea --- /dev/null +++ b/Examples/test-suite/cpp11_final_directors.i @@ -0,0 +1,18 @@ +%module(directors="1") cpp11_final_directors + +%warnfilter(SWIGWARN_PARSE_KEYWORD) final; + +%director Derived; + +%inline %{ +struct Base { + virtual void basemeth() final {} + virtual ~Base() {} +}; + +struct Derived : Base { + virtual int derivedmeth() final { return 1; } + virtual int meth() { return 2; } + virtual ~Derived() {} +}; +%} diff --git a/Examples/test-suite/python/cpp11_final_directors_runme.py b/Examples/test-suite/python/cpp11_final_directors_runme.py new file mode 100644 index 000000000..2e5f8af96 --- /dev/null +++ b/Examples/test-suite/python/cpp11_final_directors_runme.py @@ -0,0 +1,11 @@ +import cpp11_final_directors + +class Derived2(cpp11_final_directors.Derived): + + def meth(self): + return 3 + + +b = Derived2() +if b.meth() != 3: + raise RuntimeError diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index f20f1db2f..4046e480e 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1552,6 +1552,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) Parm *throws; String *throwf; String *nexcept; + String *final; } dtype; struct { const char *type; @@ -1567,6 +1568,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) ParmList *throws; String *throwf; String *nexcept; + String *final; } decl; Parm *tparms; struct { @@ -3189,6 +3191,7 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail { Setattr($$,"throws",$4.throws); Setattr($$,"throw",$4.throwf); Setattr($$,"noexcept",$4.nexcept); + Setattr($$,"final",$4.final); if ($5.val && $5.type) { /* store initializer type as it might be different to the declared type */ SwigType *valuetype = NewSwigType($5.type); @@ -3266,6 +3269,7 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail { Setattr($$,"throws",$4.throws); Setattr($$,"throw",$4.throwf); Setattr($$,"noexcept",$4.nexcept); + Setattr($$,"final",$4.final); if (!$9) { if (Len(scanner_ccode)) { String *code = Copy(scanner_ccode); @@ -3330,6 +3334,7 @@ c_decl_tail : SEMI { Setattr($$,"throws",$3.throws); Setattr($$,"throw",$3.throwf); Setattr($$,"noexcept",$3.nexcept); + Setattr($$,"final",$3.final); if ($4.bitfield) { Setattr($$,"bitfield", $4.bitfield); } @@ -3638,6 +3643,7 @@ c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { Setattr($$,"throws",$6.throws); Setattr($$,"throw",$6.throwf); Setattr($$,"noexcept",$6.nexcept); + Setattr($$,"final",$6.final); err = 0; } } @@ -4704,6 +4710,7 @@ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { Setattr($$,"throws",$6.throws); Setattr($$,"throw",$6.throwf); Setattr($$,"noexcept",$6.nexcept); + Setattr($$,"final",$6.final); if (Len(scanner_ccode)) { String *code = Copy(scanner_ccode); Setattr($$,"code",code); @@ -4740,6 +4747,7 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end { Setattr($$,"throws",$6.throws); Setattr($$,"throw",$6.throwf); Setattr($$,"noexcept",$6.nexcept); + Setattr($$,"final",$6.final); if ($6.val) Setattr($$,"value",$6.val); if ($6.qualifier) @@ -4760,6 +4768,7 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end { Setattr($$,"throws",$7.throws); Setattr($$,"throw",$7.throwf); Setattr($$,"noexcept",$7.nexcept); + Setattr($$,"final",$7.final); if ($7.val) Setattr($$,"value",$7.val); if (Len(scanner_ccode)) { @@ -4941,6 +4950,7 @@ cpp_end : cpp_const SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const EQUAL default_delete SEMI { Clear(scanner_ccode); @@ -4951,6 +4961,7 @@ cpp_end : cpp_const SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const LBRACE { skip_balanced('{','}'); @@ -4961,6 +4972,7 @@ cpp_end : cpp_const SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } ; @@ -4973,6 +4985,7 @@ cpp_vend : cpp_const SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const EQUAL definetype SEMI { Clear(scanner_ccode); @@ -4982,7 +4995,8 @@ cpp_vend : cpp_const SEMI { $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; - $$.nexcept = $1.nexcept; + $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const LBRACE { skip_balanced('{','}'); @@ -4992,7 +5006,8 @@ cpp_vend : cpp_const SEMI { $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; - $$.nexcept = $1.nexcept; + $$.nexcept = $1.nexcept; + $$.final = $1.final; } ; @@ -5210,6 +5225,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } } | EQUAL definetype LBRACKET expr RBRACKET { @@ -5223,6 +5239,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } else { $$.val = NewStringf("%s[%s]",$2.val,$4.val); } @@ -5236,6 +5253,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | COLON expr { $$.val = 0; @@ -5245,6 +5263,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | empty { $$.val = 0; @@ -5254,6 +5273,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } ; @@ -6293,6 +6313,7 @@ definetype : { /* scanner_check_typedef(); */ } expr { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; scanner_ignore_typedef(); } | default_delete { @@ -6319,6 +6340,7 @@ deleted_definition : DELETE_KW { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } ; @@ -6333,6 +6355,7 @@ explicit_default : DEFAULT { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } ; @@ -6525,6 +6548,7 @@ valexpr : exprnum { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | WCHARCONST { $$.val = NewString($1); @@ -6538,6 +6562,7 @@ valexpr : exprnum { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } /* grouping */ @@ -6892,18 +6917,18 @@ virt_specifier_seq : OVERRIDE { $$ = 0; } | FINAL { - $$ = 0; + $$ = NewString("1"); } | FINAL OVERRIDE { - $$ = 0; + $$ = NewString("1"); } | OVERRIDE FINAL { - $$ = 0; + $$ = NewString("1"); } ; virt_specifier_seq_opt : virt_specifier_seq { - $$ = 0; + $$ = $1; } | empty { $$ = 0; @@ -6914,31 +6939,37 @@ exception_specification : THROW LPAREN parms RPAREN { $$.throws = $3; $$.throwf = NewString("1"); $$.nexcept = 0; + $$.final = 0; } | NOEXCEPT { $$.throws = 0; $$.throwf = 0; $$.nexcept = NewString("true"); + $$.final = 0; } | virt_specifier_seq { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = $1; } | THROW LPAREN parms RPAREN virt_specifier_seq { $$.throws = $3; $$.throwf = NewString("1"); $$.nexcept = 0; + $$.final = $5; } | NOEXCEPT virt_specifier_seq { $$.throws = 0; $$.throwf = 0; $$.nexcept = NewString("true"); + $$.final = $2; } | NOEXCEPT LPAREN expr RPAREN { $$.throws = 0; $$.throwf = 0; $$.nexcept = $3.val; + $$.final = 0; } ; @@ -6946,6 +6977,7 @@ qualifiers_exception_specification : cv_ref_qualifier { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; $$.qualifier = $1.qualifier; $$.refqualifier = $1.refqualifier; } @@ -6968,6 +7000,7 @@ cpp_const : qualifiers_exception_specification { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; $$.qualifier = 0; $$.refqualifier = 0; } @@ -6980,6 +7013,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; if ($1.qualifier) Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); } @@ -6990,6 +7024,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; if ($1.qualifier) Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); } @@ -7001,6 +7036,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | LPAREN parms RPAREN LBRACE { skip_balanced('{','}'); @@ -7010,6 +7046,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | EQUAL definetype SEMI { $$.have_parms = 0; @@ -7017,6 +7054,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | exception_specification EQUAL default_delete SEMI { $$.have_parms = 0; @@ -7024,6 +7062,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; if ($1.qualifier) Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); } diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index fde82bd96..fbcea4dbd 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -211,6 +211,7 @@ #define WARN_LANG_EXTEND_CONSTRUCTOR 522 #define WARN_LANG_EXTEND_DESTRUCTOR 523 #define WARN_LANG_EXPERIMENTAL 524 +#define WARN_LANG_DIRECTOR_FINAL 525 /* -- Doxygen comments -- */ diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index f9af9723a..acb5e4348 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -2109,7 +2109,7 @@ int Language::classDirectorMethods(Node *n) { Node *item = Getitem(vtable, i); String *method = Getattr(item, "methodNode"); String *fqdname = Getattr(item, "fqdname"); - if (GetFlag(method, "feature:nodirector")) + if (GetFlag(method, "feature:nodirector") || GetFlag(method, "final")) continue; String *wrn = Getattr(method, "feature:warnfilter"); @@ -2198,6 +2198,13 @@ int Language::classDirector(Node *n) { String *using_protected_members_code = NewString(""); for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { Node *nodeType = Getattr(ni, "nodeType"); + if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) { + String *classtype = Getattr(n, "classtype"); + Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor of director base class %s is marked as final.\n", classtype); + Delete(vtable); + Delete(using_protected_members_code); + return SWIG_OK; + } bool cdeclaration = (Cmp(nodeType, "cdecl") == 0); if (cdeclaration && !GetFlag(ni, "feature:ignore")) { if (isNonVirtualProtectedAccess(ni)) { From e8cc5929de91226f23ae3d4e31d35e6c53472e6a Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Sun, 24 Feb 2019 08:04:45 -0700 Subject: [PATCH 2/6] Remove a useless warning filter Add cpp11_final_directors to Examples/test-suite/common.mk. --- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_final_directors.i | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 3d4edd47b..7b4836a17 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -571,6 +571,7 @@ CPP11_TEST_CASES += \ cpp11_director_enums \ cpp11_directors \ cpp11_explicit_conversion_operators \ + cpp11_final_directors \ cpp11_final_override \ cpp11_function_objects \ cpp11_inheriting_constructors \ diff --git a/Examples/test-suite/cpp11_final_directors.i b/Examples/test-suite/cpp11_final_directors.i index d724543ea..2b001bd7b 100644 --- a/Examples/test-suite/cpp11_final_directors.i +++ b/Examples/test-suite/cpp11_final_directors.i @@ -1,7 +1,5 @@ %module(directors="1") cpp11_final_directors -%warnfilter(SWIGWARN_PARSE_KEYWORD) final; - %director Derived; %inline %{ From b9c4a84780157ab1812a4ba6cdb72020430f8385 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 2 Mar 2019 19:02:35 +0000 Subject: [PATCH 3/6] Warning fix for final destructor in directors Fix suppression of final destructors used in director classes. Add testcase for final destructors in director classes. --- Examples/test-suite/cpp11_final_directors.i | 8 ++++++++ Examples/test-suite/errors/cpp_final_destructor.stderr | 1 + Source/Modules/lang.cxx | 2 ++ 3 files changed, 11 insertions(+) create mode 100644 Examples/test-suite/errors/cpp_final_destructor.stderr diff --git a/Examples/test-suite/cpp11_final_directors.i b/Examples/test-suite/cpp11_final_directors.i index 2b001bd7b..ccd5d1b20 100644 --- a/Examples/test-suite/cpp11_final_directors.i +++ b/Examples/test-suite/cpp11_final_directors.i @@ -1,6 +1,9 @@ %module(directors="1") cpp11_final_directors %director Derived; +%director BaseFinalDestructor; + +%warnfilter(SWIGWARN_LANG_DIRECTOR_FINAL) BaseFinalDestructor::~BaseFinalDestructor; %inline %{ struct Base { @@ -13,4 +16,9 @@ struct Derived : Base { virtual int meth() { return 2; } virtual ~Derived() {} }; + +struct BaseFinalDestructor { + virtual void basefinalmeth() final {} + virtual ~BaseFinalDestructor() final {} +}; %} diff --git a/Examples/test-suite/errors/cpp_final_destructor.stderr b/Examples/test-suite/errors/cpp_final_destructor.stderr new file mode 100644 index 000000000..924396341 --- /dev/null +++ b/Examples/test-suite/errors/cpp_final_destructor.stderr @@ -0,0 +1 @@ +cpp_final_destructor.i:7: Warning 525: Destructor of director base class BaseFinal is marked as final. diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index acb5e4348..d79e07f36 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -2200,7 +2200,9 @@ int Language::classDirector(Node *n) { Node *nodeType = Getattr(ni, "nodeType"); if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) { String *classtype = Getattr(n, "classtype"); + SWIG_WARN_NODE_BEGIN(ni); Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor of director base class %s is marked as final.\n", classtype); + SWIG_WARN_NODE_END(ni); Delete(vtable); Delete(using_protected_members_code); return SWIG_OK; From 3b07cba74066ef3a95b1e66a8c7d869a9510d1b9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 2 Mar 2019 19:57:33 +0000 Subject: [PATCH 4/6] Fixes for final destructors in director classes A class marked as a director with a final destructor should not be a wrapped as a director class. Fix seg faults in this case. --- Examples/test-suite/cpp11_final_directors.i | 9 +++++++++ Source/Modules/lang.cxx | 3 +++ 2 files changed, 12 insertions(+) diff --git a/Examples/test-suite/cpp11_final_directors.i b/Examples/test-suite/cpp11_final_directors.i index ccd5d1b20..b58111adb 100644 --- a/Examples/test-suite/cpp11_final_directors.i +++ b/Examples/test-suite/cpp11_final_directors.i @@ -1,9 +1,13 @@ %module(directors="1") cpp11_final_directors %director Derived; + +// Check SWIG will not wrap these classes as directors where the destructors are final %director BaseFinalDestructor; +%director BaseFinalDestructor2; %warnfilter(SWIGWARN_LANG_DIRECTOR_FINAL) BaseFinalDestructor::~BaseFinalDestructor; +%warnfilter(SWIGWARN_LANG_DIRECTOR_FINAL) BaseFinalDestructor2::~BaseFinalDestructor2; %inline %{ struct Base { @@ -21,4 +25,9 @@ struct BaseFinalDestructor { virtual void basefinalmeth() final {} virtual ~BaseFinalDestructor() final {} }; + +struct BaseFinalDestructor2 { + virtual void basefinalmeth() {} + virtual ~BaseFinalDestructor2() final {} +}; %} diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index d79e07f36..272936e4e 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1894,6 +1894,8 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_ } if (!checkAttribute(nn, "storage", "virtual")) continue; + if (GetFlag(nn, "final")) + continue; /* we need to add methods(cdecl) and destructor (to check for throw decl) */ int is_destructor = (Cmp(nodeType, "destructor") == 0); if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) { @@ -2203,6 +2205,7 @@ int Language::classDirector(Node *n) { SWIG_WARN_NODE_BEGIN(ni); Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor of director base class %s is marked as final.\n", classtype); SWIG_WARN_NODE_END(ni); + SetFlag(n, "feature:nodirector"); Delete(vtable); Delete(using_protected_members_code); return SWIG_OK; From 34108deec7e89d9f7c70b337702cfffb1e34c006 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 3 Mar 2019 14:26:43 +0000 Subject: [PATCH 5/6] Documentation for directors and virtual final methods --- Doc/Manual/Go.html | 4 +++- Doc/Manual/Java.html | 7 ++++--- Doc/Manual/Perl5.html | 7 ++++--- Doc/Manual/Php.html | 7 ++++--- Doc/Manual/Python.html | 7 ++++--- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 4a60e45e0..047b46edf 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -785,7 +785,9 @@ In order to override virtual methods on a C++ class with Go methods the NewDirectorClassName constructor functions receives a DirectorInterface argument. The methods in the DirectorInterface are a subset of the public and protected virtual methods -of the C++ class. If the DirectorInterface contains a method with a +of the C++ class. +Virtual methods that have a final specifier are unsurprisingly excluded. +If the DirectorInterface contains a method with a matching signature to a virtual method of the C++ class then the virtual C++ method will be overwritten with the Go method. As Go doesn't support protected methods all overridden protected virtual C++ methods will be public in Go. diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index bf77c1562..3a04b8a79 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -3629,7 +3629,7 @@ The %feature directive can be applied globally, to specific classes, and to spec // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -3647,7 +3647,7 @@ So for example,

    -will generate directors for all virtual methods of class Foo except bar(). +will generate directors for the virtual methods of class Foo except bar().

    @@ -3683,7 +3683,8 @@ The director classes store a pointer to their underlying Java proxy classes.

    For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in Java via proxy classes, eventually end up in at the implementation in the director class. +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in Java via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By "appropriate place" we mean the method that would have been called if the C++ base class and its Java derived classes were seamlessly integrated. That seamless integration is exactly what the director classes provide, transparently skipping over all the messy JNI glue code that binds the two languages together. diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 5ce765c26..766ccaede 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -3070,7 +3070,7 @@ globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -3088,7 +3088,7 @@ directors for specific classes or methods. So for example,

    -will generate directors for all virtual methods of class Foo except +will generate directors for the virtual methods of class Foo except bar().

    @@ -3153,7 +3153,8 @@ For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in Perl via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 85732fd33..1b8b2d468 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -937,7 +937,7 @@ globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -955,7 +955,7 @@ directors for specific classes or methods. So for example,

    -will generate directors for all virtual methods of class Foo except +will generate directors for the virtual methods of class Foo except bar().

    @@ -1020,7 +1020,8 @@ For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in PHP via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By "appropriate diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 6a174fddf..2554e9da3 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -2934,7 +2934,7 @@ globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -2952,7 +2952,7 @@ directors for specific classes or methods. So for example,

    -will generate directors for all virtual methods of class Foo except +will generate directors for the virtual methods of class Foo except bar().

    @@ -3018,7 +3018,8 @@ For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in Python via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By From 39b44a377a785ac45d7de5cdf725fb10caef48d1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 3 Mar 2019 15:12:29 +0000 Subject: [PATCH 6/6] Warning tweaks for destructors that are final in director classes --- Doc/Manual/Warnings.html | 2 +- Examples/test-suite/errors/cpp_final_destructor.stderr | 2 +- Source/Modules/lang.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 8b2ab2b95..c63d7de0c 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -535,7 +535,7 @@ example.i(4) : Syntax error in input(1).
  • 522. Use of an illegal constructor name 'name' in %extend is deprecated, the constructor name should be 'name'.
  • 523. Use of an illegal destructor name 'name' in %extend is deprecated, the destructor name should be 'name'.
  • 524. Experimental target language. Target language language specified by lang is an experimental language. Please read about SWIG experimental languages, htmllink. -
  • 525. The director base class 'name' or the destructor of director base class 'name' is marked as final. +
  • 525. Destructor declaration is final, name cannot be a director class.

    18.9.6 Doxygen comments (560-599)

    diff --git a/Examples/test-suite/errors/cpp_final_destructor.stderr b/Examples/test-suite/errors/cpp_final_destructor.stderr index 924396341..d8c509d0c 100644 --- a/Examples/test-suite/errors/cpp_final_destructor.stderr +++ b/Examples/test-suite/errors/cpp_final_destructor.stderr @@ -1 +1 @@ -cpp_final_destructor.i:7: Warning 525: Destructor of director base class BaseFinal is marked as final. +cpp_final_destructor.i:7: Warning 525: Destructor BaseFinal::~BaseFinal() is final, BaseFinal cannot be a director class. diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 272936e4e..f7979b611 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -2203,7 +2203,7 @@ int Language::classDirector(Node *n) { if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) { String *classtype = Getattr(n, "classtype"); SWIG_WARN_NODE_BEGIN(ni); - Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor of director base class %s is marked as final.\n", classtype); + Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor %s is final, %s cannot be a director class.\n", Swig_name_decl(ni), classtype); SWIG_WARN_NODE_END(ni); SetFlag(n, "feature:nodirector"); Delete(vtable);