C++ PATCH: PR 12762

Mark Mitchell mark@codesourcery.com
Fri Nov 14 18:51:00 GMT 2003


This patch fixes an error message regression in GCC 3.4.

For:

  template <typename> struct A { A() {}};
  typedef A<int> Ac;
  Ac<double> a; // { dg-error "template" }

 we now say:

  `Ac' is not a template

which is better than 3.3 in that we do not then go on to say:

  ISO C++ forbids declaration of `a' with no type

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2003-11-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/12762
	* parser.c (cp_parser_enclosed_template_argument_list): New
	function.
	(cp_parser_template_id): Use it.
	(cp_parser_simple_type_specifier): Recognize invalid template
	syntax.

2003-11-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/12762
	* g++.dg/template/error3.C: New test.

Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.120
diff -c -5 -p -r1.120 parser.c
*** cp/parser.c	12 Nov 2003 19:57:56 -0000	1.120
--- cp/parser.c	14 Nov 2003 18:34:33 -0000
*************** static void cp_parser_template_declarati
*** 1629,1638 ****
--- 1629,1640 ----
    (cp_parser *, bool);
  static tree cp_parser_single_declaration
    (cp_parser *, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
+ static tree cp_parser_enclosed_template_argument_list
+   (cp_parser *);
  static void cp_parser_save_default_args
    (cp_parser *, tree);
  static void cp_parser_late_parsing_for_member
    (cp_parser *, tree);
  static void cp_parser_late_parsing_default_args
*************** cp_parser_template_id (cp_parser *parser
*** 7507,7521 ****
  		       bool template_keyword_p, 
  		       bool check_dependency_p)
  {
    tree template;
    tree arguments;
-   tree saved_scope;
-   tree saved_qualifying_scope;
-   tree saved_object_scope;
    tree template_id;
-   bool saved_greater_than_is_operator_p;
    ptrdiff_t start_of_id;
    tree access_check = NULL_TREE;
    cp_token *next_token;
  
    /* If the next token corresponds to a template-id, there is no need
--- 7509,7519 ----
*************** cp_parser_template_id (cp_parser *parser
*** 7574,7610 ****
      {
        pop_deferring_access_checks ();
        return error_mark_node;
      }
  
!   /* [temp.names]
! 
!      When parsing a template-id, the first non-nested `>' is taken as
!      the end of the template-argument-list rather than a greater-than
!      operator.  */
!   saved_greater_than_is_operator_p 
!     = parser->greater_than_is_operator_p;
!   parser->greater_than_is_operator_p = false;
!   /* Parsing the argument list may modify SCOPE, so we save it
!      here.  */
!   saved_scope = parser->scope;
!   saved_qualifying_scope = parser->qualifying_scope;
!   saved_object_scope = parser->object_scope;
!   /* Parse the template-argument-list itself.  */
!   if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
!     arguments = NULL_TREE;
!   else
!     arguments = cp_parser_template_argument_list (parser);
!   /* Look for the `>' that ends the template-argument-list.  */
!   cp_parser_require (parser, CPP_GREATER, "`>'");
!   /* The `>' token might be a greater-than operator again now.  */
!   parser->greater_than_is_operator_p 
!     = saved_greater_than_is_operator_p;
!   /* Restore the SAVED_SCOPE.  */
!   parser->scope = saved_scope;
!   parser->qualifying_scope = saved_qualifying_scope;
!   parser->object_scope = saved_object_scope;
  
    /* Build a representation of the specialization.  */
    if (TREE_CODE (template) == IDENTIFIER_NODE)
      template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
    else if (DECL_CLASS_TEMPLATE_P (template)
--- 7572,7583 ----
      {
        pop_deferring_access_checks ();
        return error_mark_node;
      }
  
!   /* Parse the arguments.  */
!   arguments = cp_parser_enclosed_template_argument_list (parser);
  
    /* Build a representation of the specialization.  */
    if (TREE_CODE (template) == IDENTIFIER_NODE)
      template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
    else if (DECL_CLASS_TEMPLATE_P (template)
*************** cp_parser_simple_type_specifier (cp_pars
*** 8428,8437 ****
--- 8401,8425 ----
      {
        cp_parser_error (parser, "expected type-name");
        return error_mark_node;
      }
  
+   /* There is no valid C++ program where a non-template type can never
+      be 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;
+     }
+ 
    return type;
  }
  
  /* Parse a type-name.
  
*************** cp_parser_functional_cast (cp_parser* pa
*** 13854,13863 ****
--- 13842,13896 ----
      = cp_parser_parenthesized_expression_list (parser, false,
  					       /*non_constant_p=*/NULL);
  
    return build_functional_cast (type, expression_list);
  }
+ 
+ /* Parse a template-argument-list, as well as the trailing ">" (but
+    not the opening ">").  See cp_parser_template_argument_list for the
+    return value.  */
+ 
+ static tree
+ cp_parser_enclosed_template_argument_list (cp_parser* parser)
+ {
+   tree arguments;
+   tree saved_scope;
+   tree saved_qualifying_scope;
+   tree saved_object_scope;
+   bool saved_greater_than_is_operator_p;
+ 
+   /* [temp.names]
+ 
+      When parsing a template-id, the first non-nested `>' is taken as
+      the end of the template-argument-list rather than a greater-than
+      operator.  */
+   saved_greater_than_is_operator_p 
+     = parser->greater_than_is_operator_p;
+   parser->greater_than_is_operator_p = false;
+   /* Parsing the argument list may modify SCOPE, so we save it
+      here.  */
+   saved_scope = parser->scope;
+   saved_qualifying_scope = parser->qualifying_scope;
+   saved_object_scope = parser->object_scope;
+   /* Parse the template-argument-list itself.  */
+   if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
+     arguments = NULL_TREE;
+   else
+     arguments = cp_parser_template_argument_list (parser);
+   /* Look for the `>' that ends the template-argument-list.  */
+   cp_parser_require (parser, CPP_GREATER, "`>'");
+   /* The `>' token might be a greater-than operator again now.  */
+   parser->greater_than_is_operator_p 
+     = saved_greater_than_is_operator_p;
+   /* Restore the SAVED_SCOPE.  */
+   parser->scope = saved_scope;
+   parser->qualifying_scope = saved_qualifying_scope;
+   parser->object_scope = saved_object_scope;
+ 
+   return arguments;
+ }
+ 
  
  /* MEMBER_FUNCTION is a member function, or a friend.  If default
     arguments, or the body of the function have not yet been parsed,
     parse them now.  */
  
Index: testsuite/g++.dg/template/error3.C
===================================================================
RCS file: testsuite/g++.dg/template/error3.C
diff -N testsuite/g++.dg/template/error3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/error3.C	14 Nov 2003 18:34:34 -0000
***************
*** 0 ****
--- 1,5 ----
+ // PR 12762
+ 
+ template <typename> struct A { A() {}};
+ typedef A<int> Ac;
+ Ac<double> a; // { dg-error "template" }



More information about the Gcc-patches mailing list