Add support for parsing C++11 final classes
Such as:
class X final {};
This no longer gives a syntax error.
This change has introduced one more shift-reduce conflict in the parser.
with a conflict with a C style variable declaration with name final:
class X final;
resulting in a syntax error (for C++ not C). This is an an unusual style
for C++ code and more typical declarations do work:
X final;
Closes #672
This commit is contained in:
parent
76f5670fa4
commit
ba279ae939
9 changed files with 267 additions and 24 deletions
|
|
@ -13,14 +13,14 @@
|
|||
* some point. Beware.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
/* There are 6 known shift-reduce conflicts in this file, fail compilation if any
|
||||
more are introduced.
|
||||
/* There are a small number of known shift-reduce conflicts in this file, fail
|
||||
compilation if any more are introduced.
|
||||
|
||||
Please don't increase the number of the conflicts if at all possible. And if
|
||||
you really have no choice but to do it, make sure you clearly document each
|
||||
new conflict in this file.
|
||||
*/
|
||||
%expect 6
|
||||
%expect 7
|
||||
|
||||
%{
|
||||
#define yylex yylex
|
||||
|
|
@ -1716,6 +1716,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
|
|||
%type <node> lambda_introducer lambda_body lambda_template;
|
||||
%type <pl> lambda_tail;
|
||||
%type <str> virt_specifier_seq virt_specifier_seq_opt;
|
||||
%type <str> class_virt_specifier_opt;
|
||||
|
||||
%%
|
||||
|
||||
|
|
@ -3708,7 +3709,11 @@ cpp_declaration : cpp_class_decl { $$ = $1; }
|
|||
|
||||
|
||||
/* A simple class/struct/union definition */
|
||||
cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
||||
|
||||
/* Note that class_virt_specifier_opt for supporting final classes introduces one shift-reduce conflict
|
||||
with C style variable declarations, such as: struct X final; */
|
||||
|
||||
cpp_class_decl: storage_class cpptype idcolon class_virt_specifier_opt inherit LBRACE {
|
||||
String *prefix;
|
||||
List *bases = 0;
|
||||
Node *scope = 0;
|
||||
|
|
@ -3716,10 +3721,10 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
$<node>$ = new_node("class");
|
||||
Setline($<node>$,cparse_start_line);
|
||||
Setattr($<node>$,"kind",$2);
|
||||
if ($4) {
|
||||
Setattr($<node>$,"baselist", Getattr($4,"public"));
|
||||
Setattr($<node>$,"protectedbaselist", Getattr($4,"protected"));
|
||||
Setattr($<node>$,"privatebaselist", Getattr($4,"private"));
|
||||
if ($5) {
|
||||
Setattr($<node>$,"baselist", Getattr($5,"public"));
|
||||
Setattr($<node>$,"protectedbaselist", Getattr($5,"protected"));
|
||||
Setattr($<node>$,"privatebaselist", Getattr($5,"private"));
|
||||
}
|
||||
Setattr($<node>$,"allows_typedef","1");
|
||||
|
||||
|
|
@ -3747,8 +3752,8 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
Setattr($<node>$, "Classprefix", $3);
|
||||
Classprefix = NewString($3);
|
||||
/* Deal with inheritance */
|
||||
if ($4)
|
||||
bases = Swig_make_inherit_list($3,Getattr($4,"public"),Namespaceprefix);
|
||||
if ($5)
|
||||
bases = Swig_make_inherit_list($3,Getattr($5,"public"),Namespaceprefix);
|
||||
prefix = SwigType_istemplate_templateprefix($3);
|
||||
if (prefix) {
|
||||
String *fbase, *tbase;
|
||||
|
|
@ -3828,7 +3833,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
Delattr($$, "prev_symtab");
|
||||
|
||||
/* Check for pure-abstract class */
|
||||
Setattr($$,"abstracts", pure_abstracts($7));
|
||||
Setattr($$,"abstracts", pure_abstracts($8));
|
||||
|
||||
/* This bit of code merges in a previously defined %extend directive (if any) */
|
||||
{
|
||||
|
|
@ -3844,12 +3849,12 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
scpname = Swig_symbol_qualifiedscopename(0);
|
||||
Setattr(classes, scpname, $$);
|
||||
|
||||
appendChild($$, $7);
|
||||
appendChild($$, $8);
|
||||
|
||||
if (am)
|
||||
Swig_extend_append_previous($$, am);
|
||||
|
||||
p = $9;
|
||||
p = $10;
|
||||
if (p && !nscope_inner) {
|
||||
if (!cparse_cplusplus && currentOuterClass)
|
||||
appendChild(currentOuterClass, p);
|
||||
|
|
@ -3873,8 +3878,8 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
}
|
||||
p = nextSibling(p);
|
||||
}
|
||||
if ($9 && Cmp($1,"typedef") == 0)
|
||||
add_typedef_name($$, $9, $3, cscope, scpname);
|
||||
if ($10 && Cmp($1,"typedef") == 0)
|
||||
add_typedef_name($$, $10, $3, cscope, scpname);
|
||||
Delete(scpname);
|
||||
|
||||
if (cplus_mode != CPLUS_PUBLIC) {
|
||||
|
|
@ -3896,12 +3901,12 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
if (cplus_mode == CPLUS_PRIVATE) {
|
||||
$$ = 0; /* skip private nested classes */
|
||||
} else if (cparse_cplusplus && currentOuterClass && ignore_nested_classes && !GetFlag($$, "feature:flatnested")) {
|
||||
$$ = nested_forward_declaration($1, $2, $3, Copy($3), $9);
|
||||
$$ = nested_forward_declaration($1, $2, $3, Copy($3), $10);
|
||||
} else if (nscope_inner) {
|
||||
/* this is tricky */
|
||||
/* we add the declaration in the original namespace */
|
||||
if (Strcmp(nodeType(nscope_inner), "class") == 0 && cparse_cplusplus && ignore_nested_classes && !GetFlag($$, "feature:flatnested"))
|
||||
$$ = nested_forward_declaration($1, $2, $3, Copy($3), $9);
|
||||
$$ = nested_forward_declaration($1, $2, $3, Copy($3), $10);
|
||||
appendChild(nscope_inner, $$);
|
||||
Swig_symbol_setscope(Getattr(nscope_inner, "symtab"));
|
||||
Delete(Namespaceprefix);
|
||||
|
|
@ -3913,14 +3918,14 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
Swig_symbol_setscope(cscope);
|
||||
Delete(Namespaceprefix);
|
||||
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
||||
add_symbols($9);
|
||||
add_symbols($10);
|
||||
if (nscope) {
|
||||
$$ = nscope; /* here we return recreated namespace tower instead of the class itself */
|
||||
if ($9) {
|
||||
appendSibling($$, $9);
|
||||
if ($10) {
|
||||
appendSibling($$, $10);
|
||||
}
|
||||
} else if (!SwigType_istemplate(ty) && template_parameters == 0) { /* for template we need the class itself */
|
||||
$$ = $9;
|
||||
$$ = $10;
|
||||
}
|
||||
} else {
|
||||
Delete(yyrename);
|
||||
|
|
@ -3931,7 +3936,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
outer = Getattr(outer, "nested:outer");
|
||||
appendSibling(outer, $$);
|
||||
Swig_symbol_setscope(cscope); /* declaration goes in the parent scope */
|
||||
add_symbols($9);
|
||||
add_symbols($10);
|
||||
set_scope_to_global();
|
||||
Delete(Namespaceprefix);
|
||||
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
||||
|
|
@ -3944,7 +3949,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
|||
} else {
|
||||
yyrename = Copy(Getattr($<node>$, "class_rename"));
|
||||
add_symbols($$);
|
||||
add_symbols($9);
|
||||
add_symbols($10);
|
||||
Delattr($$, "class_rename");
|
||||
}
|
||||
}
|
||||
|
|
@ -7062,6 +7067,14 @@ virt_specifier_seq_opt : virt_specifier_seq {
|
|||
}
|
||||
;
|
||||
|
||||
class_virt_specifier_opt : FINAL {
|
||||
$$ = NewString("1");
|
||||
}
|
||||
| empty {
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
exception_specification : THROW LPAREN parms RPAREN {
|
||||
$$.throws = $3;
|
||||
$$.throwf = NewString("1");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue