OSDN Git Service

gcc/cp/
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index eacf5e9..4dec792 100644 (file)
@@ -1732,6 +1732,10 @@ static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
+static tree cp_parser_template_type_arg
+  (cp_parser *);
+static tree cp_parser_type_id_1
+  (cp_parser *, bool);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
@@ -1909,7 +1913,7 @@ static tree cp_parser_maybe_treat_template_as_class
 static bool cp_parser_check_declarator_template_parameters
   (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned, location_t);
+  (cp_parser *, unsigned, location_t, cp_declarator *);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -2619,6 +2623,8 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
          /* Stop if this is an unnested '}', or closes the outermost
             nesting level.  */
          nesting_depth--;
+         if (nesting_depth < 0)
+           return;
          if (!nesting_depth)
            nesting_depth = -1;
          break;
@@ -5772,7 +5778,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
        new_declarator = NULL;
     }
 
-  type = groktypename (&type_specifier_seq, new_declarator);
+  type = groktypename (&type_specifier_seq, new_declarator, false);
   return type;
 }
 
@@ -10544,7 +10550,7 @@ cp_parser_template_argument (cp_parser* parser)
 
      Therefore, we try a type-id first.  */
   cp_parser_parse_tentatively (parser);
-  argument = cp_parser_type_id (parser);
+  argument = cp_parser_template_type_arg (parser);
   /* If there was no error parsing the type-id but the next token is a
      '>>', our behavior depends on which dialect of C++ we're
      parsing. In C++98, we probably found a typo for '> >'. But there
@@ -10732,7 +10738,7 @@ cp_parser_template_argument (cp_parser* parser)
      was the only alternative that matched (albeit with a '>' after
      it). We can assume it's just a typo from the user, and a
      diagnostic will then be issued.  */
-  return cp_parser_type_id (parser);
+  return cp_parser_template_type_arg (parser);
 }
 
 /* Parse an explicit-instantiation.
@@ -11761,7 +11767,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
             there were no qualifying templates.  */
          if (!cp_parser_check_template_parameters (parser,
                                                    /*num_templates=*/0,
-                                                   token->location))
+                                                   token->location,
+                                                   /*declarator=*/NULL))
            return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
@@ -12007,6 +12014,11 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
   else
     value = NULL_TREE;
 
+  /* If we are processing a template, make sure the initializer of the
+     enumerator doesn't contain any bare template parameter pack.  */
+  if (check_for_bare_parameter_packs (value))
+    value = error_mark_node;
+
   /* Create the enumerator.  */
   build_enumerator (identifier, value, type);
 }
@@ -13766,7 +13778,7 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
    Returns the TYPE specified.  */
 
 static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
 {
   cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *abstract_declarator;
@@ -13795,7 +13807,18 @@ cp_parser_type_id (cp_parser* parser)
       return error_mark_node;
     }
   
-  return groktypename (&type_specifier_seq, abstract_declarator);
+  return groktypename (&type_specifier_seq, abstract_declarator,
+                      is_template_arg);
+}
+
+static tree cp_parser_type_id (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, false);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, true);
 }
 
 /* Parse a type-specifier-seq.
@@ -14927,10 +14950,8 @@ cp_parser_class_name (cp_parser *parser,
 static tree
 cp_parser_class_specifier (cp_parser* parser)
 {
-  cp_token *token;
   tree type;
   tree attributes = NULL_TREE;
-  int has_trailing_semicolon;
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
   bool saved_in_function_body;
@@ -15008,10 +15029,6 @@ cp_parser_class_specifier (cp_parser* parser)
 
   /* Look for the trailing `}'.  */
   cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
-  /* We get better error messages by noticing a common problem: a
-     missing trailing `;'.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  has_trailing_semicolon = (token->type == CPP_SEMICOLON);
   /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     attributes = cp_parser_attributes_opt (parser);
@@ -15382,7 +15399,8 @@ cp_parser_class_head (cp_parser* parser,
   /* Make sure that the right number of template parameters were
      present.  */
   if (!cp_parser_check_template_parameters (parser, num_templates,
-                                           type_start_token->location))
+                                           type_start_token->location,
+                                           /*declarator=*/NULL))
     {
       /* If something went wrong, there is no point in even trying to
         process the class-definition.  */
@@ -17291,9 +17309,9 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
           additional level of template parameters.  */
        ++num_templates;
 
-      return cp_parser_check_template_parameters (parser,
-                                                 num_templates,
-                                                 declarator_location);
+      return cp_parser_check_template_parameters 
+       (parser, num_templates, declarator_location, declarator);
+
 
     case cdk_function:
     case cdk_array:
@@ -17314,30 +17332,38 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 /* NUM_TEMPLATES were used in the current declaration.  If that is
    invalid, return FALSE and issue an error messages.  Otherwise,
-   return TRUE.  */
+   return TRUE.  If DECLARATOR is non-NULL, then we are checking a
+   declarator and we can print more accurate diagnostics.  */
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
                                     unsigned num_templates,
-                                    location_t location)
+                                    location_t location,
+                                    cp_declarator *declarator)
 {
+  /* If there are the same number of template classes and parameter
+     lists, that's OK.  */
+  if (parser->num_template_parameter_lists == num_templates)
+    return true;
+  /* If there are more, but only one more, then we are referring to a
+     member template.  That's OK too.  */
+  if (parser->num_template_parameter_lists == num_templates + 1)
+    return true;
   /* If there are more template classes than parameter lists, we have
      something like:
 
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("%Htoo few template-parameter-lists", &location);
+      if (declarator)
+       error_at (location, "specializing member %<%T::%E%> "
+                 "requires %<template<>%> syntax", 
+                 declarator->u.id.qualifying_scope,
+                 declarator->u.id.unqualified_name);
+      else 
+       error_at (location, "too few template-parameter-lists");
       return false;
     }
-  /* If there are the same number of template classes and parameter
-     lists, that's OK.  */
-  if (parser->num_template_parameter_lists == num_templates)
-    return true;
-  /* If there are more, but only one more, then we are referring to a
-     member template.  That's OK too.  */
-  if (parser->num_template_parameter_lists == num_templates + 1)
-      return true;
   /* Otherwise, there are too many template parameter lists.  We have
      something like: