OSDN Git Service

* parser.c (cp_parser_context_free_list): New variable.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 31 Dec 2002 00:11:47 +0000 (00:11 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 31 Dec 2002 00:11:47 +0000 (00:11 +0000)
(cp_parser_context_new): Use it.
(cp_parser_error): Check return code from
cp_parser_simulate_error.
(cp_parser_simulate_error): Return a value.
(cp_parser_id_expression): Optimize common case.
(cp_parser_class_name): Likewise.
(cp_parser_class_specifier): Adjust call to
cp_parser_late_parsing_default_args.
(cp_parser_lookup_name): Optimize common case.
(cp_parser_late_parsing_for_member): Adjust call to
cp_parser_late_parsing_default_args.
(cp_parser_late_parsing_default_args): Add scope parameter.
(cp_parser_require): Avoid creating the error message unless it's
needed.
(cp_parser_parse_definitely): Place free'd contexts on the free
list.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60665 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/parser.c

index db212ba..fd3af09 100644 (file)
@@ -1,5 +1,23 @@
 2002-12-30  Mark Mitchell  <mark@codesourcery.com>
 
+       * parser.c (cp_parser_context_free_list): New variable.
+       (cp_parser_context_new): Use it.
+       (cp_parser_error): Check return code from
+       cp_parser_simulate_error.
+       (cp_parser_simulate_error): Return a value.
+       (cp_parser_id_expression): Optimize common case.
+       (cp_parser_class_name): Likewise.
+       (cp_parser_class_specifier): Adjust call to
+       cp_parser_late_parsing_default_args.
+       (cp_parser_lookup_name): Optimize common case.
+       (cp_parser_late_parsing_for_member): Adjust call to
+       cp_parser_late_parsing_default_args.
+       (cp_parser_late_parsing_default_args): Add scope parameter.
+       (cp_parser_require): Avoid creating the error message unless it's
+       needed.
+       (cp_parser_parse_definitely): Place free'd contexts on the free
+       list.
+
        * parser.c (cp_parser_declaration_seq_opt): Handle pending_lang_change.
 
 2002-12-30  David Edelsohn  <edelsohn@gnu.org>
index cb8dbe9..6c40d9d 100644 (file)
@@ -1196,6 +1196,10 @@ typedef struct cp_parser_context GTY (())
 static cp_parser_context *cp_parser_context_new
   PARAMS ((cp_parser_context *));
 
+/* Class variables.  */
+
+static GTY(()) cp_parser_context* cp_parser_context_free_list;
+
 /* Constructors and destructors.  */
 
 /* Construct a new context.  The context below this one on the stack
@@ -1208,8 +1212,16 @@ cp_parser_context_new (next)
   cp_parser_context *context;
 
   /* Allocate the storage.  */
-  context = ((cp_parser_context *) 
-            ggc_alloc_cleared (sizeof (cp_parser_context)));
+  if (cp_parser_context_free_list != NULL)
+    {
+      /* Pull the first entry from the free list.  */
+      context = cp_parser_context_free_list;
+      cp_parser_context_free_list = context->next;
+      memset ((char *)context, 0, sizeof (*context));
+    }
+  else
+    context = ((cp_parser_context *) 
+              ggc_alloc_cleared (sizeof (cp_parser_context)));
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
   /* If this is not the bottomost context, copy information that we
@@ -1704,7 +1716,7 @@ static tree cp_parser_functional_cast
 static void cp_parser_late_parsing_for_member
   PARAMS ((cp_parser *, tree));
 static void cp_parser_late_parsing_default_args
-  PARAMS ((cp_parser *, tree));
+  (cp_parser *, tree, tree);
 static tree cp_parser_sizeof_operand
   PARAMS ((cp_parser *, enum rid));
 static bool cp_parser_declares_only_class_p
@@ -1741,7 +1753,7 @@ static bool cp_parser_committed_to_tentative_parse
   PARAMS ((cp_parser *));
 static void cp_parser_error
   PARAMS ((cp_parser *, const char *));
-static void cp_parser_simulate_error
+static bool cp_parser_simulate_error
   PARAMS ((cp_parser *));
 static void cp_parser_check_type_definition
   PARAMS ((cp_parser *));
@@ -2213,24 +2225,26 @@ cp_parser_error (parser, message)
      cp_parser *parser;
      const char *message;
 {
-  /* Remember that we have issued an error.  */
-  cp_parser_simulate_error (parser);
   /* Output the MESSAGE -- unless we're parsing tentatively.  */
-  if (!cp_parser_parsing_tentatively (parser) 
-      || cp_parser_committed_to_tentative_parse (parser))
+  if (!cp_parser_simulate_error (parser))
     error (message);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
-   during this tentative parse.  */
+   during this tentative parse.  Returns true if the error was
+   simulated; false if a messgae should be issued by the caller.  */
 
-static void
+static bool
 cp_parser_simulate_error (parser)
      cp_parser *parser;
 {
   if (cp_parser_parsing_tentatively (parser)
       && !cp_parser_committed_to_tentative_parse (parser))
-    parser->context->status = CP_PARSER_STATUS_KIND_ERROR;
+    {
+      parser->context->status = CP_PARSER_STATUS_KIND_ERROR;
+      return true;
+    }
+  return false;
 }
 
 /* This function is called when a type is defined.  If type
@@ -3117,8 +3131,16 @@ cp_parser_id_expression (cp_parser *parser,
       cp_token *token;
       tree id;
 
-      /* We don't know yet whether or not this will be a 
-        template-id.  */
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+
+      /* If it's an identifier, and the next token is not a "<", then
+        we can avoid the template-id case.  This is an optimization
+        for this common case.  */
+      if (token->type == CPP_NAME 
+         && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
+       return cp_parser_identifier (parser);
+
       cp_parser_parse_tentatively (parser);
       /* Try a template-id.  */
       id = cp_parser_template_id (parser, 
@@ -3128,7 +3150,8 @@ cp_parser_id_expression (cp_parser *parser,
       if (cp_parser_parse_definitely (parser))
        return id;
 
-      /* Peek at the next token.  */
+      /* Peek at the next token.  (Changes in the token buffer may
+        have invalidated the pointer obtained above.)  */
       token = cp_lexer_peek_token (parser->lexer);
 
       switch (token->type)
@@ -11331,7 +11354,16 @@ cp_parser_class_name (cp_parser *parser,
   tree decl;
   tree scope;
   bool typename_p;
-  
+  cp_token *token;
+
+  /* All class-names start with an identifier.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
+    {
+      cp_parser_error (parser, "expected class-name");
+      return error_mark_node;
+    }
+    
   /* PARSER->SCOPE can be cleared when parsing the template-arguments
      to a template-id, so we save it here.  */
   scope = parser->scope;
@@ -11339,21 +11371,11 @@ cp_parser_class_name (cp_parser *parser,
      in a qualified name where the enclosing scope is type-dependent.  */
   typename_p = (typename_keyword_p && scope && TYPE_P (scope)
                && cp_parser_dependent_type_p (scope));
-
-  /* We don't know whether what comes next is a template-id or 
-     not.  */
-  cp_parser_parse_tentatively (parser);
-  /* Try a template-id.  */
-  decl = cp_parser_template_id (parser, template_keyword_p,
-                               check_dependency_p);
-  if (cp_parser_parse_definitely (parser))
-    {
-      if (decl == error_mark_node)
-       return error_mark_node;
-    }
-  else
+  /* Handle the common case (an identifier, but not a template-id)
+     efficiently.  */
+  if (token->type == CPP_NAME 
+      && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
     {
-      /* If it wasn't a template-id, try a simple identifier.  */
       tree identifier;
 
       /* Look for the identifier.  */
@@ -11385,6 +11407,14 @@ cp_parser_class_name (cp_parser *parser,
                                        check_dependency_p);
        }
     }
+  else
+    {
+      /* Try a template-id.  */
+      decl = cp_parser_template_id (parser, template_keyword_p,
+                                   check_dependency_p);
+      if (decl == error_mark_node)
+       return error_mark_node;
+    }
 
   decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
 
@@ -11515,7 +11545,7 @@ cp_parser_class_specifier (parser)
           parser->default_arg_types;
           parser->default_arg_types = TREE_CHAIN (parser->default_arg_types))
        cp_parser_late_parsing_default_args
-         (parser, TREE_PURPOSE (parser->default_arg_types));
+         (parser, TREE_PURPOSE (parser->default_arg_types), NULL_TREE);
       
       /* Reverse the queue, so that we process it in the order the
         functions were declared.  */
@@ -13392,9 +13422,7 @@ cp_parser_lookup_name (parser, name, check_access, is_type,
     {
       /* The error message we have to print is too complicated for
         cp_parser_error, so we incorporate its actions directly.  */
-      cp_parser_simulate_error (parser);
-      if (!cp_parser_parsing_tentatively (parser)
-         || cp_parser_committed_to_tentative_parse (parser))
+      if (!cp_parser_simulate_error (parser))
        {
          error ("reference to `%D' is ambiguous", name);
          print_candidates (decl);
@@ -14216,11 +14244,10 @@ cp_parser_late_parsing_for_member (parser, member_function)
 
   /* If there are default arguments that have not yet been processed,
      take care of them now.  */
-  if (DECL_FUNCTION_MEMBER_P (member_function))
-    push_nested_class (DECL_CONTEXT (member_function), 1);
-  cp_parser_late_parsing_default_args (parser, TREE_TYPE (member_function));
-  if (DECL_FUNCTION_MEMBER_P (member_function))
-    pop_nested_class ();
+  cp_parser_late_parsing_default_args (parser, TREE_TYPE (member_function),
+                                      DECL_FUNCTION_MEMBER_P (member_function)
+                                      ? DECL_CONTEXT (member_function)
+                                      : NULL_TREE);
 
   /* If the body of the function has not yet been parsed, parse it
      now.  */
@@ -14276,12 +14303,12 @@ cp_parser_late_parsing_for_member (parser, member_function)
 }
 
 /* TYPE is a FUNCTION_TYPE or METHOD_TYPE which contains a parameter
-   with an unparsed DEFAULT_ARG.  Parse those default args now.  */
+   with an unparsed DEFAULT_ARG.  If non-NULL, SCOPE is the class in
+   whose context name lookups in the default argument should occur.
+   Parse the default args now.  */
 
 static void
-cp_parser_late_parsing_default_args (parser, type)
-     cp_parser *parser;
-     tree type;
+cp_parser_late_parsing_default_args (cp_parser *parser, tree type, tree scope)
 {
   cp_lexer *saved_lexer;
   cp_token_cache *tokens;
@@ -14312,7 +14339,11 @@ cp_parser_late_parsing_default_args (parser, type)
       saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
       parser->local_variables_forbidden_p = true;
        /* Parse the assignment-expression.  */
+      if (scope)
+       push_nested_class (scope, 1);
       TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
+      if (scope)
+       pop_nested_class ();
 
        /* Restore saved state.  */
       parser->lexer = saved_lexer;
@@ -14450,14 +14481,9 @@ cp_parser_require (parser, type, token_desc)
     return cp_lexer_consume_token (parser->lexer);
   else
     {
-      dyn_string_t error_msg;
-
-      /* Format the error message.  */
-      error_msg = dyn_string_new (0);
-      dyn_string_append_cstr (error_msg, "expected ");
-      dyn_string_append_cstr (error_msg, token_desc);
-      cp_parser_error (parser, error_msg->s);
-      dyn_string_delete (error_msg);
+      /* Output the MESSAGE -- unless we're parsing tentatively.  */
+      if (!cp_parser_simulate_error (parser))
+       error ("expected %s", token_desc);
       return NULL;
     }
 }
@@ -14759,15 +14785,16 @@ cp_parser_parse_definitely (parser)
        parser->context->deferred_access_checks 
          = chainon (parser->context->deferred_access_checks,
                     context->deferred_access_checks);
-      return true;
     }
   /* Otherwise, if errors occurred, roll back our state so that things
      are just as they were before we began the tentative parse.  */
   else
-    {
-      cp_lexer_rollback_tokens (parser->lexer);
-      return false;
-    }
+    cp_lexer_rollback_tokens (parser->lexer);
+  /* Add the context to the front of the free list.  */
+  context->next = cp_parser_context_free_list;
+  cp_parser_context_free_list = context;
+
+  return !error_occurred;
 }
 
 /* Returns non-zero if we are parsing tentatively.  */