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 20173


This patch fixes an accepts-invalid regression.  We were (sort of)
permitting partial specialization of function templates, with
confusing results.

Tested on x86_64-unknown-linux-gnu, applied to mainline.  I will
backport to 4.1, once the branch reopens.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2006-05-23  Mark Mitchell  <mark@codesourcery.com>

	PR c++/20173
	* pt.c (determine_specialization): Disallow partial
	specializations of templates.

2006-05-23  Mark Mitchell  <mark@codesourcery.com>

	PR c++/20173
	* g++.dg/template/error21.C: New test.

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 113911)
+++ gcc/cp/pt.c	(working copy)
@@ -150,7 +150,6 @@ static tree get_template_base (tree, tre
 static tree try_class_unification (tree, tree, tree, tree);
 static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
 					   tree, tree);
-static tree determine_specialization (tree, tree, tree *, int, int);
 static int template_args_equal (tree, tree);
 static void tsubst_default_arguments (tree);
 static tree for_each_template_parm_r (tree *, int *, void *);
@@ -1321,6 +1320,11 @@ print_candidates (tree fns)
    template classes that appeared in the name of the function. See
    check_explicit_specialization for a more accurate description.
 
+   TSK indicates what kind of template declaration (if any) is being
+   declared.  TSK_TEMPLATE indicates that the declaration given by
+   DECL, though a FUNCTION_DECL, has template parameters, and is
+   therefore a template function.
+
    The template args (those explicitly specified and those deduced)
    are output in a newly created vector *TARGS_OUT.
 
@@ -1332,7 +1336,8 @@ determine_specialization (tree template_
 			  tree decl,
 			  tree* targs_out,
 			  int need_member_template,
-			  int template_count)
+			  int template_count,
+			  tmpl_spec_kind tsk)
 {
   tree fns;
   tree targs;
@@ -1450,6 +1455,18 @@ determine_specialization (tree template_
 				      (current_template_parms))))
 	    continue;
 
+	  /* Function templates cannot be specializations; there are
+	     no partial specializations of functions.  Therefore, if
+	     the type of DECL does not match FN, there is no
+	     match.  */
+	  if (tsk == tsk_template)
+	    {
+	      if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+			     decl_arg_types))
+		candidates = tree_cons (NULL_TREE, fn, candidates);
+	      continue;
+	    }
+
 	  /* See whether this function might be a specialization of this
 	     template.  */
 	  targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true);
@@ -1576,10 +1593,14 @@ determine_specialization (tree template_
   /* We have one, and exactly one, match.  */
   if (candidates)
     {
+      tree fn = TREE_VALUE (candidates);
+      /* DECL is a re-declaration of a template function.  */
+      if (TREE_CODE (fn) == TEMPLATE_DECL)
+	return fn;
       /* It was a specialization of an ordinary member function in a
 	 template class.  */
-      *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));
-      return DECL_TI_TEMPLATE (TREE_VALUE (candidates));
+      *targs_out = copy_node (DECL_TI_ARGS (fn));
+      return DECL_TI_TEMPLATE (fn);
     }
 
   /* It was a specialization of a template.  */
@@ -2042,7 +2063,8 @@ check_explicit_specialization (tree decl
       tmpl = determine_specialization (declarator, decl,
 				       &targs,
 				       member_specialization,
-				       template_count);
+				       template_count,
+				       tsk);
 
       if (!tmpl || tmpl == error_mark_node)
 	/* We couldn't figure out what this declaration was
@@ -2088,8 +2110,8 @@ check_explicit_specialization (tree decl
 	    revert_static_member_fn (decl);
 
 	  /* If this is a specialization of a member template of a
-	     template class.  In we want to return the TEMPLATE_DECL,
-	     not the specialization of it.  */
+	     template class, we want to return the TEMPLATE_DECL, not
+	     the specialization of it.  */
 	  if (tsk == tsk_template)
 	    {
 	      SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
@@ -5163,7 +5185,8 @@ tsubst_friend_function (tree decl, tree 
       tmpl = determine_specialization (template_id, new_friend,
 				       &new_args,
 				       /*need_member_template=*/0,
-				       TREE_VEC_LENGTH (args));
+				       TREE_VEC_LENGTH (args),
+				       tsk_none);
       return instantiate_template (tmpl, new_args, tf_error);
     }
 
Index: gcc/testsuite/g++.dg/template/error21.C
===================================================================
--- gcc/testsuite/g++.dg/template/error21.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/error21.C	(revision 0)
@@ -0,0 +1,15 @@
+// PR c++/20173
+
+template<typename AT>
+struct A{
+  template<typename T>
+  void function(T){}
+};
+
+template<>
+template<typename T>
+void A<int>::function(T){}
+
+template<>
+template<typename T>
+void A<double>::function(T*){} // { dg-error "match" }


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