mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 08:30:35 +08:00
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:
parent
a150cb057b
commit
0c88d88668
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
10
gcc/testsuite/g++.dg/template/typename8.C
Normal file
10
gcc/testsuite/g++.dg/template/typename8.C
Normal file
@ -0,0 +1,10 @@
|
||||
// PR c++/18738
|
||||
|
||||
namespace foo {
|
||||
typedef int my_type;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct A {
|
||||
typename foo::my_type bar();
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user