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]

PR C++/26988


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 ) {}


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