Commit 0c88d886 by Mark Mitchell Committed by Mark Mitchell

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
parent a150cb05
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> 2004-12-14 Andrew Pinski <pinskia@physics.uc.edu>
PR c++/18965 PR c++/18965
......
...@@ -2669,15 +2669,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, ...@@ -2669,15 +2669,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
return error_mark_node; return error_mark_node;
} }
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
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;
}
if (!dependent_type_p (context) if (!dependent_type_p (context)
|| currently_open_class (context)) || currently_open_class (context))
...@@ -9048,6 +9040,8 @@ grok_op_properties (tree decl, int friendp, bool complain) ...@@ -9048,6 +9040,8 @@ grok_op_properties (tree decl, int friendp, bool complain)
return ok; return ok;
} }
/* Return a string giving the keyword associate with CODE. */
static const char * static const char *
tag_name (enum tag_types code) tag_name (enum tag_types code)
{ {
...@@ -9058,9 +9052,11 @@ tag_name (enum tag_types code) ...@@ -9058,9 +9052,11 @@ tag_name (enum tag_types code)
case class_type: case class_type:
return "class"; return "class";
case union_type: case union_type:
return "union "; return "union";
case enum_type: case enum_type:
return "enum"; return "enum";
case typename_type:
return "typename";
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -9106,7 +9102,8 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -9106,7 +9102,8 @@ check_elaborated_type_specifier (enum tag_types tag_code,
In other words, the only legitimate declaration to use in the In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when elaborated type specifier is the implicit typedef created when
the type is declared. */ 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)); error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
cp_error_at ("%qD has a previous declaration here", decl); cp_error_at ("%qD has a previous declaration here", decl);
...@@ -9114,14 +9111,16 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -9114,14 +9111,16 @@ check_elaborated_type_specifier (enum tag_types tag_code,
} }
else if (TREE_CODE (type) != RECORD_TYPE else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_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)); error ("%qT referred to as %qs", type, tag_name (tag_code));
cp_error_at ("%qT has a previous declaration here", type); cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node; return error_mark_node;
} }
else if (TREE_CODE (type) != ENUMERAL_TYPE 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); error ("%qT referred to as enum", type);
cp_error_at ("%qT has a previous declaration here", type); cp_error_at ("%qT has a previous declaration here", type);
......
...@@ -1939,9 +1939,8 @@ cp_parser_non_integral_constant_expression (cp_parser *parser, ...@@ -1939,9 +1939,8 @@ cp_parser_non_integral_constant_expression (cp_parser *parser,
return false; return false;
} }
/* Emit a diagnostic for an invalid type name. Consider also if it is /* Emit a diagnostic for an invalid type name. SCOPE is the
qualified or not and the result of a lookup, to provide a better qualifying scope (or NULL, if none) for ID. */
message. */
static void static void
cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) 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, ...@@ -9647,7 +9646,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
} }
/* For a `typename', we needn't call xref_tag. */ /* 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, return cp_parser_make_typename_type (parser, parser->scope,
identifier); identifier);
/* Look up a qualified name in the usual way. */ /* Look up a qualified name in the usual way. */
...@@ -9655,9 +9655,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, ...@@ -9655,9 +9655,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
{ {
tree decl; 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, decl = cp_parser_lookup_name (parser, identifier,
tag_type, tag_type,
/*is_template=*/false, /*is_template=*/false,
...@@ -9692,7 +9689,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, ...@@ -9692,7 +9689,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
if (TREE_CODE (decl) != TYPE_DECL) if (TREE_CODE (decl) != TYPE_DECL)
{ {
error ("expected type-name"); cp_parser_diagnose_invalid_type_name (parser,
parser->scope,
identifier);
return error_mark_node; return error_mark_node;
} }
......
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> 2004-12-14 Andrew Pinski <pinskia@physics.uc.edu>
* gcc.c-torture/20041214-1.c: New test. * gcc.c-torture/20041214-1.c: New test.
......
...@@ -10,7 +10,7 @@ namespace NS { ...@@ -10,7 +10,7 @@ namespace NS {
} }
template <class T> class X { template <class T> class X {
friend class NS::C; // { dg-error "expected|friend" } friend class NS::C; // { dg-error "template|friend" }
}; };
X<int> c; X<int> c;
// PR c++/18738
namespace foo {
typedef int my_type;
}
template<typename T>
struct A {
typename foo::my_type bar();
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment