From 368e1ca644c999336975ada6d1ab3af40c13f757 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 2 Jan 2015 14:57:33 +0100 Subject: [PATCH] Support noexcept and rvalue references in C++ parser --- dtool/src/cppparser/cppBison.yxx | 111 +++++++++++------- dtool/src/cppparser/cppFunctionType.cxx | 3 + dtool/src/cppparser/cppFunctionType.h | 1 + dtool/src/cppparser/cppInstanceIdentifier.cxx | 10 +- dtool/src/cppparser/cppInstanceIdentifier.h | 1 + dtool/src/cppparser/cppPreprocessor.cxx | 1 + dtool/src/cppparser/cppReferenceType.cxx | 22 +++- dtool/src/cppparser/cppReferenceType.h | 13 +- 8 files changed, 110 insertions(+), 52 deletions(-) diff --git a/dtool/src/cppparser/cppBison.yxx b/dtool/src/cppparser/cppBison.yxx index 238c4f578b..80d78fe184 100644 --- a/dtool/src/cppparser/cppBison.yxx +++ b/dtool/src/cppparser/cppBison.yxx @@ -1,6 +1,6 @@ // Filename: cppBison.y // Created by: drose (16Jan99) -// +// //////////////////////////////////////////////////////////////////// %{ @@ -38,7 +38,7 @@ CPPScope *current_scope = NULL; CPPScope *global_scope = NULL; CPPPreprocessor *current_lexer = NULL; -static CPPStructType *current_struct = NULL; +static CPPStructType *current_struct = NULL; static CPPEnumType *current_enum = NULL; static int current_storage_class = 0; static CPPType *current_type = NULL; @@ -98,7 +98,7 @@ parse_cpp(CPPParser *cp) { current_scope = old_scope; global_scope = old_global_scope; current_lexer = old_lexer; - + } CPPExpression * @@ -140,7 +140,7 @@ parse_type(CPPPreprocessor *pp, CPPScope *new_current_scope, yyparse(); CPPType *result = current_type; - + current_scope = old_scope; global_scope = old_global_scope; current_lexer = old_lexer; @@ -223,8 +223,8 @@ pop_struct() { %token UNARY_REF %token POINTSAT %token SCOPE -%token PLUSPLUS -%token MINUSMINUS +%token PLUSPLUS +%token MINUSMINUS %token TIMESEQUAL %token DIVIDEEQUAL %token MODEQUAL @@ -242,14 +242,14 @@ pop_struct() { %token KW_CATCH %token KW_CHAR %token KW_WCHAR_T -%token KW_CLASS -%token KW_CONST +%token KW_CLASS +%token KW_CONST %token KW_DELETE %token KW_DOUBLE %token KW_DYNAMIC_CAST %token KW_ELSE -%token KW_END_PUBLISH -%token KW_ENUM +%token KW_END_PUBLISH +%token KW_ENUM %token KW_EXTENSION %token KW_EXTERN %token KW_EXPLICIT @@ -269,6 +269,7 @@ pop_struct() { %token KW_MUTABLE %token KW_NAMESPACE %token KW_NEW +%token KW_NOEXCEPT %token KW_OPERATOR %token KW_PRIVATE %token KW_PROTECTED @@ -280,14 +281,14 @@ pop_struct() { %token KW_SIZEOF %token KW_STATIC %token KW_STATIC_CAST -%token KW_STRUCT +%token KW_STRUCT %token KW_TEMPLATE %token KW_THROW %token KW_TRUE %token KW_TRY -%token KW_TYPEDEF +%token KW_TYPEDEF %token KW_TYPENAME -%token KW_UNION +%token KW_UNION %token KW_UNSIGNED %token KW_USING %token KW_VIRTUAL @@ -417,7 +418,7 @@ constructor_init: extern_c: storage_class '{' { - push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | + push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | ($1 & CPPInstance::SC_c_binding)); } cpp '}' @@ -434,7 +435,7 @@ declaration: | using_declaration | friend_declaration | KW_TYPEDEF typedef_declaration - | KW_BEGIN_PUBLISH + | KW_BEGIN_PUBLISH { if (publish_nest_level != 0) { yyerror("Unclosed __begin_publish", publish_loc); @@ -447,7 +448,7 @@ declaration: publish_nest_level++; current_scope->set_current_vis(V_published); } - | KW_END_PUBLISH + | KW_END_PUBLISH { if (publish_nest_level != 1) { yyerror("Unmatched __end_publish", @1); @@ -765,7 +766,7 @@ typedef_const_instance_identifiers: function_prototype: /* Functions with implicit return types, and constructors */ - IDENTIFIER '(' + IDENTIFIER '(' { push_scope($1->get_scope(current_scope, global_scope)); } @@ -821,13 +822,13 @@ function_prototype: if ($2->is_scoped()) { yyerror("Invalid destructor name: ~" + $2->get_fully_scoped_name(), @2); } else { - CPPIdentifier *ident = + CPPIdentifier *ident = new CPPIdentifier("~" + $2->get_simple_name(), @2.file); delete $2; CPPType *type; type = new CPPSimpleType(CPPSimpleType::T_void); - + CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident); ii->add_func_modifier($5, $7); @@ -932,7 +933,7 @@ function_prototype: avoid shift/reduce conflicts. */ | IDENTIFIER { - CPPDeclaration *decl = + CPPDeclaration *decl = $1->find_symbol(current_scope, global_scope, current_lexer); if (decl != (CPPDeclaration *)NULL) { $$ = decl->as_instance(); @@ -950,6 +951,10 @@ function_post: | KW_CONST { $$ = (int)CPPFunctionType::F_const_method; +} + | function_post KW_NOEXCEPT +{ + $$ = (int)CPPFunctionType::F_noexcept; } | function_post KW_THROW '(' ')' { @@ -1239,6 +1244,11 @@ instance_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND instance_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' instance_identifier %prec UNARY { @@ -1436,6 +1446,11 @@ not_paren_formal_parameter_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND not_paren_formal_parameter_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' not_paren_formal_parameter_identifier %prec UNARY { @@ -1476,6 +1491,11 @@ formal_parameter_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND formal_parameter_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' formal_parameter_identifier %prec UNARY { @@ -1519,6 +1539,11 @@ empty_instance_identifier: { $$ = $2; $$->add_modifier(IIT_reference); +} + | ANDAND empty_instance_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_rvalue_reference); } | SCOPING '*' empty_instance_identifier %prec UNARY { @@ -1574,7 +1599,7 @@ type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1590,7 +1615,7 @@ type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1638,7 +1663,7 @@ type_decl: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1654,7 +1679,7 @@ type_decl: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1686,7 +1711,7 @@ predefined_type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1702,7 +1727,7 @@ predefined_type: if (type != NULL) { $$ = type; } else { - CPPExtensionType *et = + CPPExtensionType *et = CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file)) ->as_extension_type(); CPPScope *scope = $2->get_scope(current_scope, global_scope); @@ -1733,9 +1758,9 @@ full_type: anonymous_struct: struct_keyword '{' { - CPPVisibility starting_vis = + CPPVisibility starting_vis = ($1 == CPPExtensionType::T_class) ? V_private : V_public; - + CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"), starting_vis); CPPStructType *st = new CPPStructType($1, NULL, current_scope, @@ -1757,7 +1782,7 @@ anonymous_struct: named_struct: struct_keyword name { - CPPVisibility starting_vis = + CPPVisibility starting_vis = ($1 == CPPExtensionType::T_class) ? V_private : V_public; CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer); @@ -1771,7 +1796,7 @@ named_struct: new_scope, @1.file); new_scope->set_struct_type(st); current_scope->define_extension_type(st); - + push_scope(new_scope); push_struct(st); } @@ -1916,7 +1941,7 @@ namespace_declaration: CPPScope *scope = $2->find_scope(current_scope, global_scope, current_lexer); if (scope == NULL) { // This must be a new namespace declaration. - CPPScope *parent_scope = + CPPScope *parent_scope = $2->get_scope(current_scope, global_scope, current_lexer); if (parent_scope == NULL) { parent_scope = current_scope; @@ -2104,13 +2129,13 @@ element: | ELLIPSIS | OROR | ANDAND | EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE | LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT - | SCOPE | PLUSPLUS | MINUSMINUS + | SCOPE | PLUSPLUS | MINUSMINUS | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL | KW_BOOL | KW_CATCH | KW_CHAR | KW_WCHAR_T | KW_CLASS | KW_CONST | KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM | KW_EXTERN | KW_EXPLICIT | KW_FALSE - | KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO + | KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO | KW_IF | KW_INLINE | KW_INT | KW_LONG | KW_MUTABLE | KW_NEW | KW_PRIVATE | KW_PROTECTED | KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_RETURN @@ -2329,65 +2354,65 @@ const_expr: } | KW_INT '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_CHAR '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_WCHAR_T '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_BOOL '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_SHORT '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_short)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_LONG '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_long)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_UNSIGNED '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_unsigned)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_SIGNED '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_signed)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_FLOAT '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } | KW_DOUBLE '(' optional_const_expr_comma ')' { - CPPType *type = + CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); } diff --git a/dtool/src/cppparser/cppFunctionType.cxx b/dtool/src/cppparser/cppFunctionType.cxx index 8625f7e721..515729cf39 100644 --- a/dtool/src/cppparser/cppFunctionType.cxx +++ b/dtool/src/cppparser/cppFunctionType.cxx @@ -243,6 +243,9 @@ output_instance(ostream &out, int indent_level, CPPScope *scope, if (_flags & F_const_method) { out << " const"; } + if (_flags & F_noexcept) { + out << " noexcept"; + } } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/cppparser/cppFunctionType.h b/dtool/src/cppparser/cppFunctionType.h index 021aeba5ce..b728fa7b22 100644 --- a/dtool/src/cppparser/cppFunctionType.h +++ b/dtool/src/cppparser/cppFunctionType.h @@ -36,6 +36,7 @@ public: F_method_pointer = 0x10, F_unary_op = 0x20, F_operator = 0x40, + F_noexcept = 0x80, }; CPPFunctionType(CPPType *return_type, CPPParameterList *parameters, diff --git a/dtool/src/cppparser/cppInstanceIdentifier.cxx b/dtool/src/cppparser/cppInstanceIdentifier.cxx index 8db68d389d..7cd3c67283 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.cxx +++ b/dtool/src/cppparser/cppInstanceIdentifier.cxx @@ -133,7 +133,7 @@ add_func_modifier(CPPParameterList *params, int flags) { // function, check if the parameter list is empty. If it is, this // is really a unary operator, so set the unary_op flag. Operators // () and [] are never considered unary operators. - if (_ident != NULL && + if (_ident != NULL && _ident->get_simple_name().substr(0, 9) == "operator ") { if (_ident->get_simple_name() != string("operator ()") && @@ -245,7 +245,13 @@ r_unroll_type(CPPType *start_type, break; case IIT_reference: - result = new CPPReferenceType(r_unroll_type(start_type, mi)); + result = new CPPReferenceType(r_unroll_type(start_type, mi), + CPPReferenceType::VC_lvalue); + break; + + case IIT_rvalue_reference: + result = new CPPReferenceType(r_unroll_type(start_type, mi), + CPPReferenceType::VC_rvalue); break; case IIT_scoped_pointer: diff --git a/dtool/src/cppparser/cppInstanceIdentifier.h b/dtool/src/cppparser/cppInstanceIdentifier.h index 7662292c12..b906a4f386 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.h +++ b/dtool/src/cppparser/cppInstanceIdentifier.h @@ -32,6 +32,7 @@ class CPPPreprocessor; enum CPPInstanceIdentifierType { IIT_pointer, IIT_reference, + IIT_rvalue_reference, IIT_scoped_pointer, IIT_array, IIT_const, diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 0911921510..591f856da6 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -2035,6 +2035,7 @@ check_keyword(const string &name) { if (name == "__make_seq") return KW_MAKE_SEQ; if (name == "mutable") return KW_MUTABLE; if (name == "namespace") return KW_NAMESPACE; + if (name == "noexcept") return KW_NOEXCEPT; if (name == "new") return KW_NEW; if (name == "operator") return KW_OPERATOR; if (name == "private") return KW_PRIVATE; diff --git a/dtool/src/cppparser/cppReferenceType.cxx b/dtool/src/cppparser/cppReferenceType.cxx index 7438dfe89f..40d6e987da 100644 --- a/dtool/src/cppparser/cppReferenceType.cxx +++ b/dtool/src/cppparser/cppReferenceType.cxx @@ -21,9 +21,10 @@ // Description: //////////////////////////////////////////////////////////////////// CPPReferenceType:: -CPPReferenceType(CPPType *pointing_at) : +CPPReferenceType(CPPType *pointing_at, ValueCategory vcat) : CPPType(CPPFile()), - _pointing_at(pointing_at) + _pointing_at(pointing_at), + _value_category(vcat) { } @@ -146,8 +147,14 @@ void CPPReferenceType:: output_instance(ostream &out, int indent_level, CPPScope *scope, bool complete, const string &prename, const string &name) const { - _pointing_at->output_instance(out, indent_level, scope, complete, - "&" + prename, name); + + if (_value_category == VC_rvalue) { + _pointing_at->output_instance(out, indent_level, scope, complete, + "&&" + prename, name); + } else { + _pointing_at->output_instance(out, indent_level, scope, complete, + "&" + prename, name); + } } //////////////////////////////////////////////////////////////////// @@ -182,7 +189,8 @@ is_equal(const CPPDeclaration *other) const { const CPPReferenceType *ot = ((CPPDeclaration *)other)->as_reference_type(); assert(ot != NULL); - return _pointing_at == ot->_pointing_at; + return (_pointing_at == ot->_pointing_at) && + (_value_category == ot->_value_category); } @@ -198,5 +206,9 @@ is_less(const CPPDeclaration *other) const { const CPPReferenceType *ot = ((CPPDeclaration *)other)->as_reference_type(); assert(ot != NULL); + if (_value_category != ot->_value_category) { + return (_value_category < ot->_value_category); + } + return _pointing_at < ot->_pointing_at; } diff --git a/dtool/src/cppparser/cppReferenceType.h b/dtool/src/cppparser/cppReferenceType.h index 300db0035c..3bf292841e 100644 --- a/dtool/src/cppparser/cppReferenceType.h +++ b/dtool/src/cppparser/cppReferenceType.h @@ -21,13 +21,22 @@ /////////////////////////////////////////////////////////////////// // Class : CPPReferenceType -// Description : +// Description : Either an lvalue- or rvalue-reference. //////////////////////////////////////////////////////////////////// class CPPReferenceType : public CPPType { public: - CPPReferenceType(CPPType *pointing_at); + enum ValueCategory { + VC_lvalue, + VC_rvalue + }; + + CPPReferenceType(CPPType *pointing_at, ValueCategory vcat=VC_lvalue); CPPType *_pointing_at; + ValueCategory _value_category; + + inline bool is_lvalue() const; + inline bool is_rvalue() const; virtual bool is_fully_specified() const; virtual CPPDeclaration *substitute_decl(SubstDecl &subst,