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

An explicit template specification patch


Hi,

The explicit template specification code in the recent egcs code still
misses a couple cases.  Template function calls and member template
function calls inside templates are not properly handled.  I found that
template arguments are discarded on my machine (i586 Linux).

Below are all the test cases that I used and the patch against g++ (I
worked with egcs 971023).  The patch also contains the fix I posted
earlier in egcs list
(http://www.cygnus.com/ml/egcs/1997-Oct/1170.html).  Some test cases
rely on it.

I hope the approach to the problem is correct.

Thanks

Kriang Lerdsuwanakij

===========================================================
Test Cases:

diff -Nu g++.pt.old/explicit50.C g++.pt/explicit50.C
--- g++.pt.old/explicit50.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit50.C	Wed Nov  5 22:24:56 1997
@@ -0,0 +1,15 @@
+extern "C" void abort ();
+
+template <class T> int f ()
+{
+  return sizeof(T);
+}
+
+int main ()
+{
+  if (f<long> () != sizeof(long)
+      || f<char> () != sizeof(char)
+      || f<long> () != sizeof(long)
+      || f<long int> () != sizeof(long int))
+    abort ();
+}
diff -Nu g++.pt.old/explicit51.C g++.pt/explicit51.C
--- g++.pt.old/explicit51.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit51.C	Wed Nov  5 22:27:14 1997
@@ -0,0 +1,18 @@
+extern "C" void abort ();
+
+template <int a> int fact ()
+{
+  return 0;
+}
+
+template <> int fact<1> ()
+{
+  return 1;
+}
+
+int main()
+{
+  if (fact<3> () != 0 || fact<1> () != 1
+      || fact<3> () != 0 || fact<1> () != 1 || fact<1+0> () != 1)
+    abort ();
+}
diff -Nu g++.pt.old/explicit52.C g++.pt/explicit52.C
--- g++.pt.old/explicit52.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit52.C	Wed Nov  5 22:29:15 1997
@@ -0,0 +1,18 @@
+extern "C" void abort ();
+
+template <int a> inline int fact ()
+{
+  return a * fact<a-1> ();
+}
+
+template <> inline int fact<1> ()
+{
+  return 1;
+}
+
+int main()
+{
+  if (fact<3> () != 6 || fact<1> () != 1
+      || fact<3> () != 6 || fact<1> () != 1 || fact<1+0> () != 1)
+    abort ();
+}
diff -Nu g++.pt.old/explicit53.C g++.pt/explicit53.C
--- g++.pt.old/explicit53.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit53.C	Wed Nov  5 22:31:02 1997
@@ -0,0 +1,21 @@
+extern "C" void abort ();
+
+template <int a> inline int fact ();
+template <> inline int fact<1> ();
+
+template <int a> inline int fact ()
+{
+  return a * fact<a-1> ();
+}
+
+template <> inline int fact<1> ()
+{
+  return 1;
+}
+
+int main()
+{
+  if (fact<3> () != 6 || fact<1> () != 1
+      || fact<3> () != 6 || fact<1> () != 1 || fact<1+0> () != 1)
+    abort ();
+}
diff -Nu g++.pt.old/explicit54.C g++.pt/explicit54.C
--- g++.pt.old/explicit54.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit54.C	Wed Nov  5 22:33:53 1997
@@ -0,0 +1,35 @@
+extern "C" void abort ();
+
+template <int a> inline int fact2 ();
+
+template <int a> inline int fact ()
+{
+  return a * fact2<a-1> ();
+}
+
+template <> inline int fact<1> ()
+{
+  return 1;
+}
+
+template <int a> inline int fact2 ()
+{
+  return a*fact<a-1>();
+}
+
+template <> inline int fact2<1> ()
+{
+  return 1;
+}
+
+int main()
+{
+  if (fact<3> () != 6 || fact<1> () != 1
+      || fact<3> () != 6 || fact<1> () != 1 || fact<1+0> () != 1)
+    abort ();
+  if (fact2<3> () != 6 || fact2<1> () != 1
+      || fact2<3> () != 6 || fact2<1> () != 1 || fact2<1+0> () != 1)
+    abort ();
+  if (fact2<4> () != 24 || fact<4> () != 24)
+    abort ();
+}
diff -Nu g++.pt.old/explicit55.C g++.pt/explicit55.C
--- g++.pt.old/explicit55.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit55.C	Wed Nov  5 22:36:10 1997
@@ -0,0 +1,14 @@
+template <class T> T* create ()
+{
+  return new T;
+}
+
+template <class T> T* create2()
+{
+  return create<T>();
+}
+
+int main()
+{
+  int *p = create2<int>();
+}
diff -Nu g++.pt.old/explicit56.C g++.pt/explicit56.C
--- g++.pt.old/explicit56.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit56.C	Wed Nov  5 22:37:26 1997
@@ -0,0 +1,16 @@
+template <class T> T* create ();
+
+template <class T> T* create2()
+{
+  return create<T>();
+}
+
+template <class T> T* create ()
+{
+  return new T;
+}
+
+int main()
+{
+  int *p = create2<int>();
+}
diff -Nu g++.pt.old/explicit57.C g++.pt/explicit57.C
--- g++.pt.old/explicit57.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit57.C	Wed Nov  5 22:51:44 1997
@@ -0,0 +1,42 @@
+extern "C" void abort ();
+
+int a = 0;
+
+template <class T> void f ();
+template <class T> void g ()
+{
+  if (a)
+    abort ();
+}
+
+template <> void g<char> ()
+{
+}
+
+template <class T> class C
+{
+  public:
+    void ff () { f<T> (); }
+    void gg () { g<T> (); }
+};
+
+template <class T> void f ()
+{
+  if (a)
+    abort ();
+}
+
+template <> void f<char> ()
+{
+}
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+  c.gg();
+  a = 1;
+  C<char> d;
+  d.ff();
+  d.gg();
+}
diff -Nu g++.pt.old/explicit58.C g++.pt/explicit58.C
--- g++.pt.old/explicit58.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit58.C	Wed Nov  5 23:28:02 1997
@@ -0,0 +1,41 @@
+extern "C" void abort ();
+
+template <class T> void f ();
+template <class T> void g ()
+{
+  abort ();
+}
+
+template <> void g<char> ()
+{
+  abort ();
+}
+
+template <class T> class C
+{
+  public:
+    template <class U> void f () {}
+    template <class U> void g () {}
+    void ff () { f<T> (); }
+    void gg () { g<T> (); }
+};
+
+template <class T> void f ()
+{
+  abort ();
+}
+
+template <> void f<char> ()
+{
+  abort ();
+}
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+  c.gg();
+  C<char> d;
+  d.ff();
+  d.gg();
+}
diff -Nu g++.pt.old/explicit59.C g++.pt/explicit59.C
--- g++.pt.old/explicit59.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit59.C	Wed Nov  5 22:55:15 1997
@@ -0,0 +1,41 @@
+extern "C" void abort ();
+
+template <class T> void f ();
+template <class T> void g ()
+{
+  abort ();
+}
+
+template <> void g<char> ()
+{
+  abort ();
+}
+
+template <class T> class C
+{
+  public:
+    void ff () { f<T> (); }
+    void gg () { g<T> (); }
+    template <class U> void f () {}
+    template <class U> void g () {}
+};
+
+template <class T> void f ()
+{
+  abort ();
+}
+
+template <> void f<char> ()
+{
+  abort ();
+}
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+  c.gg();
+  C<char> d;
+  d.ff();
+  d.gg();
+}
diff -Nu g++.pt.old/explicit60.C g++.pt/explicit60.C
--- g++.pt.old/explicit60.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit60.C	Fri Nov  7 20:03:57 1997
@@ -0,0 +1,43 @@
+extern "C" void abort ();
+
+template <class T> void f ();
+template <class T> void g ()
+{
+  abort ();
+}
+
+template <> void g<char> ()
+{
+  abort ();
+}
+
+template <class T> class C
+{
+  public:
+    void ff () { f<T> (); }
+    void gg () { g<T> (); }
+    template <class U> void f () {}
+    template <class U> void g () {}
+    template <class U> void f (int) { abort(); }
+    template <class U> void g (int) { abort(); }
+};
+
+template <class T> void f ()
+{
+  abort ();
+}
+
+template <> void f<char> ()
+{
+  abort ();
+}
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+  c.gg();
+  C<char> d;
+  d.ff();
+  d.gg();
+}
diff -Nu g++.pt.old/explicit61.C g++.pt/explicit61.C
--- g++.pt.old/explicit61.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit61.C	Fri Nov  7 20:04:07 1997
@@ -0,0 +1,43 @@
+extern "C" void abort ();
+
+template <class T> void f ();
+template <class T> void g ()
+{
+  abort ();
+}
+
+template <> void g<char> ()
+{
+  abort ();
+}
+
+template <class T> class C
+{
+  public:
+    void ff () { f<T> (0); }
+    void gg () { g<T> (1); }
+    template <class U> void f () { abort(); }
+    template <class U> void g () { abort(); }
+    template <class U> void f (int) {}
+    template <class U> void g (int) {}
+};
+
+template <class T> void f ()
+{
+  abort ();
+}
+
+template <> void f<char> ()
+{
+  abort ();
+}
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+  c.gg();
+  C<char> d;
+  d.ff();
+  d.gg();
+}
diff -Nu g++.pt.old/explicit62.C g++.pt/explicit62.C
--- g++.pt.old/explicit62.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit62.C	Fri Nov  7 20:19:57 1997
@@ -0,0 +1,19 @@
+extern "C" void abort ();
+
+template <class T> void f ()
+{
+}
+
+
+template <class T> class C
+{
+  friend void f<char> ();
+  public:
+    void ff () { f<char> (); }
+};
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+}
diff -Nu g++.pt.old/explicit63.C g++.pt/explicit63.C
--- g++.pt.old/explicit63.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit63.C	Fri Nov  7 21:06:32 1997
@@ -0,0 +1,19 @@
+extern "C" void abort ();
+
+template <class T> void f ()
+{
+}
+
+
+template <class T> class C
+{
+  friend void f<T> ();
+  public:
+    void ff () { f<T> (); }
+};
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+}
diff -Nu g++.pt.old/explicit64.C g++.pt/explicit64.C
--- g++.pt.old/explicit64.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit64.C	Fri Nov  7 21:07:29 1997
@@ -0,0 +1,23 @@
+extern "C" void abort ();
+
+template <class T> void f ()
+{
+  abort ();
+}
+
+template <> void f<char> ()
+{
+}
+
+template <class T> class C
+{
+  friend void f<char> ();
+  public:
+    void ff () { f<char> (); }
+};
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+}
diff -Nu g++.pt.old/explicit65.C g++.pt/explicit65.C
--- g++.pt.old/explicit65.C	Wed Dec 31 16:00:00 1969
+++ g++.pt/explicit65.C	Sun Nov  9 00:52:37 1997
@@ -0,0 +1,33 @@
+extern "C" void abort ();
+
+template <class T> void f ()
+{
+  abort ();
+}
+
+template <> void f<char> ()
+{
+  abort ();
+}
+
+template <class T> void f (int)
+{
+  abort ();
+}
+
+template <> void f<char> (int)
+{
+}
+
+template <class T> class C
+{
+  friend void f<char> (int);
+  public:
+    void ff () { f<char> (0); }
+};
+
+int main ()
+{
+  C<int> c;
+  c.ff();
+}


================================================================
	* pt.c (tsubst_copy): Handle explicit template arguments in 
	function calls.
	* typeck.c (build_x_function_call): Likewise
	* decl2.c (build_expr_from_tree): Lookup function name if it 
	hasn't been done.

	* pt.c (tsubst): Instantiate template functions properly when 
	template parameter does not appear in function arguments and return 
	type.
	(comp_template_args): Handle member templates required by tsubst.


diff -u save/decl2.c cp/decl2.c
--- save/decl2.c	Tue Nov  4 02:04:17 1997
+++ cp/decl2.c	Fri Nov  7 20:06:04 1997
@@ -3571,6 +3571,10 @@
 	  tree name = TREE_OPERAND (t, 0);
 	  if (! really_overloaded_fn (name))
 	    name = build_expr_from_tree (name);
+	  else if (TREE_CODE (name) == TEMPLATE_ID_EXPR 
+	  	   && TREE_CODE (TREE_OPERAND (name, 0)) == LOOKUP_EXPR)
+	    /* Lookup function name */
+	    TREE_OPERAND (name, 0) = build_expr_from_tree (TREE_OPERAND (name,
0));
 	  return build_x_function_call
 	    (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
 	     current_class_ref);
diff -u save/pt.c cp/pt.c
--- save/pt.c	Sun Oct 26 00:11:51 1997
+++ cp/pt.c	Fri Nov  7 20:05:53 1997
@@ -1157,7 +1157,13 @@
 	continue;
       if (TREE_CODE (nt) != TREE_CODE (ot))
 	return 0;
-      if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+      if (TREE_CODE (nt) == TREE_VEC)
+        {
+          /* For member templates */
+	  if (comp_template_args (nt, ot))
+	    continue;
+        }
+      else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
 	{
 	  if (comptypes (ot, nt, 1))
 	    continue;
@@ -2246,14 +2252,6 @@
 	    type = tsubst (type, args, nargs, in_decl);
 	  }
 
-	if (type == TREE_TYPE (t)
-	    && (! member || ctx == DECL_CLASS_CONTEXT (t)))
-	  {
-	    t = copy_node (t);
-	    copy_lang_decl (t);
-	    return t;
-	  }
-
 	/* Do we already have this instantiation?  */
 	if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
 	  {
@@ -2262,7 +2260,8 @@
 
 	    for (; decls; decls = TREE_CHAIN (decls))
 	      if (TREE_TYPE (TREE_VALUE (decls)) == type
-		  && DECL_CLASS_CONTEXT (TREE_VALUE (decls)) == ctx)
+		  && DECL_CLASS_CONTEXT (TREE_VALUE (decls)) == ctx
+		  && comp_template_args (TREE_PURPOSE (decls), args))
 		return TREE_VALUE (decls);
 	  }
 
@@ -2965,7 +2964,11 @@
     case CALL_EXPR:
       {
 	tree fn = TREE_OPERAND (t, 0);
-	if (really_overloaded_fn (fn))
+	if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+	  /* Keep the TEMPLATE_ID_EXPR node for build_new_function_call
+	     later */
+	  fn = tsubst_copy (fn, args, nargs, in_decl);
+	else if (really_overloaded_fn (fn))
 	  fn = tsubst_copy (TREE_VALUE (fn), args, nargs, in_decl);
 	else
 	  fn = tsubst_copy (fn, args, nargs, in_decl);
@@ -3028,10 +3031,33 @@
 
     case TEMPLATE_ID_EXPR:
       {
-	tree r = lookup_template_function
-	  (tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
-	   tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl));
-	return r;
+        /* Substituted template arguments */
+	tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl);
+	tree chain = targs;
+	while (chain)
+	  {
+	    if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (chain))) != 't'
+		&& !uses_template_parms (TREE_VALUE (chain)))
+	      {
+		/* Sometimes, one of the args was an expression involving a
+		   template constant parameter, like N - 1.  Now that we've
+		   tsubst'd, we might have something like 2 - 1.  This will
+		   confuse lookup_template_class, so we do constant folding
+		   here.  We have to unset processing_template_decl, to
+		   fool build_expr_from_tree() into building an actual
+		   tree.  */
+
+		int saved_processing_template_decl = processing_template_decl; 
+		processing_template_decl = 0;
+		TREE_VALUE (chain) = fold
+		  (build_expr_from_tree (TREE_VALUE (chain)));
+		processing_template_decl = saved_processing_template_decl; 
+	      }
+	    chain = TREE_CHAIN (chain);
+	  }
+
+	return lookup_template_function
+	  (tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl), targs);
       }
 
     case TREE_LIST:
diff -u save/typeck.c cp/typeck.c
--- save/typeck.c	Fri Nov  7 18:53:23 1997
+++ cp/typeck.c	Sun Nov  9 01:09:11 1997
@@ -2266,6 +2266,7 @@
      tree function, params, decl;
 {
   tree type;
+  tree explicit_targs = NULL_TREE;
   int is_method;
 
   if (function == error_mark_node)
@@ -2274,6 +2275,13 @@
   if (processing_template_decl)
     return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
 
+  /* Save explicit template arguments if found */
+  if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
+    {
+      explicit_targs = TREE_OPERAND (function, 1);
+      function = TREE_OPERAND (function, 0);
+    }
+
   type = TREE_TYPE (function);
 
   if (TREE_CODE (type) == OFFSET_TYPE
@@ -2368,6 +2376,9 @@
 	  decl = build_indirect_ref (decl, NULL_PTR);
 	}
 
+      /* Put back explicit template arguments if exist*/
+      if (explicit_targs != NULL_TREE)
+        function = lookup_template_function (function, explicit_targs);
       return build_method_call (decl, function, params,
 				NULL_TREE, LOOKUP_NORMAL);
     }
@@ -2396,7 +2407,12 @@
 	  tree val = TREE_VALUE (function);
 
 	  if (flag_ansi_overloading)
-	    return build_new_function_call (function, params, NULL_TREE);
+	    {
+	      /* Put back explicit template arguments if exist*/
+	      if (explicit_targs != NULL_TREE)
+		function = lookup_template_function (function, explicit_targs);
+	      return build_new_function_call (function, params, NULL_TREE);
+	    }
 
 	  if (TREE_CODE (val) == TEMPLATE_DECL)
 	    return build_overload_call_real


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