Преглед на файлове

Support noexcept and rvalue references in C++ parser

rdb преди 11 години
родител
ревизия
368e1ca644

+ 68 - 43
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));
 }

+ 3 - 0
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";
+  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
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,

+ 8 - 2
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:

+ 1 - 0
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,

+ 1 - 0
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;

+ 17 - 5
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;
 }

+ 11 - 2
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,