diff options
author | Jason Merrill <jason@redhat.com> | 2009-11-06 16:18:42 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-11-06 16:18:42 -0500 |
commit | e1faa105c10af6f990e97a137187e04b21addbb7 (patch) | |
tree | 1fe0df5266124ea89ffc21c4d73fd145d1248d5c /gcc | |
parent | 3c3905fc17fbaad4a0a3753fb166161154119e0b (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 6 | ||||
-rw-r--r-- | gcc/cp/error.c | 14 | ||||
-rw-r--r-- | gcc/cp/parser.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/error36.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/error26.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/typename1.C | 4 |
8 files changed, 73 insertions, 11 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index be66e31..77cf10c0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/parse/error36.C b/gcc/testsuite/g++.dg/parse/error36.C new file mode 100644 index 0000000..92101e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/error36.C @@ -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 } +}; diff --git a/gcc/testsuite/g++.dg/template/error26.C b/gcc/testsuite/g++.dg/template/error26.C index 7545762..cd8d46d 100644 --- a/gcc/testsuite/g++.dg/template/error26.C +++ b/gcc/testsuite/g++.dg/template/error26.C @@ -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" } diff --git a/gcc/testsuite/g++.old-deja/g++.other/typename1.C b/gcc/testsuite/g++.old-deja/g++.other/typename1.C index 43d1352..4bf3de3 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/typename1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/typename1.C @@ -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 } |