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
This commit is contained in:
Mark Mitchell 2004-12-15 00:42:33 +00:00 committed by Mark Mitchell
parent a150cb057b
commit 0c88d88668
6 changed files with 48 additions and 22 deletions

View File

@ -1,3 +1,15 @@
2004-12-14 Mark Mitchell <mark@codesourcery.com>
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 <pinskia@physics.uc.edu>
PR c++/18965

View File

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

View File

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

View File

@ -1,3 +1,9 @@
2004-12-14 Mark Mitchell <mark@codesourcery.com>
PR c++/18738
* g++.dg/template/typename8.C: New test.
* g++.dg/parse/friend2.C: Tweak error message.
2004-12-14 Andrew Pinski <pinskia@physics.uc.edu>
* gcc.c-torture/20041214-1.c: New test.

View File

@ -10,7 +10,7 @@ namespace NS {
}
template <class T> class X {
friend class NS::C; // { dg-error "expected|friend" }
friend class NS::C; // { dg-error "template|friend" }
};
X<int> c;

View File

@ -0,0 +1,10 @@
// PR c++/18738
namespace foo {
typedef int my_type;
}
template<typename T>
struct A {
typename foo::my_type bar();
};