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.
This commit is contained in:
Zackery Spytz 2019-02-22 06:28:53 -07:00
commit c3d652c785
7 changed files with 87 additions and 7 deletions

View file

@ -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) 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 2019-02-21: wsfulton
#1240 Suppress Java 9 deprecation warnings on finalize method. #1240 Suppress Java 9 deprecation warnings on finalize method.

View file

@ -535,6 +535,7 @@ example.i(4) : Syntax error in input(1).
<li>522. Use of an illegal constructor name '<em>name</em>' in %extend is deprecated, the constructor name should be '<em>name</em>'. <li>522. Use of an illegal constructor name '<em>name</em>' in %extend is deprecated, the constructor name should be '<em>name</em>'.
<li>523. Use of an illegal destructor name '<em>name</em>' in %extend is deprecated, the destructor name should be '<em>name</em>'. <li>523. Use of an illegal destructor name '<em>name</em>' in %extend is deprecated, the destructor name should be '<em>name</em>'.
<li>524. Experimental target language. Target language <em>language</em> specified by <em>lang</em> is an experimental language. Please read about SWIG experimental languages, <em>htmllink</em>. <li>524. Experimental target language. Target language <em>language</em> specified by <em>lang</em> is an experimental language. Please read about SWIG experimental languages, <em>htmllink</em>.
<li>525. The director base class '<em>name</em>' or the destructor of director base class '<em>name</em>' is marked as final.
</ul> </ul>
<H3><a name="Warnings_doxygen">18.9.6 Doxygen comments (560-599)</a></H3> <H3><a name="Warnings_doxygen">18.9.6 Doxygen comments (560-599)</a></H3>

View file

@ -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() {}
};
%}

View file

@ -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

View file

@ -1552,6 +1552,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
Parm *throws; Parm *throws;
String *throwf; String *throwf;
String *nexcept; String *nexcept;
String *final;
} dtype; } dtype;
struct { struct {
const char *type; const char *type;
@ -1567,6 +1568,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
ParmList *throws; ParmList *throws;
String *throwf; String *throwf;
String *nexcept; String *nexcept;
String *final;
} decl; } decl;
Parm *tparms; Parm *tparms;
struct { struct {
@ -3189,6 +3191,7 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
Setattr($$,"throws",$4.throws); Setattr($$,"throws",$4.throws);
Setattr($$,"throw",$4.throwf); Setattr($$,"throw",$4.throwf);
Setattr($$,"noexcept",$4.nexcept); Setattr($$,"noexcept",$4.nexcept);
Setattr($$,"final",$4.final);
if ($5.val && $5.type) { if ($5.val && $5.type) {
/* store initializer type as it might be different to the declared type */ /* store initializer type as it might be different to the declared type */
SwigType *valuetype = NewSwigType($5.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($$,"throws",$4.throws);
Setattr($$,"throw",$4.throwf); Setattr($$,"throw",$4.throwf);
Setattr($$,"noexcept",$4.nexcept); Setattr($$,"noexcept",$4.nexcept);
Setattr($$,"final",$4.final);
if (!$9) { if (!$9) {
if (Len(scanner_ccode)) { if (Len(scanner_ccode)) {
String *code = Copy(scanner_ccode); String *code = Copy(scanner_ccode);
@ -3330,6 +3334,7 @@ c_decl_tail : SEMI {
Setattr($$,"throws",$3.throws); Setattr($$,"throws",$3.throws);
Setattr($$,"throw",$3.throwf); Setattr($$,"throw",$3.throwf);
Setattr($$,"noexcept",$3.nexcept); Setattr($$,"noexcept",$3.nexcept);
Setattr($$,"final",$3.final);
if ($4.bitfield) { if ($4.bitfield) {
Setattr($$,"bitfield", $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($$,"throws",$6.throws);
Setattr($$,"throw",$6.throwf); Setattr($$,"throw",$6.throwf);
Setattr($$,"noexcept",$6.nexcept); Setattr($$,"noexcept",$6.nexcept);
Setattr($$,"final",$6.final);
err = 0; err = 0;
} }
} }
@ -4704,6 +4710,7 @@ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
Setattr($$,"throws",$6.throws); Setattr($$,"throws",$6.throws);
Setattr($$,"throw",$6.throwf); Setattr($$,"throw",$6.throwf);
Setattr($$,"noexcept",$6.nexcept); Setattr($$,"noexcept",$6.nexcept);
Setattr($$,"final",$6.final);
if (Len(scanner_ccode)) { if (Len(scanner_ccode)) {
String *code = Copy(scanner_ccode); String *code = Copy(scanner_ccode);
Setattr($$,"code",code); Setattr($$,"code",code);
@ -4740,6 +4747,7 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
Setattr($$,"throws",$6.throws); Setattr($$,"throws",$6.throws);
Setattr($$,"throw",$6.throwf); Setattr($$,"throw",$6.throwf);
Setattr($$,"noexcept",$6.nexcept); Setattr($$,"noexcept",$6.nexcept);
Setattr($$,"final",$6.final);
if ($6.val) if ($6.val)
Setattr($$,"value",$6.val); Setattr($$,"value",$6.val);
if ($6.qualifier) if ($6.qualifier)
@ -4760,6 +4768,7 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
Setattr($$,"throws",$7.throws); Setattr($$,"throws",$7.throws);
Setattr($$,"throw",$7.throwf); Setattr($$,"throw",$7.throwf);
Setattr($$,"noexcept",$7.nexcept); Setattr($$,"noexcept",$7.nexcept);
Setattr($$,"final",$7.final);
if ($7.val) if ($7.val)
Setattr($$,"value",$7.val); Setattr($$,"value",$7.val);
if (Len(scanner_ccode)) { if (Len(scanner_ccode)) {
@ -4941,6 +4950,7 @@ cpp_end : cpp_const SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
} }
| cpp_const EQUAL default_delete SEMI { | cpp_const EQUAL default_delete SEMI {
Clear(scanner_ccode); Clear(scanner_ccode);
@ -4951,6 +4961,7 @@ cpp_end : cpp_const SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
} }
| cpp_const LBRACE { | cpp_const LBRACE {
skip_balanced('{','}'); skip_balanced('{','}');
@ -4961,6 +4972,7 @@ cpp_end : cpp_const SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
} }
; ;
@ -4973,6 +4985,7 @@ cpp_vend : cpp_const SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
} }
| cpp_const EQUAL definetype SEMI { | cpp_const EQUAL definetype SEMI {
Clear(scanner_ccode); Clear(scanner_ccode);
@ -4983,6 +4996,7 @@ cpp_vend : cpp_const SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
} }
| cpp_const LBRACE { | cpp_const LBRACE {
skip_balanced('{','}'); skip_balanced('{','}');
@ -4993,6 +5007,7 @@ cpp_vend : cpp_const SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
} }
; ;
@ -5210,6 +5225,7 @@ def_args : EQUAL definetype {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
} }
| EQUAL definetype LBRACKET expr RBRACKET { | EQUAL definetype LBRACKET expr RBRACKET {
@ -5223,6 +5239,7 @@ def_args : EQUAL definetype {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} else { } else {
$$.val = NewStringf("%s[%s]",$2.val,$4.val); $$.val = NewStringf("%s[%s]",$2.val,$4.val);
} }
@ -5236,6 +5253,7 @@ def_args : EQUAL definetype {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| COLON expr { | COLON expr {
$$.val = 0; $$.val = 0;
@ -5245,6 +5263,7 @@ def_args : EQUAL definetype {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| empty { | empty {
$$.val = 0; $$.val = 0;
@ -5254,6 +5273,7 @@ def_args : EQUAL definetype {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
; ;
@ -6293,6 +6313,7 @@ definetype : { /* scanner_check_typedef(); */ } expr {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
scanner_ignore_typedef(); scanner_ignore_typedef();
} }
| default_delete { | default_delete {
@ -6319,6 +6340,7 @@ deleted_definition : DELETE_KW {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
; ;
@ -6333,6 +6355,7 @@ explicit_default : DEFAULT {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
; ;
@ -6525,6 +6548,7 @@ valexpr : exprnum {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| WCHARCONST { | WCHARCONST {
$$.val = NewString($1); $$.val = NewString($1);
@ -6538,6 +6562,7 @@ valexpr : exprnum {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
/* grouping */ /* grouping */
@ -6892,18 +6917,18 @@ virt_specifier_seq : OVERRIDE {
$$ = 0; $$ = 0;
} }
| FINAL { | FINAL {
$$ = 0; $$ = NewString("1");
} }
| FINAL OVERRIDE { | FINAL OVERRIDE {
$$ = 0; $$ = NewString("1");
} }
| OVERRIDE FINAL { | OVERRIDE FINAL {
$$ = 0; $$ = NewString("1");
} }
; ;
virt_specifier_seq_opt : virt_specifier_seq { virt_specifier_seq_opt : virt_specifier_seq {
$$ = 0; $$ = $1;
} }
| empty { | empty {
$$ = 0; $$ = 0;
@ -6914,31 +6939,37 @@ exception_specification : THROW LPAREN parms RPAREN {
$$.throws = $3; $$.throws = $3;
$$.throwf = NewString("1"); $$.throwf = NewString("1");
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| NOEXCEPT { | NOEXCEPT {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = NewString("true"); $$.nexcept = NewString("true");
$$.final = 0;
} }
| virt_specifier_seq { | virt_specifier_seq {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = $1;
} }
| THROW LPAREN parms RPAREN virt_specifier_seq { | THROW LPAREN parms RPAREN virt_specifier_seq {
$$.throws = $3; $$.throws = $3;
$$.throwf = NewString("1"); $$.throwf = NewString("1");
$$.nexcept = 0; $$.nexcept = 0;
$$.final = $5;
} }
| NOEXCEPT virt_specifier_seq { | NOEXCEPT virt_specifier_seq {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = NewString("true"); $$.nexcept = NewString("true");
$$.final = $2;
} }
| NOEXCEPT LPAREN expr RPAREN { | NOEXCEPT LPAREN expr RPAREN {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = $3.val; $$.nexcept = $3.val;
$$.final = 0;
} }
; ;
@ -6946,6 +6977,7 @@ qualifiers_exception_specification : cv_ref_qualifier {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
$$.qualifier = $1.qualifier; $$.qualifier = $1.qualifier;
$$.refqualifier = $1.refqualifier; $$.refqualifier = $1.refqualifier;
} }
@ -6968,6 +7000,7 @@ cpp_const : qualifiers_exception_specification {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
$$.qualifier = 0; $$.qualifier = 0;
$$.refqualifier = 0; $$.refqualifier = 0;
} }
@ -6980,6 +7013,7 @@ ctor_end : cpp_const ctor_initializer SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
if ($1.qualifier) if ($1.qualifier)
Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); 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; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
if ($1.qualifier) if ($1.qualifier)
Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); 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; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| LPAREN parms RPAREN LBRACE { | LPAREN parms RPAREN LBRACE {
skip_balanced('{','}'); skip_balanced('{','}');
@ -7010,6 +7046,7 @@ ctor_end : cpp_const ctor_initializer SEMI {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| EQUAL definetype SEMI { | EQUAL definetype SEMI {
$$.have_parms = 0; $$.have_parms = 0;
@ -7017,6 +7054,7 @@ ctor_end : cpp_const ctor_initializer SEMI {
$$.throws = 0; $$.throws = 0;
$$.throwf = 0; $$.throwf = 0;
$$.nexcept = 0; $$.nexcept = 0;
$$.final = 0;
} }
| exception_specification EQUAL default_delete SEMI { | exception_specification EQUAL default_delete SEMI {
$$.have_parms = 0; $$.have_parms = 0;
@ -7024,6 +7062,7 @@ ctor_end : cpp_const ctor_initializer SEMI {
$$.throws = $1.throws; $$.throws = $1.throws;
$$.throwf = $1.throwf; $$.throwf = $1.throwf;
$$.nexcept = $1.nexcept; $$.nexcept = $1.nexcept;
$$.final = $1.final;
if ($1.qualifier) if ($1.qualifier)
Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
} }

View file

@ -211,6 +211,7 @@
#define WARN_LANG_EXTEND_CONSTRUCTOR 522 #define WARN_LANG_EXTEND_CONSTRUCTOR 522
#define WARN_LANG_EXTEND_DESTRUCTOR 523 #define WARN_LANG_EXTEND_DESTRUCTOR 523
#define WARN_LANG_EXPERIMENTAL 524 #define WARN_LANG_EXPERIMENTAL 524
#define WARN_LANG_DIRECTOR_FINAL 525
/* -- Doxygen comments -- */ /* -- Doxygen comments -- */

View file

@ -2109,7 +2109,7 @@ int Language::classDirectorMethods(Node *n) {
Node *item = Getitem(vtable, i); Node *item = Getitem(vtable, i);
String *method = Getattr(item, "methodNode"); String *method = Getattr(item, "methodNode");
String *fqdname = Getattr(item, "fqdname"); String *fqdname = Getattr(item, "fqdname");
if (GetFlag(method, "feature:nodirector")) if (GetFlag(method, "feature:nodirector") || GetFlag(method, "final"))
continue; continue;
String *wrn = Getattr(method, "feature:warnfilter"); String *wrn = Getattr(method, "feature:warnfilter");
@ -2198,6 +2198,13 @@ int Language::classDirector(Node *n) {
String *using_protected_members_code = NewString(""); String *using_protected_members_code = NewString("");
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
Node *nodeType = Getattr(ni, "nodeType"); 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); bool cdeclaration = (Cmp(nodeType, "cdecl") == 0);
if (cdeclaration && !GetFlag(ni, "feature:ignore")) { if (cdeclaration && !GetFlag(ni, "feature:ignore")) {
if (isNonVirtualProtectedAccess(ni)) { if (isNonVirtualProtectedAccess(ni)) {