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