This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[C++ PATCH]: fix bug 43


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, 
// Build don't link:
// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 17 Nov 2000 <nathan@codesourcery.com>

// bug 43. Two failings, bison parser ickiness caused us to find the member
// named the same as a friend, and then when instantiating, we'd lookup in
// the wrong scope.

namespace X {
  template <class T> class P;
  
  template <class T> void operator- (const P<T>&);
  
  template <class T>
  struct V
  {
    V (const T&);
  
    void operator- ();
    friend void operator-<> (const P<T>& a);
  };
}

int main()
{
  X::V<double> b(1.0);

  return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]