Patch for template template parameter

Kriang Lerdsuwanakij lerdsuwa@scf-fs.usc.edu
Mon Jan 19 23:51:00 GMT 1998


Hi,

This is a fix for various bugs in I found in the earlier patch.  I also
add missing 'typename' warning in code like
	template <template <class> class TT> class C {
		TT<int>::size_type k;	// Error
	};

Kriang

==============================================================

	* pt.c (coerce_template_parms): Don't access elements of ARGLIST
	that is not really present.  Substitute default arguments in 
	template template arguments.  Correctly convert TEMPLATE_DECL to 
	TEMPLATE_TEMPLATE_PARM.
	(comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM 
	are no longer treated specially here.

	* parse.y (template_template_parm): Fix copy error.

	* decl.c (grokdeclarator): Warn about missing `typename' for nested
	type created from template template parameters.
	* parse.y (bad_parm): Likewise

	* pt.c (tsubst): Update comments.


diff -rNpu3 gcc-ttp980113/cp/decl.c gcc-ttp-new/cp/decl.c
--- gcc-ttp980113/cp/decl.c	Sat Jan 10 02:27:33 1998
+++ gcc-ttp-new/cp/decl.c	Fri Jan 16 09:52:37 1998
@@ -7902,7 +7902,8 @@ grokdeclarator (declarator, declspecs, d
 	      else if (TREE_OPERAND (decl, 1)
 		       && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
 		ctype = cname;
-	      else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM)
+	      else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
+		       || TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM)
 		{
 		  cp_error ("`%T::%D' is not a valid declarator", cname,
 			    TREE_OPERAND (decl, 1));
diff -rNpu3 gcc-ttp980113/cp/parse.y gcc-ttp-new/cp/parse.y
--- gcc-ttp980113/cp/parse.y	Sat Jan 10 02:27:34 1998
+++ gcc-ttp-new/cp/parse.y	Fri Jan 16 09:45:23 1998
@@ -488,10 +488,7 @@ template_template_parm:
 		  if ($2 == signature_type_node)
 		    sorry ("signature as template template parameter");
 		  else if ($2 != class_type_node)
-		    {
-		      pedwarn ("template template parameters must use the keyword
`class'");
-		      TREE_PURPOSE ($$) = class_type_node;
-		    }
+		    pedwarn ("template template parameters must use the keyword
`class'");
 		  $$ = build_tree_list (class_type_node, tmpl);
 		}
 	;
@@ -4317,7 +4314,8 @@ bad_parm:
 		{
 		  error ("type specifier omitted for parameter");
 		  if (TREE_CODE ($$) == SCOPE_REF
-		      && TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM)
+		      && (TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_PARM
+			  || TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TEMPLATE_PARM))
 		    cp_error ("  perhaps you want `typename %E' to make it a type",
$$);
 		  $$ = build_tree_list (integer_type_node, $$);
 		}
diff -rNpu3 gcc-ttp980113/cp/pt.c gcc-ttp-new/cp/pt.c
--- gcc-ttp980113/cp/pt.c	Tue Jan 13 17:10:23 1998
+++ gcc-ttp-new/cp/pt.c	Sun Jan 18 21:38:20 1998
@@ -1019,17 +1019,25 @@ coerce_template_parms (parms, arglist, i
       vec = copy_node (arglist);
     else
       {
-	/* We arrive here when a template is used in template template
-	   parameter with some default arguments */
+	/* We arrive here when a template with some default arguments
+	   is used as template template argument.  */
 	is_tmpl_parm = 1;
 	vec = make_tree_vec (nparms);
 	for (i = 0; i < nparms; i++)
 	  {
-	    tree arg = TREE_VEC_ELT (arglist, i);
-	    if (arg)
-	      TREE_VEC_ELT (vec, i) = arg;
+	    tree arg;
+
+	    if (i < nargs)
+	      arg = TREE_VEC_ELT (arglist, i);
+	    else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
+		     == TYPE_DECL)
+	      arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+			    vec, i, in_decl);
 	    else
-	      TREE_VEC_ELT (vec, i) = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+	      arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+				 vec, i, in_decl);
+
+	    TREE_VEC_ELT (vec, i) = arg;
 	  }
       }
   else
@@ -1148,32 +1156,26 @@ coerce_template_parms (parms, arglist, i
 	{
 	  if (requires_tmpl_type)
 	    {
-	      if (!CLASSTYPE_TEMPLATE_INFO (parm))
-		{
-		  tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
-		  tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+	      tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+	      tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
 
-		  /* The parameter and argument roles have to be switched 
-		     here in order to handle default arguments properly.  
-		     For example, 
-		       template<template <class> class TT> void f(TT<int>) 
-		     should be able to accept vector<int> which comes from 
-		       template <class T, class Allcator = allocator> 
-		       class vector.  */
-
-		  val = coerce_template_parms (argparm, parmparm, in_decl);
-		  if (val != error_mark_node)
-		    val = arg;
-		    
-		  /* TEMPLATE_TEMPLATE_PARM node is preferred over 
-		     TEMPLATE_DECL.  */
-		  if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
-		    val = TREE_TYPE (val);
-		}
-	      else
-		/* The parameter has been substituted with arguments.  
-		   We have already checked this */
+	      /* The parameter and argument roles have to be switched 
+		 here in order to handle default arguments properly.  
+		 For example, 
+		   template<template <class> class TT> void f(TT<int>) 
+		 should be able to accept vector<int> which comes from 
+		   template <class T, class Allcator = allocator> 
+		   class vector.  */
+
+	      val = coerce_template_parms (argparm, parmparm, in_decl);
+	      if (val != error_mark_node)
 		val = arg;
+		    
+	      /* TEMPLATE_TEMPLATE_PARM node is preferred over 
+		 TEMPLATE_DECL.  */
+	      if (val != error_mark_node 
+		  && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+		val = TREE_TYPE (val);
 	    }
 	  else
 	    {
@@ -1286,14 +1288,6 @@ comp_template_args (oldargs, newargs)
       tree nt = TREE_VEC_ELT (newargs, i);
       tree ot = TREE_VEC_ELT (oldargs, i);
 
-      /* It's messy because we introduce template template parameters
-	 as TEMPLATE_DECL nodes in the class scope but store them in
-	 TEMPLATE_INFO as a TEMPLATE_TEMPLATE_PARM nodes */
-      if (DECL_TEMPLATE_TEMPLATE_PARM_P (nt))
-	nt = TREE_TYPE (nt);
-      if (DECL_TEMPLATE_TEMPLATE_PARM_P (ot))
-	ot = TREE_TYPE (ot);
-
       if (nt == ot)
 	continue;
       if (TREE_CODE (nt) != TREE_CODE (ot))
@@ -2386,16 +2380,21 @@ tsubst (t, args, nargs, in_decl)
 		  {
 		    if (CLASSTYPE_TEMPLATE_INFO (t))
 		      {
-			/* We are processing a data member constructed 
-			   from template template parameter */
+			/* We are processing a type constructed from
+			   a template template parameter */
 			tree argvec = tsubst (
 					TREE_VALUE (CLASSTYPE_TEMPLATE_INFO (t)), 
 					args, nargs, in_decl);
 			tree r;
 
-			/* ARG is the real template to be instantiated.  */
+			/* We can get a TEMPLATE_TEMPLATE_PARM here when 
+			   we are resolving nested-types in the signature of 
+			   a member function templates.
+			   Otherwise ARG is a TEMPLATE_DECL and is the real 
+			   template to be instantiated.  */
 			if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
 			  arg = TYPE_NAME (arg);
+
 			r = lookup_template_class (DECL_NAME (arg), 
 						   argvec, in_decl);
 			return cp_build_type_variant (r, TYPE_READONLY (t),
diff -rNpu3 gcc-ttp980113/testsuite/g++.old-deja/g++.pt/ttp39.C
gcc-ttp-new/testsuite/g++.old-deja/g++.pt/ttp39.C
--- gcc-ttp980113/testsuite/g++.old-deja/g++.pt/ttp39.C	Wed Dec 31
16:00:00 1969
+++ gcc-ttp-new/testsuite/g++.old-deja/g++.pt/ttp39.C	Sun Jan 18
21:38:54 1998
@@ -0,0 +1,29 @@
+template<class T, class U = T> class D
+{
+	public:
+		int f();
+};
+
+template<class T, class U> int D<T,U>::f()
+{
+	return sizeof(T)+sizeof(U);
+}
+
+template<template<class> class D,class E> class C
+{
+		D<E> d;
+	public:
+		int f() { return d.f(); }
+};
+
+template<template<class> class D> int f(D<int> &d1)
+{
+	d1.f();
+	return 0;
+}
+
+int main()
+{
+	D<int> c1;
+	f(c1);
+}



More information about the Gcc mailing list