This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 18738
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 14 Dec 2004 16:45:17 -0800
- Subject: C++ PATCH: PR 18738
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/18738. We were rejecting uses of "typename"
where the qualfying scope was a namespace, rather than a type.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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 Mark Mitchell <mark@codesourcery.com>
PR c++/18738
* g++.dg/template/typename8.C: New test.
* g++.dg/parse/friend2.C: Tweak error message.
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1340
diff -c -5 -p -r1.1340 decl.c
*** cp/decl.c 8 Dec 2004 10:25:06 -0000 1.1340
--- cp/decl.c 15 Dec 2004 00:37:30 -0000
*************** make_typename_type (tree context, tree n
*** 2667,2685 ****
{
error ("%qD used without template parameters", name);
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;
! }
if (!dependent_type_p (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
--- 2667,2677 ----
{
error ("%qD used without template parameters", name);
return error_mark_node;
}
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
! gcc_assert (TYPE_P (context));
if (!dependent_type_p (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
*************** grok_op_properties (tree decl, int frien
*** 9046,9068 ****
}
return ok;
}
static const char *
tag_name (enum tag_types code)
{
switch (code)
{
case record_type:
return "struct";
case class_type:
return "class";
case union_type:
! return "union ";
case enum_type:
return "enum";
default:
gcc_unreachable ();
}
}
--- 9038,9064 ----
}
return ok;
}
+ /* Return a string giving the keyword associate with CODE. */
+
static const char *
tag_name (enum tag_types code)
{
switch (code)
{
case record_type:
return "struct";
case class_type:
return "class";
case union_type:
! return "union";
case enum_type:
return "enum";
+ case typename_type:
+ return "typename";
default:
gcc_unreachable ();
}
}
*************** check_elaborated_type_specifier (enum ta
*** 9104,9129 ****
type-parameter, the elaborated-type-specifier is ill-formed.
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))
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
cp_error_at ("%qD has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
! && tag_code != enum_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)
{
error ("%qT referred to as enum", type);
cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
--- 9100,9128 ----
type-parameter, the elaborated-type-specifier is ill-formed.
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)
! && 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);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_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 != typename_type)
{
error ("%qT referred to as enum", type);
cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.293
diff -c -5 -p -r1.293 parser.c
*** cp/parser.c 10 Dec 2004 16:04:15 -0000 1.293
--- cp/parser.c 15 Dec 2004 00:37:33 -0000
*************** cp_parser_non_integral_constant_expressi
*** 1939,1951 ****
parser->non_integral_constant_expression_p = true;
}
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. */
static void
cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
{
tree decl, old_scope;
--- 1939,1950 ----
parser->non_integral_constant_expression_p = true;
}
return false;
}
! /* 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)
{
tree decl, old_scope;
*************** cp_parser_elaborated_type_specifier (cp_
*** 9655,9675 ****
parser->scope = NULL_TREE;
return error_mark_node;
}
/* For a `typename', we needn't call xref_tag. */
! if (tag_type == typename_type)
return cp_parser_make_typename_type (parser, parser->scope,
identifier);
/* Look up a qualified name in the usual way. */
if (parser->scope)
{
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,
/*is_namespace=*/false,
/*check_dependency=*/true,
--- 9654,9672 ----
parser->scope = NULL_TREE;
return error_mark_node;
}
/* For a `typename', we needn't call xref_tag. */
! 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. */
if (parser->scope)
{
tree decl;
decl = cp_parser_lookup_name (parser, identifier,
tag_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
*************** cp_parser_elaborated_type_specifier (cp_
*** 9700,9710 ****
(decl, /*tag_name_p=*/is_friend
&& parser->num_template_parameter_lists));
if (TREE_CODE (decl) != TYPE_DECL)
{
! error ("expected type-name");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
check_elaborated_type_specifier
--- 9697,9709 ----
(decl, /*tag_name_p=*/is_friend
&& parser->num_template_parameter_lists));
if (TREE_CODE (decl) != TYPE_DECL)
{
! cp_parser_diagnose_invalid_type_name (parser,
! parser->scope,
! identifier);
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
check_elaborated_type_specifier
Index: testsuite/g++.dg/parse/friend2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/parse/friend2.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 friend2.C
*** testsuite/g++.dg/parse/friend2.C 29 Jan 2003 14:25:06 -0000 1.1
--- testsuite/g++.dg/parse/friend2.C 15 Dec 2004 00:37:33 -0000
*************** namespace NS {
*** 8,16 ****
template <class T1, class T2, class T3 = int, class T4 = int>
struct C {};
}
template <class T> class X {
! friend class NS::C; // { dg-error "expected|friend" }
};
X<int> c;
--- 8,16 ----
template <class T1, class T2, class T3 = int, class T4 = int>
struct C {};
}
template <class T> class X {
! friend class NS::C; // { dg-error "template|friend" }
};
X<int> c;
Index: testsuite/g++.dg/template/typename8.C
===================================================================
RCS file: testsuite/g++.dg/template/typename8.C
diff -N testsuite/g++.dg/template/typename8.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/typename8.C 15 Dec 2004 00:37:37 -0000
***************
*** 0 ****
--- 1,10 ----
+ // PR c++/18738
+
+ namespace foo {
+ typedef int my_type;
+ }
+
+ template<typename T>
+ struct A {
+ typename foo::my_type bar();
+ };