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 789


Hi,
I've installed this which fixes bug 789 where we ICE'd because we expected
to find a partial instantiation of a template template member when 
nstantiating an instance of it. That assumption is false when it's
A<T>::C<int> as in this test case.
So the fix is to generate the partial instantiation, if we failed to
find it. Also tidied up some comments and confusing looping logic
in lookup_template_class.

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-23  Nathan Sidwell  <nathan@codesourcery.com>

	* pt.c (lookup_template_class): Simplify loop exit constructs.
	Cope when there is no partial instantiation of a template
	template member.

Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.478
diff -c -3 -p -r1.478 pt.c
*** pt.c	2000/11/17 12:36:26	1.478
--- pt.c	2000/11/23 08:43:12
*************** maybe_get_template_decl_from_type_decl (
*** 3700,3708 ****
     D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
     (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC.  It will
     be a TREE_LIST if called directly from the parser, and a TREE_VEC
!    otherwise.)  Since ARGLIST is build on the temp_decl_obstack, we must
!    copy it here to keep it from being reclaimed when the decl storage
!    is reclaimed.
  
     IN_DECL, if non-NULL, is the template declaration we are trying to
     instantiate.  
--- 3700,3706 ----
     D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
     (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC.  It will
     be a TREE_LIST if called directly from the parser, and a TREE_VEC
!    otherwise.)
  
     IN_DECL, if non-NULL, is the template declaration we are trying to
     instantiate.  
*************** lookup_template_class (d1, arglist, in_d
*** 3925,3947 ****
  		found = NULL_TREE;
  	    }
  	}
-       
-       if (!found)
- 	{
- 	  for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
- 	       found; found = TREE_CHAIN (found))
- 	    if (comp_template_args (TREE_PURPOSE (found), arglist))
- 	      break;
- 
- 	  if (found)
- 	    found = TREE_VALUE (found);
- 	}
- 
        if (found)
! 	return found;
  
        /* This type is a "partial instantiation" if any of the template
! 	 arguments still inolve template parameters.  Note that we set
  	 IS_PARTIAL_INSTANTIATION for partial specializations as
  	 well.  */
        is_partial_instantiation = uses_template_parms (arglist);
--- 3923,3938 ----
  		found = NULL_TREE;
  	    }
  	}
        if (found)
!         return found;
!       
!       for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
! 	   found; found = TREE_CHAIN (found))
! 	if (comp_template_args (TREE_PURPOSE (found), arglist))
! 	   return TREE_VALUE (found);
  
        /* This type is a "partial instantiation" if any of the template
! 	 arguments still involve template parameters.  Note that we set
  	 IS_PARTIAL_INSTANTIATION for partial specializations as
  	 well.  */
        is_partial_instantiation = uses_template_parms (arglist);
*************** lookup_template_class (d1, arglist, in_d
*** 4016,4024 ****
  	found = template;
        else
  	{
! 	  /* This is a full instantiation of a member template.  There
! 	     should be some partial instantiation of which this is an
! 	     instance.  */
  
  	  for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
  	       found; found = TREE_CHAIN (found))
--- 4007,4014 ----
  	found = template;
        else
  	{
! 	  /* This is a full instantiation of a member template.  Look
! 	     for a partial instantiation of which this is an instance.  */
  
  	  for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
  	       found; found = TREE_CHAIN (found))
*************** lookup_template_class (d1, arglist, in_d
*** 4054,4064 ****
  	    }
  
  	  if (!found)
! 	    my_friendly_abort (0);
  	}
  
!       SET_TYPE_TEMPLATE_INFO (t,
! 			      tree_cons (found, arglist, NULL_TREE));  
        DECL_TEMPLATE_INSTANTIATIONS (template) 
  	= tree_cons (arglist, t, 
  		     DECL_TEMPLATE_INSTANTIATIONS (template));
--- 4044,4067 ----
  	    }
  
  	  if (!found)
! 	    {
! 	      /* There was no partial instantiation. This happens
!                  where C<T> is a member template of A<T> and it's used
!                  in something like
!                 
!                   template <typename T> struct B { A<T>::C<int> m; };
!                   B<float>;
!                 
!                  Create the partial instantiation.
!                */
!               TREE_VEC_LENGTH (arglist)--;
!               template = tsubst (template, arglist, /*complain=*/0, NULL_TREE);
!               TREE_VEC_LENGTH (arglist)++;
!               found = template;
!             }
  	}
  
!       SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));  
        DECL_TEMPLATE_INSTANTIATIONS (template) 
  	= tree_cons (arglist, t, 
  		     DECL_TEMPLATE_INSTANTIATIONS (template));
// Build don't link:

// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 22 Nov 2000 <nathan@codesourcery.com>

// Bug 789. We ICE'd trying to instantiate B<float> because there was no
// existing partial specialization of C in A<float>.

template <typename T>
struct A {
    template <typename D1>
    struct C { };
};

template <typename T1>
struct B {
   A<T1>::C<int> s1;
};

int main()
{
    B<float> b;
    
    return 0;
}

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