[C++ PATCH]: fix bug 43
Nathan Sidwell
nathan@codesourcery.com
Mon Nov 27 04:55:00 GMT 2000
Hi,
I've installed the attached which fixes bug 43 which turned out to have
two separate causes.
1) in tsubst_friend_function, we had the wrong scope set up for tsubsting
the function's name (an IDENTIFIER, LOOKUP_EXPR or OVERLOAD). If the template
class has a member of the same name, we'll find that and die because the class
is incomplete.
Fix-push to the current class's enclosing scope.
2) parser ickiness with operator names causes a similar lookup to happen earlier
too. We end up building a COMPONENT_REF.
Fix-undo the COMPONENT_REF when we discover it during building the friend.
N.B. Apparently DECL_TI_TEMPLATE can also be an OVERLOAD for template
friend functions, update cp-tree.h to say so.
built & tested on i686-pc-linux-gnu, approved by Mark.
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2000-11-27 Nathan Sidwell <nathan@codesourcery.com>
* decl.c (grokfndecl): Undo COMPONENT_REF damage caused by
bison parser ickiness.
* pt.c (tsubst_friend_function): Enter namespace scope when
tsubsting the function name.
* cp-tree.h (DECL_TI_TEMPLATE): Update comment to reflect reality.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.543
diff -c -3 -p -r1.543 cp-tree.h
*** cp-tree.h 2000/11/27 10:55:30 1.543
--- cp-tree.h 2000/11/27 12:02:45
*************** struct lang_decl
*** 2362,2369 ****
As a special case, for a member friend template of a template
class, this value will not be a TEMPLATE_DECL, but rather a
! LOOKUP_EXPR or IDENTIFIER_NODE indicating the name of the template
! and any explicit template arguments provided. For example, in:
template <class T> struct S { friend void f<int>(int, double); }
--- 2362,2370 ----
As a special case, for a member friend template of a template
class, this value will not be a TEMPLATE_DECL, but rather a
! LOOKUP_EXPR, IDENTIFIER_NODE or OVERLOAD indicating the name of
! the template and any explicit template arguments provided. For
! example, in:
template <class T> struct S { friend void f<int>(int, double); }
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.716
diff -c -3 -p -r1.716 decl.c
*** decl.c 2000/11/19 21:07:23 1.716
--- decl.c 2000/11/27 12:03:01
*************** grokfndecl (ctype, type, declarator, ori
*** 8944,8949 ****
--- 8944,8952 ----
orig_declarator);
else
{
+ tree fns = TREE_OPERAND (orig_declarator, 0);
+ tree args = TREE_OPERAND (orig_declarator, 1);
+
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
/* Something like `template <class T> friend void f<T>()'. */
*************** grokfndecl (ctype, type, declarator, ori
*** 8956,8965 ****
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
! DECL_TEMPLATE_INFO (decl)
! = tree_cons (TREE_OPERAND (orig_declarator, 0),
! TREE_OPERAND (orig_declarator, 1),
! NULL_TREE);
if (has_default_arg)
{
--- 8959,8980 ----
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
!
! if (TREE_CODE (fns) == COMPONENT_REF)
! {
! /* Due to bison parser ickiness, we will have already looked
! up an operator_name or PFUNCNAME within the current class
! (see template_id in parse.y). If the current class contains
! such a name, we'll get a COMPONENT_REF here. Undo that. */
!
! my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
! == current_class_type, 20001120);
! fns = TREE_OPERAND (fns, 1);
! }
! my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
! || TREE_CODE (fns) == LOOKUP_EXPR
! || TREE_CODE (fns) == OVERLOAD, 20001120);
! DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
if (has_default_arg)
{
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.480
diff -c -3 -p -r1.480 pt.c
*** pt.c 2000/11/23 15:19:35 1.480
--- pt.c 2000/11/27 12:03:13
*************** tsubst_friend_function (decl, args)
*** 4422,4438 ****
function declaration. Now, we have to figure out what
instantiation of what template. */
{
! tree template_id;
tree new_args;
tree tmpl;
!
! template_id
! = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
! args, /*complain=*/1,
! NULL_TREE),
! tsubst (DECL_TI_ARGS (decl),
! args, /*complain=*/1,
! NULL_TREE));
new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
&new_args,
--- 4422,4443 ----
function declaration. Now, we have to figure out what
instantiation of what template. */
{
! tree template_id, arglist, fns;
tree new_args;
tree tmpl;
! tree ns = CP_DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
!
! /* Friend functions are looked up in the containing namespace scope.
! We must enter that scope, to avoid finding member functions of the
! current cless with same name. */
! push_nested_namespace (ns);
! fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
! /*complain=*/1, NULL_TREE);
! pop_nested_namespace (ns);
! arglist = tsubst (DECL_TI_ARGS (decl), args,
! /*complain=*/1, NULL_TREE);
! template_id = lookup_template_function (fns, arglist);
!
new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
tmpl = determine_specialization (template_id, new_friend,
&new_args,
More information about the Gcc-patches
mailing list