Add C++11 virtual specifier sequences (final and/or override on methods)
Parsing support added. The final and override information is not used or added to the parse tree atm.
This commit is contained in:
parent
fc3098ea55
commit
6a72e16b37
5 changed files with 218 additions and 35 deletions
|
|
@ -414,6 +414,29 @@ class DerivedClass: public BaseClass {
|
|||
};
|
||||
</pre></div>
|
||||
|
||||
<H3><a name="CPlusPlus11_explicit_overrides_final"></a>Explicit overrides and final</H3>
|
||||
|
||||
<p>
|
||||
The special identifiers <tt>final</tt> and <tt>override</tt> can be used on methods and destructors,
|
||||
such as in the following example:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
struct BaseStruct {
|
||||
virtual void ab() const = 0;
|
||||
virtual void cd();
|
||||
virtual void ef();
|
||||
virtual ~BaseStruct();
|
||||
};
|
||||
struct DerivedStruct : BaseStruct {
|
||||
virtual void ab() const override;
|
||||
virtual void cd() final;
|
||||
virtual void ef() final override;
|
||||
virtual ~DerivedStruct() override;
|
||||
};
|
||||
</pre></div>
|
||||
|
||||
|
||||
<H3><a name="CPlusPlus11_null_pointer_constant"></a>7.2.11 Null pointer constant</H3>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -490,6 +490,7 @@ CPP11_TEST_CASES = \
|
|||
cpp11_default_delete \
|
||||
cpp11_delegating_constructors \
|
||||
cpp11_explicit_conversion_operators \
|
||||
cpp11_final_override \
|
||||
cpp11_function_objects \
|
||||
cpp11_inheriting_constructors \
|
||||
cpp11_initializer_list \
|
||||
|
|
|
|||
128
Examples/test-suite/cpp11_final_override.i
Normal file
128
Examples/test-suite/cpp11_final_override.i
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// Test C++11 virtual specifier sequences (final and/or override on methods)
|
||||
// Also check final/override - the two 'identifiers with special meaning' work as normal identifiers
|
||||
|
||||
%module cpp11_final_override
|
||||
|
||||
%warnfilter(SWIGWARN_PARSE_KEYWORD) final; // 'final' is a java keyword, renaming to '_final'
|
||||
%warnfilter(SWIGWARN_PARSE_KEYWORD) override; // 'override' is a C# keyword, renaming to '_override'
|
||||
|
||||
%inline %{
|
||||
|
||||
struct Base {
|
||||
virtual void stuff() const {}
|
||||
virtual void override1() const {}
|
||||
virtual void override2() const {}
|
||||
virtual void finaloverride1() {}
|
||||
virtual void finaloverride2() {}
|
||||
virtual void finaloverride3() {}
|
||||
virtual void finaloverride4() const {}
|
||||
virtual ~Base() {}
|
||||
};
|
||||
|
||||
struct Derived /*final*/ : Base {
|
||||
virtual void stuff() const noexcept override final {}
|
||||
virtual void override1() const noexcept override;
|
||||
virtual void override2() const noexcept override;
|
||||
virtual void final1() final {}
|
||||
virtual void final2() noexcept final {}
|
||||
virtual void final4() const final {}
|
||||
virtual void final5() const noexcept final {}
|
||||
virtual void finaloverride1() final override {}
|
||||
virtual void finaloverride2() override final {}
|
||||
virtual void finaloverride3() noexcept override final {}
|
||||
virtual void finaloverride4() const noexcept override final {}
|
||||
virtual ~Derived() override final {}
|
||||
};
|
||||
void Derived::override2() const noexcept {}
|
||||
|
||||
// Pure virtual methods
|
||||
struct PureBase {
|
||||
virtual void pure1(int) const = 0;
|
||||
virtual void pure2(int) const = 0;
|
||||
virtual void pure3(int) const = 0;
|
||||
virtual void pure4(int) const = 0;
|
||||
virtual void pure5(int) const = 0;
|
||||
virtual ~PureBase() {}
|
||||
};
|
||||
|
||||
struct PureDerived : PureBase {
|
||||
virtual void pure1(int) const override = 0;
|
||||
virtual void pure2(int) const final = 0;
|
||||
virtual void pure3(int) const override final = 0;
|
||||
virtual void pure4(int) const final override = 0;
|
||||
virtual void pure5(int) const noexcept final override = 0;
|
||||
virtual ~PureDerived() override final;
|
||||
};
|
||||
void PureDerived::pure1(int) const {}
|
||||
void PureDerived::pure2(int) const {}
|
||||
void PureDerived::pure3(int) const {}
|
||||
void PureDerived::pure4(int) const {}
|
||||
void PureDerived::pure5(int) const noexcept {}
|
||||
PureDerived::~PureDerived() {}
|
||||
|
||||
// Destructors and virtual specifier sequences (final/override)
|
||||
struct Destructors1 : Base {
|
||||
virtual ~Destructors1() override {}
|
||||
};
|
||||
struct Destructors2 : Base {
|
||||
virtual ~Destructors2() final {}
|
||||
};
|
||||
struct Destructors3 : Base {
|
||||
virtual ~Destructors3() noexcept final override {}
|
||||
};
|
||||
struct Destructors4 : Base {
|
||||
virtual ~Destructors4() noexcept override final {}
|
||||
};
|
||||
|
||||
// Check the two 'identifiers with special meaning' work as normal identifiers
|
||||
struct FinalOverrideMethods {
|
||||
virtual void final() {}
|
||||
virtual void override(int) {}
|
||||
};
|
||||
struct FinalOverrideVariables {
|
||||
int final;
|
||||
double override;
|
||||
};
|
||||
void final(int) {}
|
||||
void override() {}
|
||||
%}
|
||||
|
||||
%{
|
||||
void Derived::override1() const noexcept {}
|
||||
%}
|
||||
|
||||
// Example in documentation ... declarations only
|
||||
%inline %{
|
||||
struct BaseStruct {
|
||||
virtual void ab() const = 0;
|
||||
virtual void cd();
|
||||
virtual void ef();
|
||||
virtual ~BaseStruct();
|
||||
};
|
||||
struct DerivedStruct : BaseStruct {
|
||||
virtual void ab() const override;
|
||||
virtual void cd() final;
|
||||
virtual void ef() final override;
|
||||
virtual ~DerivedStruct() override;
|
||||
};
|
||||
struct DerivedNoVirtualStruct : BaseStruct {
|
||||
void ab() const override;
|
||||
void cd() final;
|
||||
void ef() final override;
|
||||
~DerivedNoVirtualStruct() override;
|
||||
};
|
||||
%}
|
||||
|
||||
%{
|
||||
void BaseStruct::cd() {}
|
||||
void BaseStruct::ef() {}
|
||||
BaseStruct::~BaseStruct() {}
|
||||
void DerivedStruct::ab() const {}
|
||||
void DerivedStruct::cd() {}
|
||||
void DerivedStruct::ef() {}
|
||||
DerivedStruct::~DerivedStruct() {}
|
||||
void DerivedNoVirtualStruct::ab() const {}
|
||||
void DerivedNoVirtualStruct::cd() {}
|
||||
void DerivedNoVirtualStruct::ef() {}
|
||||
DerivedNoVirtualStruct::~DerivedNoVirtualStruct() {}
|
||||
%}
|
||||
|
|
@ -748,18 +748,18 @@ int yylex(void) {
|
|||
yylval.intvalue = cparse_line;
|
||||
return (TEMPLATE);
|
||||
}
|
||||
if (strcmp(yytext, "delete") == 0) {
|
||||
if (strcmp(yytext, "delete") == 0)
|
||||
return (DELETE_KW);
|
||||
}
|
||||
if (strcmp(yytext, "default") == 0) {
|
||||
if (strcmp(yytext, "default") == 0)
|
||||
return (DEFAULT);
|
||||
}
|
||||
if (strcmp(yytext, "using") == 0) {
|
||||
if (strcmp(yytext, "using") == 0)
|
||||
return (USING);
|
||||
}
|
||||
if (strcmp(yytext, "namespace") == 0) {
|
||||
if (strcmp(yytext, "namespace") == 0)
|
||||
return (NAMESPACE);
|
||||
}
|
||||
if (strcmp(yytext, "override") == 0)
|
||||
return (OVERRIDE);
|
||||
if (strcmp(yytext, "final") == 0)
|
||||
return (FINAL);
|
||||
} else {
|
||||
if (strcmp(yytext, "class") == 0) {
|
||||
Swig_warning(WARN_PARSE_CLASS_KEYWORD, cparse_file, cparse_line, "class keyword used, but not in C++ mode.\n");
|
||||
|
|
|
|||
|
|
@ -1388,8 +1388,9 @@ static void mark_nodes_as_extend(Node *n) {
|
|||
%token ILLEGAL CONSTANT
|
||||
%token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
|
||||
%token ENUM
|
||||
%token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH EXPLICIT AUTO NOEXCEPT
|
||||
%token STATIC_ASSERT CONSTEXPR THREAD_LOCAL DECLTYPE /* C++11 keywords */
|
||||
%token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH EXPLICIT
|
||||
%token STATIC_ASSERT CONSTEXPR THREAD_LOCAL DECLTYPE AUTO NOEXCEPT /* C++11 keywords */
|
||||
%token OVERRIDE FINAL /* C++11 identifiers with special meaning */
|
||||
%token USING
|
||||
%token <node> NAMESPACE
|
||||
%token NATIVE INLINE
|
||||
|
|
@ -1443,6 +1444,7 @@ static void mark_nodes_as_extend(Node *n) {
|
|||
%type <node> kwargs options;
|
||||
|
||||
/* Misc */
|
||||
%type <id> identifier;
|
||||
%type <dtype> initializer cpp_const exception_specification;
|
||||
%type <id> storage_class;
|
||||
%type <pl> parms ptail rawparms varargs_parms ;
|
||||
|
|
@ -1480,6 +1482,7 @@ static void mark_nodes_as_extend(Node *n) {
|
|||
%type <node> lambda_introducer lambda_body;
|
||||
%type <pl> lambda_tail;
|
||||
%type <node> optional_constant_directive;
|
||||
%type <str> virt_specifier_seq;
|
||||
|
||||
%%
|
||||
|
||||
|
|
@ -1701,7 +1704,7 @@ clear_directive : CLEAR tm_list SEMI {
|
|||
%constant type name = value;
|
||||
------------------------------------------------------------ */
|
||||
|
||||
constant_directive : CONSTANT ID EQUAL definetype SEMI {
|
||||
constant_directive : CONSTANT identifier EQUAL definetype SEMI {
|
||||
if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) {
|
||||
SwigType *type = NewSwigType($4.type);
|
||||
$$ = new_node("constant");
|
||||
|
|
@ -1783,7 +1786,7 @@ echo_directive : ECHO HBLOCK {
|
|||
%except;
|
||||
------------------------------------------------------------ */
|
||||
|
||||
except_directive : EXCEPT LPAREN ID RPAREN LBRACE {
|
||||
except_directive : EXCEPT LPAREN identifier RPAREN LBRACE {
|
||||
skip_balanced('{','}');
|
||||
$$ = 0;
|
||||
Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
|
||||
|
|
@ -1795,7 +1798,7 @@ except_directive : EXCEPT LPAREN ID RPAREN LBRACE {
|
|||
Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
|
||||
}
|
||||
|
||||
| EXCEPT LPAREN ID RPAREN SEMI {
|
||||
| EXCEPT LPAREN identifier RPAREN SEMI {
|
||||
$$ = 0;
|
||||
Swig_warning(WARN_DEPRECATED_EXCEPT,cparse_file, cparse_line, "%%except is deprecated. Use %%exception instead.\n");
|
||||
}
|
||||
|
|
@ -2080,13 +2083,13 @@ name_directive : NAME LPAREN idstring RPAREN {
|
|||
%native(scriptname) type name (parms);
|
||||
------------------------------------------------------------ */
|
||||
|
||||
native_directive : NATIVE LPAREN ID RPAREN storage_class ID SEMI {
|
||||
native_directive : NATIVE LPAREN identifier RPAREN storage_class identifier SEMI {
|
||||
$$ = new_node("native");
|
||||
Setattr($$,"name",$3);
|
||||
Setattr($$,"wrap:name",$6);
|
||||
add_symbols($$);
|
||||
}
|
||||
| NATIVE LPAREN ID RPAREN storage_class type declarator SEMI {
|
||||
| NATIVE LPAREN identifier RPAREN storage_class type declarator SEMI {
|
||||
if (!SwigType_isfunction($7.type)) {
|
||||
Swig_error(cparse_file,cparse_line,"%%native declaration '%s' is not a function.\n", $7.id);
|
||||
$$ = 0;
|
||||
|
|
@ -2112,13 +2115,13 @@ native_directive : NATIVE LPAREN ID RPAREN storage_class ID SEMI {
|
|||
%pragma name
|
||||
------------------------------------------------------------ */
|
||||
|
||||
pragma_directive : PRAGMA pragma_lang ID EQUAL pragma_arg {
|
||||
pragma_directive : PRAGMA pragma_lang identifier EQUAL pragma_arg {
|
||||
$$ = new_node("pragma");
|
||||
Setattr($$,"lang",$2);
|
||||
Setattr($$,"name",$3);
|
||||
Setattr($$,"value",$5);
|
||||
}
|
||||
| PRAGMA pragma_lang ID {
|
||||
| PRAGMA pragma_lang identifier {
|
||||
$$ = new_node("pragma");
|
||||
Setattr($$,"lang",$2);
|
||||
Setattr($$,"name",$3);
|
||||
|
|
@ -2129,13 +2132,12 @@ pragma_arg : string { $$ = NewString($1); }
|
|||
| HBLOCK { $$ = $1; }
|
||||
;
|
||||
|
||||
pragma_lang : LPAREN ID RPAREN { $$ = $2; }
|
||||
pragma_lang : LPAREN identifier RPAREN { $$ = $2; }
|
||||
| empty { $$ = (char *) "swig"; }
|
||||
;
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
%rename identifier newname;
|
||||
%rename identifier "newname";
|
||||
%rename(newname) identifier;
|
||||
------------------------------------------------------------ */
|
||||
|
||||
rename_directive : rename_namewarn declarator idstring SEMI {
|
||||
|
|
@ -2883,7 +2885,7 @@ c_declaration : c_decl {
|
|||
|
||||
$$ = 0; /* TODO - ignored for now */
|
||||
}
|
||||
| TEMPLATE LESSTHAN template_parms GREATERTHAN USING idcolon EQUAL ID {
|
||||
| TEMPLATE LESSTHAN template_parms GREATERTHAN USING idcolon EQUAL identifier {
|
||||
skip_decl();
|
||||
$$ = new_node("using");
|
||||
Setattr($$,"uname",$8);
|
||||
|
|
@ -4221,7 +4223,7 @@ cpp_namespace_decl : NAMESPACE idcolon LBRACE {
|
|||
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
||||
add_symbols($$);
|
||||
}
|
||||
| NAMESPACE ID EQUAL idcolon SEMI {
|
||||
| NAMESPACE identifier EQUAL idcolon SEMI {
|
||||
/* Namespace alias */
|
||||
Node *n;
|
||||
$$ = new_node("namespace");
|
||||
|
|
@ -5810,7 +5812,7 @@ explicit_default : DEFAULT {
|
|||
|
||||
/* Some stuff for handling enums */
|
||||
|
||||
ename : ID { $$ = $1; }
|
||||
ename : identifier { $$ = $1; }
|
||||
| empty { $$ = (char *) 0;}
|
||||
;
|
||||
|
||||
|
|
@ -5837,7 +5839,7 @@ enumlist : enumlist COMMA optional_constant_directive edecl optional_cons
|
|||
}
|
||||
;
|
||||
|
||||
edecl : ID {
|
||||
edecl : identifier {
|
||||
SwigType *type = NewSwigType(T_INT);
|
||||
$$ = new_node("enumitem");
|
||||
Setattr($$,"name",$1);
|
||||
|
|
@ -5845,7 +5847,7 @@ edecl : ID {
|
|||
SetFlag($$,"feature:immutable");
|
||||
Delete(type);
|
||||
}
|
||||
| ID EQUAL etype {
|
||||
| identifier EQUAL etype {
|
||||
SwigType *type = NewSwigType($3.type == T_BOOL ? T_BOOL : ($3.type == T_CHAR ? T_CHAR : T_INT));
|
||||
$$ = new_node("enumitem");
|
||||
Setattr($$,"name",$1);
|
||||
|
|
@ -6263,6 +6265,20 @@ opt_virtual : VIRTUAL
|
|||
| empty
|
||||
;
|
||||
|
||||
virt_specifier_seq : OVERRIDE {
|
||||
$$ = 0;
|
||||
}
|
||||
| FINAL {
|
||||
$$ = 0;
|
||||
}
|
||||
| FINAL OVERRIDE {
|
||||
$$ = 0;
|
||||
}
|
||||
| OVERRIDE FINAL {
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
exception_specification : THROW LPAREN parms RPAREN {
|
||||
$$.throws = $3;
|
||||
$$.throwf = NewString("1");
|
||||
|
|
@ -6273,7 +6289,16 @@ exception_specification : THROW LPAREN parms RPAREN {
|
|||
$$.throwf = 0;
|
||||
$$.nexcept = NewString("true");
|
||||
}
|
||||
|
||||
| virt_specifier_seq {
|
||||
$$.throws = 0;
|
||||
$$.throwf = 0;
|
||||
$$.nexcept = 0;
|
||||
}
|
||||
| NOEXCEPT virt_specifier_seq {
|
||||
$$.throws = 0;
|
||||
$$.throwf = 0;
|
||||
$$.nexcept = NewString("true");
|
||||
}
|
||||
| NOEXCEPT LPAREN expr RPAREN {
|
||||
$$.throws = 0;
|
||||
$$.throwf = 0;
|
||||
|
|
@ -6390,7 +6415,13 @@ template_decl : LESSTHAN valparms GREATERTHAN {
|
|||
| empty { $$ = (char*)""; }
|
||||
;
|
||||
|
||||
idstring : ID { $$ = $1; }
|
||||
/* Identifiers including the C++11 identifiers with special meaning */
|
||||
identifier : ID { $$ = $1; }
|
||||
| OVERRIDE { $$ = Swig_copy_string("override"); }
|
||||
| FINAL { $$ = Swig_copy_string("final"); }
|
||||
;
|
||||
|
||||
idstring : identifier { $$ = $1; }
|
||||
| default_delete { $$ = $1.val; }
|
||||
| string { $$ = $1; }
|
||||
;
|
||||
|
|
@ -6442,7 +6473,7 @@ idcolontail : DCOLON idtemplate idcolontail {
|
|||
;
|
||||
|
||||
|
||||
idtemplate : ID template_decl {
|
||||
idtemplate : identifier template_decl {
|
||||
$$ = NewStringf("%s%s",$1,$2);
|
||||
/* if (Len($2)) {
|
||||
scanner_last_id(1);
|
||||
|
|
@ -6451,19 +6482,19 @@ idtemplate : ID template_decl {
|
|||
;
|
||||
|
||||
/* Identifier, but no templates */
|
||||
idcolonnt : ID idcolontailnt {
|
||||
idcolonnt : identifier idcolontailnt {
|
||||
$$ = 0;
|
||||
if (!$$) $$ = NewStringf("%s%s", $1,$2);
|
||||
Delete($2);
|
||||
}
|
||||
| NONID DCOLON ID idcolontailnt {
|
||||
| NONID DCOLON identifier idcolontailnt {
|
||||
$$ = NewStringf("::%s%s",$3,$4);
|
||||
Delete($4);
|
||||
}
|
||||
| ID {
|
||||
| identifier {
|
||||
$$ = NewString($1);
|
||||
}
|
||||
| NONID DCOLON ID {
|
||||
| NONID DCOLON identifier {
|
||||
$$ = NewStringf("::%s",$3);
|
||||
}
|
||||
| OPERATOR {
|
||||
|
|
@ -6474,17 +6505,17 @@ idcolonnt : ID idcolontailnt {
|
|||
}
|
||||
;
|
||||
|
||||
idcolontailnt : DCOLON ID idcolontailnt {
|
||||
idcolontailnt : DCOLON identifier idcolontailnt {
|
||||
$$ = NewStringf("::%s%s",$2,$3);
|
||||
Delete($3);
|
||||
}
|
||||
| DCOLON ID {
|
||||
| DCOLON identifier {
|
||||
$$ = NewStringf("::%s",$2);
|
||||
}
|
||||
| DCOLON OPERATOR {
|
||||
$$ = NewStringf("::%s",$2);
|
||||
}
|
||||
| DCNOT ID {
|
||||
| DCNOT identifier {
|
||||
$$ = NewStringf("::~%s",$2);
|
||||
}
|
||||
;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue