This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 20173
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 23 May 2006 13:47:16 -0700
- Subject: C++ PATCH: PR 20173
- Reply-to: mark at codesourcery dot com
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" }