This is the mail archive of the gcc-bugs@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]

Patch for g++-980308: bug in template template parameter implementation again


Bernd Nottelmann <nottelm@PTP283.UNI-MUENSTER.DE> wrote:

> Unfortunately I have found a new internal compiler error -
> though I have installed the two patches from Kriang
> (http://www.cygnus.com/ml/egcs-bugs/1998-Mar/0229.html and
> http://www.cygnus.com/ml/egcs-bugs/1998-Mar/0255.html) ...
> here is some sample code:
> 
> /*-------------------bug3.C-------------------*/
> template < class T, template < class > class E1, template < class > class E2 >
> struct Add {
>   Add(const E1<T>& e1, const E2<T>& e2) {}
> };
> 
> template < class T >
> struct Id {
>   template < template < class > class E >
>   Add < T, Id, E > operator+(const E<T>& e) const {
>     return Add < T, Id, E >(*this, e);
>   }
> 
>   template <> Add < T, Id, Id > operator+(const Id<T>& e) const {
>     return Add < T, Id, Id >(*this, e);
>   }
> };
> 

The code look ok to me.  The patch included below fixes a bug that 
affect the code above (without an extra `<>' after `operator+' in the 
specialization syntax).  It also fixes the `Id<double>& + Id<double>&'
bug you mentioned.  

I believe that the extra bracket is not required (according to C++ 
Programming Language, page 344).  The parser in egcs still cannot handle 
various template function or operator specialization construct.  It might 
lead to incorrect error messages or internal compiler error.  I haven't 
found a good fix for this.  :(

--Kriang


	* pt.c (complete_template_args): New function.
	(get_bindings): Deal with specializations of function templates
	with return type containing parameters from outer class 
	templates.

	(tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
	substitute arguments and compose a new type.


diff -cprN gcc-980311/cp/pt.c gcc-980315/cp/pt.c
*** gcc-980311/cp/pt.c	Wed Mar 11 20:18:48 1998
--- gcc-980315/cp/pt.c	Sun Mar 15 15:32:25 1998
*************** static tree get_class_bindings PROTO((tr
*** 81,86 ****
--- 81,87 ----
  static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int));
  static tree tsubst_enum	PROTO((tree, tree, tree *));
  static tree add_to_template_args PROTO((tree, tree));
+ static tree complete_template_args PROTO((tree, tree));
  static int  type_unification_real PROTO((tree, tree *, tree, tree,
  					 int, int, int));
  static void note_template_header PROTO((int));
*************** is_member_template (t)
*** 296,301 ****
--- 297,370 ----
    return is_member_or_friend_template (t, 0);
  }
  
+ /* Return a new template argument vector which contains all of ARGS
+    for all outer templates TYPE is contained in, but has as its 
+    innermost set of arguments the EXTRA_ARGS.  */
+ 
+ static tree
+ complete_template_args (decl, extra_args)
+      tree decl;
+      tree extra_args;
+ {
+   int depth;
+   tree type;
+   
+   my_friendly_assert (TREE_CODE (decl) == TEMPLATE_DECL, 0);
+   my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
+ 
+   decl = DECL_TEMPLATE_RESULT (decl);
+   type = DECL_REAL_CONTEXT (decl);
+ 
+   /* For constructor and destructor, it can be template simply
+      because the class it belongs to is.  If this is the case,
+      it and its context share the same template arguments and
+      we don't want its context in template_class_depth 
+      computation.  */
+ 
+   if (DECL_LANG_SPECIFIC (decl) && DECL_CONSTRUCTOR_P (decl))
+     {
+       /* Check whether its context is a template class.  */
+       if (CLASSTYPE_TEMPLATE_INFO (type)
+ 	  && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ 	  && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ 	{
+ 	  if (comp_template_args (CLASSTYPE_TI_ARGS (type),
+ 				  DECL_TI_ARGS (decl)))
+ 	    type = TYPE_CONTEXT (type);
+ 
+ 	}
+     }
+   else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
+     {
+       /* There is no template destructors.  */
+       type = TYPE_CONTEXT (type);
+     }
+   
+   depth = template_class_depth (type);
+   if (depth)
+     {
+       tree new_args = make_tree_vec (depth + 1);
+ 
+       for (; type && TREE_CODE (type) != FUNCTION_DECL;
+ 	   type = TYPE_CONTEXT (type))
+ 	{
+ 	  if (CLASSTYPE_TEMPLATE_INFO (type)
+ 	      && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ 	      && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ 	    {
+ 	      --depth;
+ 	      TREE_VEC_ELT (new_args, depth) = CLASSTYPE_TI_ARGS (type);
+ 	    }
+ 	}
+ 
+       TREE_VEC_ELT (new_args, 
+ 		    TREE_VEC_LENGTH (new_args) - 1) = extra_args;
+       extra_args = new_args;
+     }
+ 
+   return extra_args;
+ }
+ 
  /* Return a new template argument vector which contains all of ARGS,
     but has as its innermost set of arguments the EXTRA_ARGS.  */
  
*************** tsubst (t, args, in_decl)
*** 3525,3531 ****
  	  {
  	  case TEMPLATE_TYPE_PARM:
  	  case TEMPLATE_TEMPLATE_PARM:
! 	    r = copy_node (t);
  	    TEMPLATE_TYPE_PARM_INDEX (r)
  	      = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
  					    r, levels);
--- 3594,3613 ----
  	  {
  	  case TEMPLATE_TYPE_PARM:
  	  case TEMPLATE_TEMPLATE_PARM:
! 
! 	    if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
! 		&& CLASSTYPE_TEMPLATE_INFO (t))
! 	      {
! 		tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
! 				      args, in_decl);
! 		r = lookup_template_class (TYPE_NAME (t), argvec, in_decl, 
! 					   DECL_CONTEXT (TYPE_NAME (t)));
! 		r = cp_build_type_variant (r, TYPE_READONLY (t),
! 					   TYPE_VOLATILE (t));
! 	      }
! 	    else
! 	      r = copy_node (t);
! 
  	    TEMPLATE_TYPE_PARM_INDEX (r)
  	      = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
  					    r, levels);
*************** get_bindings (fn, decl, explicit_args)
*** 5702,5708 ****
    if (i == 0)
      {
        /* Check to see that the resulting return type is also OK.  */
!       tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs, NULL_TREE);
  
        if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
  	return NULL_TREE;
--- 5784,5792 ----
    if (i == 0)
      {
        /* Check to see that the resulting return type is also OK.  */
!       tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), 
! 		       complete_template_args (fn, targs),
! 		       NULL_TREE);
  
        if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
  	return NULL_TREE;



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