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]
Other format: [Raw text]

C++ PATCH: PR 8511


Zack was kind enough to cut this template instantiation problem down
to a small test case.  This patch fixes the problem.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-11-30  Mark Mitchell  <mark@codesourcery.com>

	PR c++/8511
	* pt.c (instantiate_decl): Handle template friends defined outside
	of the class correctly.

2002-11-30  Mark Mitchell  <mark@codesourcery.com>

	PR c++/8511
	* g++.dg/template/friend8.C: New test.

Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.631
diff -c -5 -p -r1.631 pt.c
*** cp/pt.c	20 Nov 2002 05:17:01 -0000	1.631
--- cp/pt.c	30 Nov 2002 21:55:01 -0000
*************** tree
*** 9964,9974 ****
  instantiate_decl (d, defer_ok)
       tree d;
       int defer_ok;
  {
    tree tmpl = DECL_TI_TEMPLATE (d);
!   tree args = DECL_TI_ARGS (d);
    tree td;
    tree code_pattern;
    tree spec;
    tree gen_tmpl;
    int pattern_defined;
--- 9964,9975 ----
  instantiate_decl (d, defer_ok)
       tree d;
       int defer_ok;
  {
    tree tmpl = DECL_TI_TEMPLATE (d);
!   tree gen_args;
!   tree args;
    tree td;
    tree code_pattern;
    tree spec;
    tree gen_tmpl;
    int pattern_defined;
*************** instantiate_decl (d, defer_ok)
*** 9998,10008 ****
       there's no reason to instantiate it.  Note that
       retrieve_specialization gives us both instantiations and
       specializations, so we must explicitly check
       DECL_TEMPLATE_SPECIALIZATION.  */
    gen_tmpl = most_general_template (tmpl);
!   spec = retrieve_specialization (gen_tmpl, args);
    if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
      return spec;
  
    /* This needs to happen before any tsubsting.  */
    if (! push_tinst_level (d))
--- 9999,10010 ----
       there's no reason to instantiate it.  Note that
       retrieve_specialization gives us both instantiations and
       specializations, so we must explicitly check
       DECL_TEMPLATE_SPECIALIZATION.  */
    gen_tmpl = most_general_template (tmpl);
!   gen_args = DECL_TI_ARGS (d);
!   spec = retrieve_specialization (gen_tmpl, gen_args);
    if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
      return spec;
  
    /* This needs to happen before any tsubsting.  */
    if (! push_tinst_level (d))
*************** instantiate_decl (d, defer_ok)
*** 10059,10068 ****
--- 10061,10077 ----
        td = DECL_TI_TEMPLATE (td);
      }
  
    code_pattern = DECL_TEMPLATE_RESULT (td);
  
+   /* In the case of a friend temlpate whose definition is provided
+      outside the class, we may have too many arguments.  Drop the ones
+      we don't need.  */
+   args = get_innermost_template_args (gen_args,
+ 				      TMPL_PARMS_DEPTH 
+ 				      (DECL_TEMPLATE_PARMS (td)));
+ 
    if (TREE_CODE (d) == FUNCTION_DECL)
      pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
    else
      pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
  
*************** instantiate_decl (d, defer_ok)
*** 10123,10142 ****
        if (DECL_CLASS_SCOPE_P (d))
  	pushclass (DECL_CONTEXT (d), 1);
  
        if (TREE_CODE (gen) == FUNCTION_DECL)
  	{
! 	  tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d);
! 	  tsubst (TYPE_RAISES_EXCEPTIONS (type), args,
  		  tf_error | tf_warning, d);
  	  /* Don't simply tsubst the function type, as that will give
  	     duplicate warnings about poor parameter qualifications.
  	     The function arguments are the same as the decl_arguments
  	     without the top level cv qualifiers.  */
  	  type = TREE_TYPE (type);
  	}
!       tsubst (type, args, tf_error | tf_warning, d);
  
        if (DECL_CLASS_SCOPE_P (d))
  	popclass ();
      }
    
--- 10132,10151 ----
        if (DECL_CLASS_SCOPE_P (d))
  	pushclass (DECL_CONTEXT (d), 1);
  
        if (TREE_CODE (gen) == FUNCTION_DECL)
  	{
! 	  tsubst (DECL_ARGUMENTS (gen), gen_args, tf_error | tf_warning, d);
! 	  tsubst (TYPE_RAISES_EXCEPTIONS (type), gen_args,
  		  tf_error | tf_warning, d);
  	  /* Don't simply tsubst the function type, as that will give
  	     duplicate warnings about poor parameter qualifications.
  	     The function arguments are the same as the decl_arguments
  	     without the top level cv qualifiers.  */
  	  type = TREE_TYPE (type);
  	}
!       tsubst (type, gen_args, tf_error | tf_warning, d);
  
        if (DECL_CLASS_SCOPE_P (d))
  	popclass ();
      }
    
Index: testsuite/g++.dg/template/friend8.C
===================================================================
RCS file: testsuite/g++.dg/template/friend8.C
diff -N testsuite/g++.dg/template/friend8.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/friend8.C	30 Nov 2002 21:55:04 -0000
***************
*** 0 ****
--- 1,18 ----
+ template <int N> struct ivector
+ {
+   template <int r, int c> friend void
+     mult_mv ();
+ };
+ 
+ template struct ivector<3>;
+ 
+ template <int r, int c> void
+ mult_mv ()
+ {
+   c;
+ }
+ 
+ void get_local_point_pos ()
+ {
+   mult_mv<7, 3> ();
+ }


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