This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR C++/26988
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 11 Feb 2007 12:18:41 -0800
- Subject: PR C++/26988
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/26988, a rejects-valid regression where we
wrongly rejected specialization of certain member template
constructors. The problem was that we were getting confused by
artificial parameters introduced into the function parameter list.
(If we had a separate C++ lowering phase, this wouldn't be an issue.)
Using the functions we've got for skipping artificial parameters
allows us to handle this correctly.
Tested on x86_64-unknown-linux-gnu, applied to mainline. I will
backport to 4.2 and 4.1.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2007-02-11 Mark Mitchell <mark@codesourcery.com>
PR c++/26988
* pt.c (determine_specialization): Use skip_artificial_parms_for.
(fn_type_unificiation): Likewise.
(get_bindings): Likewise.
2007-02-11 Mark Mitchell <mark@codesourcery.com>
PR c++/26988
* g++.dg/template/spec34.C: New test
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 121738)
+++ gcc/cp/pt.c (working copy)
@@ -1436,33 +1436,6 @@ determine_specialization (tree template_
tree decl_arg_types;
tree fn_arg_types;
- /* DECL might be a specialization of FN. */
-
- /* Adjust the type of DECL in case FN is a static member. */
- decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- if (DECL_STATIC_FUNCTION_P (fn)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- decl_arg_types = TREE_CHAIN (decl_arg_types);
-
- /* Check that the number of function parameters matches.
- For example,
- template <class T> void f(int i = 0);
- template <> void f<int>();
- The specialization f<int> is invalid but is not caught
- by get_bindings below. */
-
- fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
- if (list_length (fn_arg_types) != list_length (decl_arg_types))
- continue;
-
- /* For a non-static member function, we need to make sure that
- the const qualification is the same. This can be done by
- checking the 'this' in the argument list. */
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && !same_type_p (TREE_VALUE (fn_arg_types),
- TREE_VALUE (decl_arg_types)))
- continue;
-
/* In case of explicit specialization, we need to check if
the number of template headers appearing in the specialization
is correct. This is usually done in check_explicit_specialization,
@@ -1501,14 +1474,44 @@ determine_specialization (tree template_
(current_template_parms))))
continue;
+ /* DECL might be a specialization of FN. */
+ decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+
+ /* For a non-static member function, we need to make sure
+ that the const qualification is the same. Since
+ get_bindings does not try to merge the "this" parameter,
+ we must do the comparison explicitly. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !same_type_p (TREE_VALUE (fn_arg_types),
+ TREE_VALUE (decl_arg_types)))
+ continue;
+
+ /* Skip the "this" parameter and, for constructors of
+ classes with virtual bases, the VTT parameter. A
+ full specialization of a constructor will have a VTT
+ parameter, but a template never will. */
+ decl_arg_types
+ = skip_artificial_parms_for (decl, decl_arg_types);
+ fn_arg_types
+ = skip_artificial_parms_for (fn, fn_arg_types);
+
+ /* Check that the number of function parameters matches.
+ For example,
+ template <class T> void f(int i = 0);
+ template <> void f<int>();
+ The specialization f<int> is invalid but is not caught
+ by get_bindings below. */
+ if (list_length (fn_arg_types) != list_length (decl_arg_types))
+ 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))
+ if (compparms (fn_arg_types, decl_arg_types))
candidates = tree_cons (NULL_TREE, fn, candidates);
continue;
}
@@ -9843,10 +9846,8 @@ fn_type_unification (tree fn,
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
}
- parms = TYPE_ARG_TYPES (fntype);
/* Never do unification on the 'this' parameter. */
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
- parms = TREE_CHAIN (parms);
+ parms = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (fntype));
if (return_type)
{
@@ -11394,10 +11395,9 @@ get_bindings (tree fn, tree decl, tree e
return NULL_TREE;
}
- decl_arg_types = TYPE_ARG_TYPES (decl_type);
/* Never do unification on the 'this' parameter. */
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- decl_arg_types = TREE_CHAIN (decl_arg_types);
+ decl_arg_types = skip_artificial_parms_for (decl,
+ TYPE_ARG_TYPES (decl_type));
if (fn_type_unification (fn, explicit_args, targs,
decl_arg_types,
Index: gcc/testsuite/g++.dg/template/spec34.C
===================================================================
--- gcc/testsuite/g++.dg/template/spec34.C (revision 0)
+++ gcc/testsuite/g++.dg/template/spec34.C (revision 0)
@@ -0,0 +1,9 @@
+// PR c++/26988
+
+struct B{};
+
+struct Bar : virtual B {
+ template <typename T> Bar( T const& cast );
+};
+
+template <> Bar::Bar( int const & cast ) {}