This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(C++) Patch to elaborated-type-specifier handling
- To: gcc-patches at gcc dot gnu dot org
- Subject: (C++) Patch to elaborated-type-specifier handling
- From: Jason Merrill <jason at redhat dot com>
- Date: Tue, 12 Sep 2000 17:56:25 -0700
This patch:
1) Generates a diagnostic for 'friend T' where T is looked up to be an
implicit typename.
2) Generates a warning for 'friend struct T', since the user probably
wanted the inherited type, not some global type.
3) Causes 'struct B::T' where B is the current (template) class
to generate a TYPENAME_TYPE, as per core issue 180, so that
'friend struct B::T' is well-formed.
Test in g++.pt/inherit2.C.
2000-09-12 Jason Merrill <jason@redhat.com>
* decl.c (grokdeclarator): Complain about 'friend T' for implicit
typenames, too. Downgrade complaint to pedwarn.
(xref_tag): Warn about surprising behavior of 'friend struct T'.
* decl2.c (handle_class_head): Generate a TYPENAME_TYPE for
'class This::Inherited'.
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.688
diff -c -p -r1.688 decl.c
*** decl.c 2000/09/11 01:50:48 1.688
--- decl.c 2000/09/13 00:49:15
*************** grokdeclarator (declarator, declspecs, d
*** 11411,11422 ****
cp_error ("`inline' specified for friend class declaration");
inlinep = 0;
}
! if (!current_aggr && TREE_CODE (type) != TYPENAME_TYPE)
{
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
! cp_error ("template parameters cannot be friends");
else
! cp_error ("friend declaration requires `%#T'", type);
}
/* Only try to do this stuff if we didn't already give up. */
--- 11408,11430 ----
cp_error ("`inline' specified for friend class declaration");
inlinep = 0;
}
!
! /* Until core issue 180 is resolved, allow 'friend typename A::B'.
! But don't allow implicit typenames. */
! if (!current_aggr && (TREE_CODE (type) != TYPENAME_TYPE
! || IMPLICIT_TYPENAME_P (type)))
{
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
! cp_pedwarn ("template parameters cannot be friends");
! else if (TREE_CODE (type) == TYPENAME_TYPE)
! cp_pedwarn ("\
! friend declaration requires class-key, i.e. `friend class %T::%T'",
! constructor_name (current_class_type),
! TYPE_IDENTIFIER (type));
else
! cp_pedwarn ("\
! friend declaration requires class-key, i.e. `friend %#T'",
! type);
}
/* Only try to do this stuff if we didn't already give up. */
*************** xref_tag (code_type_node, name, globaliz
*** 12925,12930 ****
--- 12933,12954 ----
}
else
t = IDENTIFIER_TYPE_VALUE (name);
+
+ /* Warn about 'friend struct Inherited;' doing the wrong thing. */
+ if (t && globalize && TREE_CODE (t) == TYPENAME_TYPE)
+ {
+ static int explained;
+
+ cp_warning ("`%s %T' declares a new type at namespace scope;\n\
+ to refer to the inherited type, say `%s %T::%T'%s",
+ tag_name (tag_code), name, tag_name (tag_code),
+ constructor_name (current_class_type), TYPE_IDENTIFIER (t),
+ (!explained ? "\n\
+ (names from dependent base classes are not visible to unqualified name lookup)"
+ : ""));
+
+ explained = 1;
+ }
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
&& TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.395
diff -c -p -r1.395 decl2.c
*** decl2.c 2000/09/10 21:34:40 1.395
--- decl2.c 2000/09/13 00:49:17
*************** tree
*** 5436,5442 ****
handle_class_head (aggr, scope, id)
tree aggr, scope, id;
{
! tree decl;
if (TREE_CODE (id) == TYPE_DECL)
/* We must bash typedefs back to the main decl of the type. Otherwise
--- 5436,5442 ----
handle_class_head (aggr, scope, id)
tree aggr, scope, id;
{
! tree decl = NULL_TREE;
if (TREE_CODE (id) == TYPE_DECL)
/* We must bash typedefs back to the main decl of the type. Otherwise
*************** handle_class_head (aggr, scope, id)
*** 5446,5452 ****
decl = DECL_TEMPLATE_RESULT (id);
else
{
! tree current = current_scope();
if (current == NULL_TREE)
current = current_namespace;
--- 5446,5452 ----
decl = DECL_TEMPLATE_RESULT (id);
else
{
! tree current = current_scope ();
if (current == NULL_TREE)
current = current_namespace;
*************** handle_class_head (aggr, scope, id)
*** 5454,5460 ****
scope = global_namespace;
if (scope == NULL_TREE)
scope = global_namespace;
! if (scope == current)
{
/* We've been given AGGR SCOPE::ID, when we're already inside SCOPE.
Be nice about it. */
--- 5454,5470 ----
scope = global_namespace;
if (scope == NULL_TREE)
scope = global_namespace;
!
! if (TYPE_P (scope))
! {
! /* According to the suggested resolution of core issue 180,
! 'typename' is assumed after a class-key. */
! decl = make_typename_type (scope, id, 1);
! if (decl == error_mark_node)
! return error_mark_node;
! decl = TYPE_MAIN_DECL (decl);
! }
! else if (scope == current)
{
/* We've been given AGGR SCOPE::ID, when we're already inside SCOPE.
Be nice about it. */
*************** handle_class_head (aggr, scope, id)
*** 5468,5474 ****
cp_error ("no file-scope type named `%D'", id);
/* Inject it at the current scope. */
! decl = TYPE_MAIN_DECL (xref_tag (aggr, id, 1));
}
/* Enter the SCOPE. If this turns out not to be a definition, the
--- 5478,5485 ----
cp_error ("no file-scope type named `%D'", id);
/* Inject it at the current scope. */
! if (!decl)
! decl = TYPE_MAIN_DECL (xref_tag (aggr, id, 1));
}
/* Enter the SCOPE. If this turns out not to be a definition, the