diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 425bf7c7f23d..00e9ca07cf81 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2012-06-27 Jason Merrill + * parser.c (cp_parser_check_for_invalid_template_id): tag_type parm. + (cp_parser_simple_type_specifier, cp_parser_class_head): Adjust. + (cp_parser_elaborated_type_specifier): Adjust. + * decl.c (duplicate_decls): Return error_mark_node on template + mismatch. + PR c++/53563 * parser.c (cp_parser_template_id): Add tag_type parm. (cp_parser_template_name): Likewise. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1346f924c2bb..ab560199cedd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1463,6 +1463,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) { error ("declaration of template %q#D", newdecl); error ("conflicts with previous declaration %q+#D", olddecl); + return error_mark_node; } else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7012caa2e6ae..027a7b9d07af 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2278,7 +2278,7 @@ static bool cp_parser_check_type_definition static void cp_parser_check_for_definition_in_return_type (cp_declarator *, tree, location_t type_location); static void cp_parser_check_for_invalid_template_id - (cp_parser *, tree, location_t location); + (cp_parser *, tree, enum tag_types, location_t location); static bool cp_parser_non_integral_constant_expression (cp_parser *, non_integral_constant); static void cp_parser_diagnose_invalid_type_name @@ -2551,7 +2551,9 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, static void cp_parser_check_for_invalid_template_id (cp_parser* parser, - tree type, location_t location) + tree type, + enum tag_types tag_type, + location_t location) { cp_token_position start = 0; @@ -2560,7 +2562,12 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser, if (TYPE_P (type)) error_at (location, "%qT is not a template", type); else if (TREE_CODE (type) == IDENTIFIER_NODE) - error_at (location, "%qE is not a template", type); + { + if (tag_type != none_type) + error_at (location, "%qE is not a class template", type); + else + error_at (location, "%qE is not a template", type); + } else error_at (location, "invalid template-id"); /* Remember the location of the invalid "<". */ @@ -13668,7 +13675,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, /* There is no valid C++ program where a non-template type is followed by a "<". That usually indicates that the user thought that the type was a template. */ - cp_parser_check_for_invalid_template_id (parser, type, token->location); + cp_parser_check_for_invalid_template_id (parser, type, none_type, + token->location); return TYPE_NAME (type); } @@ -13770,6 +13778,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, followed by a "<". That usually indicates that the user thought that the type was a template. */ cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type), + none_type, token->location); } @@ -14273,7 +14282,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /* A "<" cannot follow an elaborated type specifier. If that happens, the user was probably trying to form a template-id. */ - cp_parser_check_for_invalid_template_id (parser, type, token->location); + cp_parser_check_for_invalid_template_id (parser, type, tag_type, + token->location); return type; } @@ -18429,6 +18439,7 @@ cp_parser_class_head (cp_parser* parser, if (id) { cp_parser_check_for_invalid_template_id (parser, id, + class_key, type_start_token->location); } virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ebba545cf3ab..4217e6a6675f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2012-06-27 Jason Merrill + * g++.dg/cpp0x/override2.C: Adjust. + * g++.dg/template/error5.C: Adjust. + * g++.dg/parse/crash28.C: Adjust. + PR c++/53563 * g++.dg/parse/template27.C: New. * g++.dg/template/crash74.C: Adjust expected output. diff --git a/gcc/testsuite/g++.dg/cpp0x/override2.C b/gcc/testsuite/g++.dg/cpp0x/override2.C index 0d8871d6ae29..4d5a412baf5e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/override2.C +++ b/gcc/testsuite/g++.dg/cpp0x/override2.C @@ -18,7 +18,7 @@ template struct B4 final {}; template struct B5 final {}; -struct undeclared final { }; // { dg-error "not a template" } +struct undeclared final { }; // { dg-error "not a class template" } struct D5 : B3 {}; diff --git a/gcc/testsuite/g++.dg/parse/crash28.C b/gcc/testsuite/g++.dg/parse/crash28.C index 67d78d6bb7f5..68a975915cbc 100644 --- a/gcc/testsuite/g++.dg/parse/crash28.C +++ b/gcc/testsuite/g++.dg/parse/crash28.C @@ -5,10 +5,10 @@ // Origin:Andrew Pinski // Volker Reichelt -template class insert_iterator > {}; // { dg-error "not a template|not declared in this scope|expected unqualified-id|extra" } +template class insert_iterator > {}; // { dg-error "not a class template|not declared in this scope|expected unqualified-id|extra" } template class insert_iterator { // { dg-error "template" } hash_set<_Value>; }; -template struct A > {}; // { dg-error "not a template|not declared in this scope|expected unqualified-id|extra" } +template struct A > {}; // { dg-error "not a class template|not declared in this scope|expected unqualified-id|extra" } struct A {}; diff --git a/gcc/testsuite/g++.dg/template/error5.C b/gcc/testsuite/g++.dg/template/error5.C index 0c793509da40..72d3c29b8fd5 100644 --- a/gcc/testsuite/g++.dg/template/error5.C +++ b/gcc/testsuite/g++.dg/template/error5.C @@ -1,6 +1,6 @@ template -struct X { // { dg-error "not a template" } +struct X { // { dg-error "not a class template" } typedef int Y; }; -extern struct Z s; // { dg-error "not a template" } +extern struct Z s; // { dg-error "not a class template" }