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
This commit is contained in:
Jason Merrill 2009-11-06 16:18:42 -05:00 committed by Jason Merrill
parent 3c3905fc17
commit e1faa105c1
8 changed files with 73 additions and 11 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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:

View File

@ -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;

View File

@ -1,5 +1,9 @@
2009-11-06 Jason Merrill <jason@redhat.com>
PR c++/15946
* g++.dg/parse/error36.C: New.
* g++.old-deja/g++.other/typename1.C: Adjust.
PR c++/9381
* g++.dg/abi/regparm1.C: New.

View File

@ -0,0 +1,17 @@
// Test for helpful error message about missing typename.
template <class T> struct A { typedef T foo; typedef T bar; };
template <class T>
void f(T t)
{
typedef A<T>::foo type; // { dg-error "typename" }
A<T>::bar b; // { dg-error "typename" }
} // { dg-error "expected ';'" "" { target *-*-* } 8 }
template <class T> struct B
{
void f()
{
A<T>::baz z; // { dg-error "typename" }
} // { dg-error "expected ';'" "" { target *-*-* } 15 }
};

View File

@ -2,4 +2,4 @@
template<typename> struct A;
template<typename T> void foo (A<&T::template i>); // { dg-error "T::template i|mismatch|& T::i" }
template<typename T> void foo (A<&T::template i>); // { dg-error "T:: ?template i|mismatch|& T::i" }

View File

@ -13,5 +13,5 @@ public:
template<class T>
void f()
{
Vector<T>::iterator i = 0; // { dg-error "expected" } missing typename
}
Vector<T>::iterator i = 0; // { dg-error "typename" } missing typename
} // { dg-error "expected" "" { target *-*-* } 16 }