OSDN Git Service

PR c++/20173
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 May 2006 20:45:44 +0000 (20:45 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 May 2006 20:45:44 +0000 (20:45 +0000)
* pt.c (determine_specialization): Disallow partial
specializations of templates.
PR c++/20173
* g++.dg/template/error21.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114023 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/error21.C [new file with mode: 0644]

index 4cfa827..f6bcf57 100644 (file)
@@ -1,3 +1,9 @@
+2006-05-23  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20173
+       * pt.c (determine_specialization): Disallow partial
+       specializations of templates.
+
 2006-05-22  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/27716
index 8db24ca..ca57676 100644 (file)
@@ -150,7 +150,6 @@ static tree get_template_base (tree, tree, tree, tree);
 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_id,
                          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_id,
                                      (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_id,
   /* 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 declarator,
       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 declarator,
            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 args)
       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 bb4451d..eea1b80 100644 (file)
@@ -1,3 +1,8 @@
+2006-05-23  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20173
+       * g++.dg/template/error21.C: New test.
+
 2006-05-23  Kazu Hirata  <kazu@codesourcery.com>
 
        PR target/27696
diff --git a/gcc/testsuite/g++.dg/template/error21.C b/gcc/testsuite/g++.dg/template/error21.C
new file mode 100644 (file)
index 0000000..c5f04f0
--- /dev/null
@@ -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" }