From 0c88d886685d51b8579f29f079d81433ae1e9d31 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Wed, 15 Dec 2004 00:42:33 +0000 Subject: [PATCH] re PR c++/18738 (typename not allowed with non-dependent qualified name) PR c++/18738 * decl.c (make_typename_type): Do not handle namespace-scoped names here. (tag_name): Handle typename_type. (check_elaborated_type_specifier): Handle typenames. * parser.c (cp_parser_diagnose_invalid_type_name): Improve comment. (cp_parser_elaborated_type_specifier): Use cp_parser_diagnose_invalid_type_name. PR c++/18738 * g++.dg/template/typename8.C: New test. * g++.dg/parse/friend2.C: Tweak error message. From-SVN: r92172 --- gcc/cp/ChangeLog | 12 +++++++++++ gcc/cp/decl.c | 25 +++++++++++------------ gcc/cp/parser.c | 15 +++++++------- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/parse/friend2.C | 2 +- gcc/testsuite/g++.dg/template/typename8.C | 10 +++++++++ 6 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/typename8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ef5462859d9..120f9b9cff8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2004-12-14 Mark Mitchell + + PR c++/18738 + * decl.c (make_typename_type): Do not handle namespace-scoped + names here. + (tag_name): Handle typename_type. + (check_elaborated_type_specifier): Handle typenames. + * parser.c (cp_parser_diagnose_invalid_type_name): Improve + comment. + (cp_parser_elaborated_type_specifier): Use + cp_parser_diagnose_invalid_type_name. + 2004-12-14 Andrew Pinski PR c++/18965 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 410f686a3ae..d711899bdaf 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2669,15 +2669,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, return error_mark_node; } gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); - - if (TREE_CODE (context) == NAMESPACE_DECL) - { - /* We can get here from typename_sub0 in the explicit_template_type - expansion. Just fail. */ - if (complain & tf_error) - error ("no class template named %q#T in %q#T", name, context); - return error_mark_node; - } + gcc_assert (TYPE_P (context)); if (!dependent_type_p (context) || currently_open_class (context)) @@ -9048,6 +9040,8 @@ grok_op_properties (tree decl, int friendp, bool complain) return ok; } +/* Return a string giving the keyword associate with CODE. */ + static const char * tag_name (enum tag_types code) { @@ -9058,9 +9052,11 @@ tag_name (enum tag_types code) case class_type: return "class"; case union_type: - return "union "; + return "union"; case enum_type: return "enum"; + case typename_type: + return "typename"; default: gcc_unreachable (); } @@ -9106,7 +9102,8 @@ check_elaborated_type_specifier (enum tag_types tag_code, In other words, the only legitimate declaration to use in the elaborated type specifier is the implicit typedef created when the type is declared. */ - else if (!DECL_IMPLICIT_TYPEDEF_P (decl)) + else if (!DECL_IMPLICIT_TYPEDEF_P (decl) + && tag_code != typename_type) { error ("using typedef-name %qD after %qs", decl, tag_name (tag_code)); cp_error_at ("%qD has a previous declaration here", decl); @@ -9114,14 +9111,16 @@ check_elaborated_type_specifier (enum tag_types tag_code, } else if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE - && tag_code != enum_type) + && tag_code != enum_type + && tag_code != typename_type) { error ("%qT referred to as %qs", type, tag_name (tag_code)); cp_error_at ("%qT has a previous declaration here", type); return error_mark_node; } else if (TREE_CODE (type) != ENUMERAL_TYPE - && tag_code == enum_type) + && tag_code == enum_type + && tag_code != typename_type) { error ("%qT referred to as enum", type); cp_error_at ("%qT has a previous declaration here", type); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9d3696ff17f..13578f0e713 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1939,9 +1939,8 @@ cp_parser_non_integral_constant_expression (cp_parser *parser, return false; } -/* Emit a diagnostic for an invalid type name. Consider also if it is - qualified or not and the result of a lookup, to provide a better - message. */ +/* Emit a diagnostic for an invalid type name. SCOPE is the + qualifying scope (or NULL, if none) for ID. */ static void cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) @@ -9647,7 +9646,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, } /* For a `typename', we needn't call xref_tag. */ - if (tag_type == typename_type) + if (tag_type == typename_type + && TREE_CODE (parser->scope) != NAMESPACE_DECL) return cp_parser_make_typename_type (parser, parser->scope, identifier); /* Look up a qualified name in the usual way. */ @@ -9655,9 +9655,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, { tree decl; - /* In an elaborated-type-specifier, names are assumed to name - types, so we set IS_TYPE to TRUE when calling - cp_parser_lookup_name. */ decl = cp_parser_lookup_name (parser, identifier, tag_type, /*is_template=*/false, @@ -9692,7 +9689,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (TREE_CODE (decl) != TYPE_DECL) { - error ("expected type-name"); + cp_parser_diagnose_invalid_type_name (parser, + parser->scope, + identifier); return error_mark_node; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f58377f0155..ec5facc72ac 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-12-14 Mark Mitchell + + PR c++/18738 + * g++.dg/template/typename8.C: New test. + * g++.dg/parse/friend2.C: Tweak error message. + 2004-12-14 Andrew Pinski * gcc.c-torture/20041214-1.c: New test. diff --git a/gcc/testsuite/g++.dg/parse/friend2.C b/gcc/testsuite/g++.dg/parse/friend2.C index 2e88845cceb..1a2ad8bfad9 100644 --- a/gcc/testsuite/g++.dg/parse/friend2.C +++ b/gcc/testsuite/g++.dg/parse/friend2.C @@ -10,7 +10,7 @@ namespace NS { } template class X { - friend class NS::C; // { dg-error "expected|friend" } + friend class NS::C; // { dg-error "template|friend" } }; X c; diff --git a/gcc/testsuite/g++.dg/template/typename8.C b/gcc/testsuite/g++.dg/template/typename8.C new file mode 100644 index 00000000000..85f585d944a --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typename8.C @@ -0,0 +1,10 @@ +// PR c++/18738 + +namespace foo { + typedef int my_type; +} + +template +struct A { + typename foo::my_type bar(); +}; -- 2.30.2