OSDN Git Service

PR c++/10771
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Dec 2003 19:05:12 +0000 (19:05 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Dec 2003 19:05:12 +0000 (19:05 +0000)
* parser.c (cp_parser_check_for_invalid_template_id): New
function.
(cp_parser_simple_type_specifier): Use it.
(cp_parser_elaborated_type_specifier): Likewise.
(cp_parser_class_head): Likewise.

PR c++/10771
* g++.dg/template/error5.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/error5.C [new file with mode: 0644]

index 7b7f63a..de5c714 100644 (file)
@@ -1,3 +1,12 @@
+2003-12-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/10771
+       * parser.c (cp_parser_check_for_invalid_template_id): New
+       function.
+       (cp_parser_simple_type_specifier): Use it.
+       (cp_parser_elaborated_type_specifier): Likewise.
+       (cp_parser_class_head): Likewise.
+
 2003-12-02  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
        PR c++/10126\r
index c157173..9ec128c 100644 (file)
@@ -1702,6 +1702,8 @@ static void cp_parser_check_type_definition
   (cp_parser *);
 static void cp_parser_check_for_definition_in_return_type
   (tree, int);
+static void cp_parser_check_for_invalid_template_id
+  (cp_parser *, tree);
 static tree cp_parser_non_constant_expression
   (const char *);
 static bool cp_parser_diagnose_invalid_type_name
@@ -1813,6 +1815,54 @@ cp_parser_check_for_definition_in_return_type (tree declarator,
     error ("new types may not be defined in a return type");
 }
 
+/* A type-specifier (TYPE) has been parsed which cannot be followed by
+   "<" in any valid C++ program.  If the next token is indeed "<",
+   issue a message warning the user about what appears to be an
+   invalid attempt to form a template-id.  */
+
+static void
+cp_parser_check_for_invalid_template_id (cp_parser* parser, 
+                                        tree type)
+{
+  ptrdiff_t start;
+  cp_token *token;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+    {
+      if (TYPE_P (type))
+       error ("`%T' is not a template", type);
+      else if (TREE_CODE (type) == IDENTIFIER_NODE)
+       error ("`%s' is not a template", IDENTIFIER_POINTER (type));
+      else
+       error ("invalid template-id");
+      /* Remember the location of the invalid "<".  */
+      if (cp_parser_parsing_tentatively (parser)
+         && !cp_parser_committed_to_tentative_parse (parser))
+       {
+         token = cp_lexer_peek_token (parser->lexer);
+         token = cp_lexer_prev_token (parser->lexer, token);
+         start = cp_lexer_token_difference (parser->lexer,
+                                            parser->lexer->first_token,
+                                            token);
+       }
+      else
+       start = -1;
+      /* Consume the "<".  */
+      cp_lexer_consume_token (parser->lexer);
+      /* Parse the template arguments.  */
+      cp_parser_enclosed_template_argument_list (parser);
+      /* Permanently remove the invalid template arugments so that
+        this error message is not issued again.  */
+      if (start >= 0)
+       {
+         token = cp_lexer_advance_token (parser->lexer,
+                                         parser->lexer->first_token,
+                                         start);
+         cp_lexer_purge_tokens_after (parser->lexer, token);
+       }
+    }
+}
+
 /* Issue an error message about the fact that THING appeared in a
    constant-expression.  Returns ERROR_MARK_NODE.  */
 
@@ -8520,17 +8570,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
   /* There is no valid C++ program where a non-template type is
      followed by a "<".  That usually indicates that the user thought
      that the type was a template.  */
-  if (type && cp_lexer_next_token_is (parser->lexer, CPP_LESS))
-    {
-      error ("`%T' is not a template", TREE_TYPE (type));
-      /* Consume the "<".  */
-      cp_lexer_consume_token (parser->lexer);
-      /* Parse the template arguments.  */
-      cp_parser_enclosed_template_argument_list (parser);
-      /* Attempt to recover by using the basic type, ignoring the
-        template arguments.  */
-      return type;
-    }
+  if (type)
+    cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
 
   return type;
 }
@@ -8827,6 +8868,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
     }
   if (tag_type != enum_type)
     cp_parser_check_class_key (tag_type, type);
+
+  /* A "<" cannot follow an elaborated type specifier.  If that
+     happens, the user was probably trying to form a template-id.  */
+  cp_parser_check_for_invalid_template_id (parser, type);
+
   return type;
 }
 
@@ -11664,6 +11710,8 @@ cp_parser_class_head (cp_parser* parser,
 
   pop_deferring_access_checks ();
 
+  cp_parser_check_for_invalid_template_id (parser, id);
+
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
      class-specifier.  We have to detect this situation before calling
index bb142e5..b6883f5 100644 (file)
@@ -1,3 +1,8 @@
+2003-12-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/10771
+       * g++.dg/template/error5.C: New test.
+
 2003-12-02  David Ung  <davidu@mips.com>
 
        * gcc.dg/compat/vector-check.h: Corrected type for var 
diff --git a/gcc/testsuite/g++.dg/template/error5.C b/gcc/testsuite/g++.dg/template/error5.C
new file mode 100644 (file)
index 0000000..0c79350
--- /dev/null
@@ -0,0 +1,6 @@
+template <typename T>
+struct X<T*> { // { dg-error "not a template" }
+   typedef int Y;
+};
+
+extern struct Z<int> s; // { dg-error "not a template" }