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)) {