aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-11-06 16:18:42 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-11-06 16:18:42 -0500
commite1faa105c10af6f990e97a137187e04b21addbb7 (patch)
tree1fe0df5266124ea89ffc21c4d73fd145d1248d5c /gcc/cp
parent3c3905fc17fbaad4a0a3753fb166161154119e0b (diff)
downloadgcc-e1faa105c10af6f990e97a137187e04b21addbb7.zip
gcc-e1faa105c10af6f990e97a137187e04b21addbb7.tar.gz
gcc-e1faa105c10af6f990e97a137187e04b21addbb7.tar.bz2
re PR c++/15946 (Unhelpful error message when "typename" is omitted)
PR c++/15946 * parser.c (cp_parser_check_template_parameters): Don't talk about specialization at function scope. (cp_parser_diagnose_invalid_type_name): Handle dependent scope. (cp_parser_parse_and_diagnose_invalid_type_name): Likewise. (cp_parser_expression_statement): Suggest typename. * error.c (dump_decl) [SCOPE_REF]: Print the type here. (dump_expr) [SCOPE_REF]: Call it. (dump_type) [UNBOUND_CLASS_TEMPLATE]: Check TFF_UNQUALIFIED_NAME. * cxx-pretty-print.c (pp_cxx_unqualified_id): Print class template args. From-SVN: r153978
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/cxx-pretty-print.c6
-rw-r--r--gcc/cp/error.c14
-rw-r--r--gcc/cp/parser.c25
4 files changed, 49 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 36f7255..4db5aac 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,17 @@
2009-11-06 Jason Merrill <jason@redhat.com>
+ PR c++/15946
+ * parser.c (cp_parser_check_template_parameters): Don't talk about
+ specialization at function scope.
+ (cp_parser_diagnose_invalid_type_name): Handle dependent scope.
+ (cp_parser_parse_and_diagnose_invalid_type_name): Likewise.
+ (cp_parser_expression_statement): Suggest typename.
+ * error.c (dump_decl) [SCOPE_REF]: Print the type here.
+ (dump_expr) [SCOPE_REF]: Call it.
+ (dump_type) [UNBOUND_CLASS_TEMPLATE]: Check TFF_UNQUALIFIED_NAME.
+ * cxx-pretty-print.c (pp_cxx_unqualified_id): Print class template
+ args.
+
PR c++/9381
* decl2.c (build_memfn_type): Preserve attributes.
(cp_reconstruct_complex_type): Likewise.
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 1d7f9cf2..4851af9 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -200,6 +200,12 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
case TYPENAME_TYPE:
case UNBOUND_CLASS_TEMPLATE:
pp_cxx_unqualified_id (pp, TYPE_NAME (t));
+ if (CLASS_TYPE_P (t) && CLASSTYPE_USE_TEMPLATE (t))
+ {
+ pp_cxx_begin_template_argument_list (pp);
+ pp_cxx_template_argument_list (pp, CLASSTYPE_TI_ARGS (t));
+ pp_cxx_end_template_argument_list (pp);
+ }
break;
case BIT_NOT_EXPR:
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ce5660f..f423207 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -466,8 +466,11 @@ dump_type (tree t, int flags)
break;
case UNBOUND_CLASS_TEMPLATE:
- dump_type (TYPE_CONTEXT (t), flags);
- pp_cxx_colon_colon (cxx_pp);
+ if (! (flags & TFF_UNQUALIFIED_NAME))
+ {
+ dump_type (TYPE_CONTEXT (t), flags);
+ pp_cxx_colon_colon (cxx_pp);
+ }
pp_cxx_ws_string (cxx_pp, "template");
dump_type (DECL_NAME (TYPE_NAME (t)), flags);
break;
@@ -947,7 +950,9 @@ dump_decl (tree t, int flags)
break;
case SCOPE_REF:
- pp_expression (cxx_pp, t);
+ dump_type (TREE_OPERAND (t, 0), flags);
+ pp_string (cxx_pp, "::");
+ dump_decl (TREE_OPERAND (t, 1), flags|TFF_UNQUALIFIED_NAME);
break;
case ARRAY_REF:
@@ -2219,6 +2224,9 @@ dump_expr (tree t, int flags)
break;
case SCOPE_REF:
+ dump_decl (t, flags);
+ break;
+
case EXPR_PACK_EXPANSION:
case TYPEID_EXPR:
case MEMBER_REF:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1d677cb..47f5f13 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2400,6 +2400,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
error_at (location, "%qE in namespace %qE does not name a type",
id, parser->scope);
+ else if (TYPE_P (parser->scope)
+ && dependent_scope_p (parser->scope))
+ error_at (location, "need %<typename%> before %<%T::%E%> to name "
+ "a type in dependent scope %qT",
+ parser->scope, id, parser->scope);
else if (TYPE_P (parser->scope))
error_at (location, "%qE in class %qT does not name a type",
id, parser->scope);
@@ -2433,11 +2438,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
/*declarator_p=*/true,
/*optional_p=*/false);
/* After the id-expression, there should be a plain identifier,
- otherwise this is not a simple variable declaration. Also, if
- the scope is dependent, we cannot do much. */
+ otherwise this is not a simple variable declaration. */
if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || (parser->scope && TYPE_P (parser->scope)
- && dependent_type_p (parser->scope))
|| TREE_CODE (id) == TYPE_DECL)
{
cp_parser_abort_tentative_parse (parser);
@@ -7760,12 +7762,21 @@ static tree
cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
{
tree statement = NULL_TREE;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* If the next token is a ';', then there is no expression
statement. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ /* Give a helpful message for "A<T>::type t;" */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser)
+ && TREE_CODE (statement) == SCOPE_REF)
+ error_at (token->location, "need %<typename%> before %qE to name "
+ "a type in dependent scope %qT",
+ statement, TREE_OPERAND (statement, 0));
+
/* Consume the final `;'. */
cp_parser_consume_semicolon_at_end_of_statement (parser);
@@ -18197,11 +18208,15 @@ cp_parser_check_template_parameters (cp_parser* parser,
template <class T> void S<T>::R<T>::f (); */
if (parser->num_template_parameter_lists < num_templates)
{
- if (declarator)
+ if (declarator && !current_function_decl)
error_at (location, "specializing member %<%T::%E%> "
"requires %<template<>%> syntax",
declarator->u.id.qualifying_scope,
declarator->u.id.unqualified_name);
+ else if (declarator)
+ error_at (location, "invalid declaration of %<%T::%E%>",
+ declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
else
error_at (location, "too few template-parameter-lists");
return false;