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]

[lto] cp/*: Put default arguments in DECL_INITIAL of a PARM_DECL.


Hi,

Attached is a patch to put default arguments in DECL_INITIAL of a
PARM_DECL.

One of the things we'd like to do on the LTO branch is to eliminate
TREE_LIST.  As you might know, one of the biggest users of TREE_LIST
is code to handle function types.  Specifically, TYPE_ARG_TYPES points
to a linked list of TREE_LIST objects with each TREE_VALUE pointing to
a type.  Without this patch, the C++ frontend uses the TREE_PURPOSE
field of a TREE_LIST object to store a default argument for a
function.  We eventually want TREE_ARG_TYPES to point to a vector of
parameter types, not a vector of ordered pairs of a parameter type and
a default argument.

This patch frees up the TREE_PURPOSE field of a type and stores a
default argument in DECL_INITIAL of the corresponding PARM_DECL.

While the idea is very simple, changes are somewhat extensive.

To help you make sense out of this patch, I'd like to point out that
the changes in this patch fall into the following two categories in
general:

- Mechanical changes to replace TREE_PURPOSE with DECL_INITIAL

  If DECL_ARGUMENTS are not readily available in a given function,
  pass it from the parent function.  Sometimes, we need to walk the
  two lists -- TYPE_ARG_TYPES and DECL_ARGUMENTS -- at the same time.

- Merging default arguments in two FUNCTION_DECLs

  Merging default arguments with TREE_PURPOSE and that with
  DECL_INITIAL are two totally different animals.  The former must
  work around the assumption that every type is unique.  Specifically,
  if we are merging two type lists with different default arguments,
  we have to create a new type list.  With default arguments in
  DECL_INITIAL, we can simply merge default arguments between two
  functions.  This easy merging feature allows us to remove or
  simplify complicated functions like adjust_clone_args and
  copy_default_args_to_explicit_spec.

  However, the story doesn't end here.  A list of PARM_DECLs are not
  unique.  That is, two functions with the identical parameter list
  have two separate lists of PARM_DECLs.  This affects the late
  parsing of DEFAULT_ARG.  Whenever we copy a list of PARM_DECLs (via
  cloning or whatever), we have to schedule those new PARM_DECLs to be
  updated later by using DEFARG_INSTANTIATIONS.

With the summary above, I hope you'll excuse me for not explaining
every single change in this patch.

I'd like to say "thank you" to Mark Mitchell.  I received a lot of
help from him.  In fact, he's written some of the new code in this
patch.

Tested on x86_64-pc-linux-gnu with additional testcases posted at:

  http://gcc.gnu.org/ml/gcc-patches/2006-06/msg00620.html

OK to apply to the LTO branch?

Kazu Hirata

2006-06-12  Mark Mitchell  <mark@codesourcery.com>
	    Kazu Hirata  <kazu@codesourcery.com>

	Put default arguments in DECL_INITIAL of a PARM_DECL instead
	of TREE_PURPOSE of a type.
	* call.c (sufficient_parms_p): Take a list of PARM_DECLs
	instead of a list of types.
	(add_function_candidate): Adjust the call to
	sufficient_parms_p.
	(add_conv_candidate): Set viable to 0 if parameters are still
	left after the "for"loop.
	sufficient_parms_p.
	(build_over_call): Use DECL_INITIAL instead of TREE_PURPOSE
	for default arguments.
	* class.c (build_clone): Push PARM_DECLs with DEFAULT_ARG to
	DEFARG_INSTANTIATIONS.
	(adjust_clone_args): Remove.
	* cp-gimplify.c (cxx_omp_clause_apply_fn): Use DECL_INITIAL
	instead of TREE_PURPOSE for default arguments.
	* cp-tree.h (FUNCTION_FIRST_USER_PARM): Use
	DECL_TEMPLATE_RESULT if NODE is a function template.
	Remove the prototype for adjust_clone_args.
	Add a prototype for update_cloned_parms.
	* decl.c (merge_default_arguments): New.
	(duplicate_decls): Use DECL_INITIAL instead of TREE_PURPOSE
	for default arguments.  Call merge_default_arguments.  Call
	update_cloned_parms.
	(grokfndecl): Use DECL_INITIAL instead of TREE_PURPOSE for
	default arguments.
	(grokparms): Put a default argument in DECL_INITIAL instead of
	TREE_PURPOSE of a type.
	(copy_fn_p, grok_op_properties): Use DECL_INITIAL instead of
	TREE_PURPOSE for default arguments.
	(start_preparsed_function): Don't call adjust_clone_args.
	* decl2.c (Use DECL_INITIAL instead of TREE_PURPOSE for
	default arguments.
	* error.c (dump_type, dump_type_suffix, dump_function_decl):
	Adjust the call dump_parameters.
	(dump_parameters): Take parmdecls as an additional parameter.
	Use DECL_INITIAL instead of TREE_PURPOSE for default
	arguments.
	* method.c (locate_ctor): Adjust the call to
	sufficient_parms_p.
	(locate_copy): Adjust the call to sufficient_parms_p.
	* optimize.c (update_cloned_parms): New.
	(maybe_clone_body): Call update_cloned_parms.
	* parser.c (cp_parser_save_default_args,
	cp_parser_late_parsing_default_args): Use DECL_INITIAL instead
	of TREE_PURPOSE for default arguments.
	* pt.c (copy_default_args_to_explicit_spec_1): Remove.
	(copy_default_args_to_explicit_spec): Copy default arguments.
	(check_explicit_specialization, tsubst_default_arguments,
	tsubst_decl): Use DECL_INITIAL instead of TREE_PURPOSE for
	default arguments.
	(tsubst_arg_types): Don't touch DEFARG_INSTANTIATIONS.
	(fn_type_unification, unify): Adjust the call to
	type_unification_real.
	(type_unification_real): Take fn as an additional parameter.
	Use DECL_INITIAL instead of TREE_PURPOSE for default
	arguments.
	* typeck.c (commonparms): Don't merge default arguments.
	(convert_arguments): Use DECL_INITIAL instead of TREE_PURPOSE
	for default arguments.

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 114535)
+++ cp/call.c	(working copy)
@@ -437,15 +437,14 @@ null_ptr_cst_p (tree t)
   return false;
 }
 
-/* Returns nonzero if PARMLIST consists of only default parms and/or
-   ellipsis.  */
+/* Returns true iff PARM (a PARM_DECL) and all following parameters
+   have default arguments.  */
 
 bool
-sufficient_parms_p (tree parmlist)
+sufficient_parms_p (tree parm)
 {
-  for (; parmlist && parmlist != void_list_node;
-       parmlist = TREE_CHAIN (parmlist))
-    if (!TREE_PURPOSE (parmlist))
+  for (; parm; parm = TREE_CHAIN (parm))
+    if (!DECL_INITIAL (parm))
       return false;
   return true;
 }
@@ -1313,9 +1312,10 @@ add_function_candidate (struct z_candida
 			int flags)
 {
   tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
+  tree decllist = DECL_ARGUMENTS (fn);
   int i, len;
   conversion **convs;
-  tree parmnode, argnode;
+  tree parmnode, argnode, declnode;
   tree orig_arglist;
   int viable = 1;
 
@@ -1329,6 +1329,7 @@ add_function_candidate (struct z_candida
   if (DECL_CONSTRUCTOR_P (fn))
     {
       parmlist = skip_artificial_parms_for (fn, parmlist);
+      decllist = skip_artificial_parms_for (fn, decllist);
       orig_arglist = arglist;
       arglist = skip_artificial_parms_for (fn, arglist);
     }
@@ -1346,18 +1347,21 @@ add_function_candidate (struct z_candida
      us to produce an ill-formed template instantiation.  */
 
   parmnode = parmlist;
+  declnode = decllist;
   for (i = 0; i < len; ++i)
     {
       if (parmnode == NULL_TREE || parmnode == void_list_node)
 	break;
       parmnode = TREE_CHAIN (parmnode);
+      if (declnode)
+	declnode = TREE_CHAIN (declnode);
     }
 
   if (i < len && parmnode)
     viable = 0;
 
   /* Make sure there are default args for the rest of the parms.  */
-  else if (!sufficient_parms_p (parmnode))
+  else if (!sufficient_parms_p (declnode))
     viable = 0;
 
   if (! viable)
@@ -1509,7 +1513,7 @@ add_conv_candidate (struct z_candidate *
   if (i < len)
     viable = 0;
 
-  if (!sufficient_parms_p (parmnode))
+  if (parmnode && parmnode != void_list_node)
     viable = 0;
 
   return add_candidate (candidates, totype, arglist, len, convs,
@@ -4686,6 +4690,7 @@ build_over_call (struct z_candidate *can
   conversion *conv;
   tree converted_args = NULL_TREE;
   tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+  tree decl = DECL_ARGUMENTS (fn);
   tree arg, val;
   int i = 0;
   int is_method = 0;
@@ -4761,6 +4766,7 @@ build_over_call (struct z_candidate *can
       converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
       arg = TREE_CHAIN (arg);
       parm = TREE_CHAIN (parm);
+      decl = TREE_CHAIN (decl);
       /* We should never try to call the abstract constructor.  */
       gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn));
 
@@ -4770,6 +4776,7 @@ build_over_call (struct z_candidate *can
 	    (NULL_TREE, TREE_VALUE (arg), converted_args);
 	  arg = TREE_CHAIN (arg);
 	  parm = TREE_CHAIN (parm);
+	  decl = TREE_CHAIN (decl);
 	}
     }
   /* Bypass access control for 'this' parameter.  */
@@ -4814,6 +4821,7 @@ build_over_call (struct z_candidate *can
       converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);
       parm = TREE_CHAIN (parm);
       arg = TREE_CHAIN (arg);
+      decl = TREE_CHAIN (decl);
       ++i;
       is_method = 1;
     }
@@ -4829,14 +4837,17 @@ build_over_call (struct z_candidate *can
 
       val = convert_for_arg_passing (type, val);
       converted_args = tree_cons (NULL_TREE, val, converted_args);
+      if (decl)
+	decl = TREE_CHAIN (decl);
     }
 
   /* Default arguments */
-  for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
+  for (; parm && parm != void_list_node;
+       parm = TREE_CHAIN (parm), decl = TREE_CHAIN (decl), i++)
     converted_args
       = tree_cons (NULL_TREE,
 		   convert_default_arg (TREE_VALUE (parm),
-					TREE_PURPOSE (parm),
+					DECL_INITIAL (decl),
 					fn, i - is_method),
 		   converted_args);
 
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 114535)
+++ cp/class.c	(working copy)
@@ -3805,6 +3805,14 @@ build_clone (tree fn, tree name)
 
       for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
 	{
+	  tree initial = DECL_INITIAL (parms);
+
+	  /* Add PARMS to DEFARG_INSTANTIATIONS of its DECL_INITIAL if
+	     late parsing is required.  */
+	  if (initial && TREE_CODE (initial) == DEFAULT_ARG)
+	    VEC_safe_push (tree, gc,
+			   DEFARG_INSTANTIATIONS (initial), parms);
+
 	  DECL_CONTEXT (parms) = clone;
 	  cxx_dup_lang_specific_decl (parms);
 	}
@@ -3891,79 +3899,6 @@ clone_function_decl (tree fn, int update
   DECL_ABSTRACT (fn) = 1;
 }
 
-/* DECL is an in charge constructor, which is being defined. This will
-   have had an in class declaration, from whence clones were
-   declared. An out-of-class definition can specify additional default
-   arguments. As it is the clones that are involved in overload
-   resolution, we must propagate the information from the DECL to its
-   clones.  */
-
-void
-adjust_clone_args (tree decl)
-{
-  tree clone;
-
-  for (clone = TREE_CHAIN (decl); clone && DECL_CLONED_FUNCTION (clone);
-       clone = TREE_CHAIN (clone))
-    {
-      tree orig_clone_parms = TYPE_ARG_TYPES (TREE_TYPE (clone));
-      tree orig_decl_parms = TYPE_ARG_TYPES (TREE_TYPE (decl));
-      tree decl_parms, clone_parms;
-
-      clone_parms = orig_clone_parms;
-
-      /* Skip the 'this' parameter.  */
-      orig_clone_parms = TREE_CHAIN (orig_clone_parms);
-      orig_decl_parms = TREE_CHAIN (orig_decl_parms);
-
-      if (DECL_HAS_IN_CHARGE_PARM_P (decl))
-	orig_decl_parms = TREE_CHAIN (orig_decl_parms);
-      if (DECL_HAS_VTT_PARM_P (decl))
-	orig_decl_parms = TREE_CHAIN (orig_decl_parms);
-
-      clone_parms = orig_clone_parms;
-      if (DECL_HAS_VTT_PARM_P (clone))
-	clone_parms = TREE_CHAIN (clone_parms);
-
-      for (decl_parms = orig_decl_parms; decl_parms;
-	   decl_parms = TREE_CHAIN (decl_parms),
-	     clone_parms = TREE_CHAIN (clone_parms))
-	{
-	  gcc_assert (same_type_p (TREE_TYPE (decl_parms),
-				   TREE_TYPE (clone_parms)));
-
-	  if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
-	    {
-	      /* A default parameter has been added. Adjust the
-		 clone's parameters.  */
-	      tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
-	      tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
-	      tree type;
-
-	      clone_parms = orig_decl_parms;
-
-	      if (DECL_HAS_VTT_PARM_P (clone))
-		{
-		  clone_parms = tree_cons (TREE_PURPOSE (orig_clone_parms),
-					   TREE_VALUE (orig_clone_parms),
-					   clone_parms);
-		  TREE_TYPE (clone_parms) = TREE_TYPE (orig_clone_parms);
-		}
-	      type = build_method_type_directly (basetype,
-						 TREE_TYPE (TREE_TYPE (clone)),
-						 clone_parms);
-	      if (exceptions)
-		type = build_exception_variant (type, exceptions);
-	      TREE_TYPE (clone) = type;
-
-	      clone_parms = NULL_TREE;
-	      break;
-	    }
-	}
-      gcc_assert (!clone_parms);
-    }
-}
-
 /* For each of the constructors and destructors in T, create an
    in-charge and not-in-charge variant.  */
 
Index: cp/cp-gimplify.c
===================================================================
--- cp/cp-gimplify.c	(revision 114535)
+++ cp/cp-gimplify.c	(working copy)
@@ -712,15 +712,19 @@ cp_genericize (tree fndecl)
 static tree
 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
 {
-  tree defparm, parm;
+  tree defparm, parm, decl;
   int i;
 
   if (fn == NULL)
     return NULL;
 
   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
+  decl = TREE_CHAIN (DECL_ARGUMENTS (fn));
   if (arg2)
-    defparm = TREE_CHAIN (defparm);
+    {
+      defparm = TREE_CHAIN (defparm);
+      decl = TREE_CHAIN (decl);
+    }
 
   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
     {
@@ -769,9 +773,11 @@ cxx_omp_clause_apply_fn (tree fn, tree a
 	t = tree_cons (NULL, p2, t);
       /* Handle default arguments.  */
       i = 1 + (arg2 != NULL);
-      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
+      for (parm = defparm;
+	   parm != void_list_node;
+	   parm = TREE_CHAIN (parm), decl = TREE_CHAIN (decl))
 	t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
-						  TREE_PURPOSE (parm),
+						  DECL_INITIAL (decl),
 						  fn, i++), t);
       t = build_call (fn, nreverse (t));
       append_to_statement_list (t, &ret);
@@ -802,9 +808,11 @@ cxx_omp_clause_apply_fn (tree fn, tree a
 	t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
       /* Handle default arguments.  */
       i = 1 + (arg2 != NULL);
-      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
+      for (parm = defparm;
+	   parm != void_list_node;
+	   parm = TREE_CHAIN (parm), decl = TREE_CHAIN (decl))
 	t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
-						  TREE_PURPOSE (parm),
+						  DECL_INITIAL (decl),
 						  fn, i++), t);
       return build_call (fn, nreverse (t));
     }
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 114535)
+++ cp/cp-tree.h	(working copy)
@@ -930,8 +930,11 @@ enum languages { lang_c, lang_cplusplus,
   skip_artificial_parms_for ((NODE), TYPE_ARG_TYPES (TREE_TYPE (NODE)))
 
 /* Similarly, but for DECL_ARGUMENTS.  */
-#define FUNCTION_FIRST_USER_PARM(NODE) \
-  skip_artificial_parms_for ((NODE), DECL_ARGUMENTS (NODE))
+#define FUNCTION_FIRST_USER_PARM(NODE)						\
+  skip_artificial_parms_for ((NODE),						\
+			     DECL_ARGUMENTS (DECL_FUNCTION_TEMPLATE_P (NODE)	\
+					     ? DECL_TEMPLATE_RESULT (NODE)	\
+					     : (NODE)))
 
 #define PROMOTES_TO_AGGR_TYPE(NODE, CODE)	\
   (((CODE) == TREE_CODE (NODE)			\
@@ -3795,7 +3798,6 @@ extern tree build_expr_type_conversion		
 extern tree type_promotes_to			(tree);
 extern tree perform_qualification_conversions	(tree, tree);
 extern void clone_function_decl			(tree, int);
-extern void adjust_clone_args			(tree);
 
 /* decl.c */
 extern tree poplevel				(int, int, int);
@@ -4020,6 +4022,7 @@ extern tree make_alias_for			(tree, tree
 
 /* In optimize.c */
 extern bool maybe_clone_body			(tree);
+extern void update_cloned_parms			(tree, tree, bool);
 
 /* in pt.c */
 extern void check_template_shadow		(tree);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 114535)
+++ cp/decl.c	(working copy)
@@ -1095,6 +1095,25 @@ check_redeclaration_exception_specificat
     }
 }
 
+/* Merge default arguments for OLD_FN and NEW_FN.  When this routine
+   returns, both functions will have the same default arguments.  */
+
+static void
+merge_default_arguments (tree old_fn, tree new_fn)
+{
+  tree oldparm, newparm;
+
+  for (oldparm = DECL_ARGUMENTS (old_fn),
+	 newparm = DECL_ARGUMENTS (new_fn);
+       oldparm && newparm;
+       oldparm = TREE_CHAIN (oldparm),
+	 newparm = TREE_CHAIN (newparm))
+    if (DECL_INITIAL (oldparm) && !DECL_INITIAL (newparm))
+      DECL_INITIAL (newparm) = DECL_INITIAL (oldparm);
+    else
+      DECL_INITIAL (oldparm) = DECL_INITIAL (newparm);
+}
+
 /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
    If the redeclaration is invalid, a diagnostic is issued, and the
    error_mark_node is returned.  Otherwise, OLDDECL is returned.
@@ -1476,19 +1495,19 @@ duplicate_decls (tree newdecl, tree oldd
 	;
       else if (TREE_CODE (olddecl) == FUNCTION_DECL)
 	{
-	  tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
-	  tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
+	  tree t1 = DECL_ARGUMENTS (olddecl);
+	  tree t2 = DECL_ARGUMENTS (newdecl);
 	  int i = 1;
 
 	  if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
 	    t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
 
-	  for (; t1 && t1 != void_list_node;
+	  for (; t1 && t2;
 	       t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
-	    if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
+	    if (DECL_INITIAL (t1) && DECL_INITIAL (t2))
 	      {
-		if (1 == simple_cst_equal (TREE_PURPOSE (t1),
-					   TREE_PURPOSE (t2)))
+		if (1 == simple_cst_equal (DECL_INITIAL (t1),
+					   DECL_INITIAL (t2)))
 		  {
 		    pedwarn ("default argument given for parameter %d of %q#D",
 			     i, newdecl);
@@ -1601,6 +1620,7 @@ duplicate_decls (tree newdecl, tree oldd
 	    |= DECL_INLINE (new_result);
 	  DECL_DECLARED_INLINE_P (old_result)
 	    |= DECL_DECLARED_INLINE_P (new_result);
+	  merge_default_arguments (old_result, new_result);
 	  check_redeclaration_exception_specification (newdecl, olddecl);
 	}
 
@@ -1659,7 +1679,10 @@ duplicate_decls (tree newdecl, tree oldd
       /* Do this after calling `merge_types' so that default
 	 parameters don't confuse us.  */
       else if (TREE_CODE (newdecl) == FUNCTION_DECL)
-	check_redeclaration_exception_specification (newdecl, olddecl);
+	{
+	  merge_default_arguments (olddecl, newdecl);
+	  check_redeclaration_exception_specification (newdecl, olddecl);
+	}
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
 
       /* Lay the type out, unless already done.  */
@@ -2022,6 +2045,12 @@ duplicate_decls (tree newdecl, tree oldd
 	      && TREE_STATIC (olddecl))))
     make_decl_rtl (olddecl);
 
+  {
+    tree clone;
+    FOR_EACH_CLONE (clone, olddecl)
+      update_cloned_parms (clone, newdecl, false);
+  }
+
   /* The NEWDECL will no longer be needed.  Because every out-of-class
      declaration of a member results in a call to duplicate_decls,
      freeing these nodes represents in a significant savings.  */
@@ -5929,9 +5958,9 @@ grokfndecl (tree ctype,
 		      || TREE_CODE (fns) == OVERLOAD);
 	  DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
 
-	  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
-	    if (TREE_PURPOSE (t)
-		&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+	  for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
+	    if (DECL_INITIAL (t)
+		&& TREE_CODE (DECL_INITIAL (t)) == DEFAULT_ARG)
 	    {
 	      error ("default arguments are not allowed in declaration "
 		     "of friend template specialization %qD",
@@ -8234,12 +8263,13 @@ grokdeclarator (const cp_declarator *dec
 		   any subsequent parameters have default arguments.
 		   Ignore any compiler-added parms.  */
 		tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
+		tree parm_decls = FUNCTION_FIRST_USER_PARM (decl);
 
 		if (arg_types == void_list_node
 		    || (arg_types
 			&& TREE_CHAIN (arg_types)
 			&& TREE_CHAIN (arg_types) != void_list_node
-			&& !TREE_PURPOSE (TREE_CHAIN (arg_types))))
+			&& !DECL_INITIAL (TREE_CHAIN (parm_decls))))
 		  DECL_NONCONVERTING_P (decl) = 1;
 	      }
 	  }
@@ -8781,7 +8811,8 @@ grokparms (cp_parameter_declarator *firs
 
       TREE_CHAIN (decl) = decls;
       decls = decl;
-      result = tree_cons (init, type, result);
+      DECL_INITIAL (decl) = init;
+      result = tree_cons (NULL_TREE, type, result);
     }
   decls = nreverse (decls);
   result = nreverse (result);
@@ -8814,7 +8845,7 @@ grokparms (cp_parameter_declarator *firs
 int
 copy_fn_p (tree d)
 {
-  tree args;
+  tree args, parm_decls;
   tree arg_type;
   int result = 1;
 
@@ -8832,6 +8863,7 @@ copy_fn_p (tree d)
     return 0;
 
   args = FUNCTION_FIRST_USER_PARMTYPE (d);
+  parm_decls = FUNCTION_FIRST_USER_PARM (d);
   if (!args)
     return 0;
 
@@ -8854,8 +8886,11 @@ copy_fn_p (tree d)
     return 0;
 
   args = TREE_CHAIN (args);
+  if (parm_decls)
+    parm_decls = TREE_CHAIN (parm_decls);
 
-  if (args && args != void_list_node && !TREE_PURPOSE (args))
+  if (args && args != void_list_node
+      && parm_decls && !DECL_INITIAL (parm_decls))
     /* There are more non-optional args.  */
     return 0;
 
@@ -8891,7 +8926,7 @@ void grok_special_member_properties (tre
 	  if (ctor > 1)
 	    TYPE_HAS_CONST_INIT_REF (class_type) = 1;
 	}
-      else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
+      else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARM (decl)))
 	TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
     }
   else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
@@ -9071,6 +9106,8 @@ grok_op_properties (tree decl, bool comp
     TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
   else
     {
+      tree parm_decls;
+
       /* An operator function must either be a non-static member function
 	 or have at least one parameter of a class, a reference to a class,
 	 an enumeration, or a reference to an enumeration.  13.4.0.6 */
@@ -9301,11 +9338,12 @@ grok_op_properties (tree decl, bool comp
 	warning (OPT_Weffc__, "%qD should return by value", decl);
 
       /* [over.oper]/8 */
-      for (; argtypes && argtypes != void_list_node;
-	  argtypes = TREE_CHAIN (argtypes))
-	if (TREE_PURPOSE (argtypes))
+      for (parm_decls = DECL_ARGUMENTS (decl);
+	   parm_decls;
+	   parm_decls = TREE_CHAIN (parm_decls))
+	if (DECL_INITIAL (parm_decls))
 	  {
-	    TREE_PURPOSE (argtypes) = NULL_TREE;
+	    DECL_INITIAL (parm_decls) = NULL_TREE;
 	    if (operator_code == POSTINCREMENT_EXPR
 		|| operator_code == POSTDECREMENT_EXPR)
 	      {
@@ -10294,12 +10332,6 @@ start_preparsed_function (tree decl1, tr
       && lookup_attribute ("noinline", attrs))
     warning (0, "inline function %q+D given attribute noinline", decl1);
 
-  if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
-    /* This is a constructor, we must ensure that any default args
-       introduced by this definition are propagated to the clones
-       now. The clones are used directly in overload resolution.  */
-    adjust_clone_args (decl1);
-
   /* Sometimes we don't notice that a function is a static member, and
      build a METHOD_TYPE for it.  Fix that up now.  */
   if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 114535)
+++ cp/decl2.c	(working copy)
@@ -3215,17 +3215,18 @@ build_offset_ref_call_from_tree (tree fn
 void
 check_default_args (tree x)
 {
-  tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
+  tree arg = DECL_ARGUMENTS (DECL_FUNCTION_TEMPLATE_P (x)
+			     ? DECL_TEMPLATE_RESULT (x) : x);
   bool saw_def = false;
   int i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
   for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
     {
-      if (TREE_PURPOSE (arg))
+      if (DECL_INITIAL (arg))
 	saw_def = true;
       else if (saw_def)
 	{
 	  error ("default argument missing for parameter %P of %q+#D", i, x);
-	  TREE_PURPOSE (arg) = error_mark_node;
+	  DECL_INITIAL (arg) = error_mark_node;
 	}
     }
 }
Index: cp/error.c
===================================================================
--- cp/error.c	(revision 114535)
+++ cp/error.c	(working copy)
@@ -68,7 +68,7 @@ static void dump_type_suffix (tree, int)
 static void dump_function_name (tree, int);
 static void dump_expr_list (tree, int);
 static void dump_global_iord (tree);
-static void dump_parameters (tree, int);
+static void dump_parameters (tree, tree, int);
 static void dump_exception_spec (tree, int);
 static void dump_template_argument (tree, int);
 static void dump_template_argument_list (tree, int);
@@ -264,7 +264,7 @@ dump_type (tree t, int flags)
 
     case TREE_LIST:
       /* A list of function parms.  */
-      dump_parameters (t, flags);
+      dump_parameters (t, NULL_TREE, flags);
       break;
 
     case IDENTIFIER_NODE:
@@ -606,7 +606,7 @@ dump_type_suffix (tree t, int flags)
 
 	/* Function pointers don't have default args.  Not in standard C++,
 	   anyway; they may in g++, but we'll just pretend otherwise.  */
-	dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
+	dump_parameters (arg, NULL_TREE, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
 
 	if (TREE_CODE (t) == METHOD_TYPE)
 	  pp_cxx_cv_qualifier_seq
@@ -982,6 +982,7 @@ dump_function_decl (tree t, int flags)
 {
   tree fntype;
   tree parmtypes;
+  tree parmdecls;
   tree cname = NULL_TREE;
   tree template_args = NULL_TREE;
   tree template_parms = NULL_TREE;
@@ -1006,6 +1007,7 @@ dump_function_decl (tree t, int flags)
 
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
+  parmdecls = FUNCTION_FIRST_USER_PARM (t);
 
   if (DECL_CLASS_SCOPE_P (t))
     cname = DECL_CONTEXT (t);
@@ -1040,7 +1042,7 @@ dump_function_decl (tree t, int flags)
 
   if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
     {
-      dump_parameters (parmtypes, flags);
+      dump_parameters (parmtypes, parmdecls, flags);
 
       if (TREE_CODE (fntype) == METHOD_TYPE)
 	{
@@ -1076,7 +1078,7 @@ dump_function_decl (tree t, int flags)
    already been removed.  */
 
 static void
-dump_parameters (tree parmtypes, int flags)
+dump_parameters (tree parmtypes, tree parmdecls, int flags)
 {
   int first;
 
@@ -1095,13 +1097,17 @@ dump_parameters (tree parmtypes, int fla
 	}
       dump_type (TREE_VALUE (parmtypes), flags);
 
-      if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
+      if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS)
+	  && parmdecls
+	  && DECL_INITIAL (parmdecls))
 	{
 	  pp_cxx_whitespace (cxx_pp);
 	  pp_equal (cxx_pp);
 	  pp_cxx_whitespace (cxx_pp);
-	  dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
+	  dump_expr (DECL_INITIAL (parmdecls), flags | TFF_EXPR_IN_PARENS);
 	}
+      if (parmdecls)
+	parmdecls = TREE_CHAIN (parmdecls);
     }
 
   pp_cxx_right_paren (cxx_pp);
Index: cp/method.c
===================================================================
--- cp/method.c	(revision 114535)
+++ cp/method.c	(working copy)
@@ -885,11 +885,7 @@ locate_ctor (tree type, void *client ATT
   for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
     {
       tree fn = OVL_CURRENT (fns);
-      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
-
-      parms = skip_artificial_parms_for (fn, parms);
-
-      if (sufficient_parms_p (parms))
+      if (sufficient_parms_p (FUNCTION_FIRST_USER_PARM (fn)))
 	return fn;
     }
   gcc_unreachable ();
@@ -935,6 +931,8 @@ locate_copy (tree type, void *client_)
     {
       tree fn = OVL_CURRENT (fns);
       tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
+      tree decls = DECL_ARGUMENTS (DECL_FUNCTION_TEMPLATE_P (fn)
+				   ? DECL_TEMPLATE_RESULT (fn) : fn);
       tree src_type;
       int excess;
       int quals;
@@ -942,10 +940,11 @@ locate_copy (tree type, void *client_)
       parms = skip_artificial_parms_for (fn, parms);
       if (!parms)
 	continue;
+      decls = skip_artificial_parms_for (fn, decls);
       src_type = non_reference (TREE_VALUE (parms));
       if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
 	continue;
-      if (!sufficient_parms_p (TREE_CHAIN (parms)))
+      if (!sufficient_parms_p (TREE_CHAIN (decls)))
 	continue;
       quals = cp_type_quals (src_type);
       if (client->quals & ~quals)
Index: cp/optimize.c
===================================================================
--- cp/optimize.c	(revision 114535)
+++ cp/optimize.c	(working copy)
@@ -71,6 +71,40 @@ update_cloned_parm (tree parm, tree clon
   TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
 }
 
+/* Update the PARM_DECLs associated with the CLONE to match the
+   function from which it was cloned.  */
+
+void
+update_cloned_parms (tree clone, tree fn, bool first)
+{
+  tree parm, clone_parm;
+
+  /* Adjust the parameter names and locations.  */
+  parm = DECL_ARGUMENTS (fn);
+  clone_parm = DECL_ARGUMENTS (clone);
+  /* Update the `this' parameter, which is always first.  */
+  update_cloned_parm (parm, clone_parm, first);
+  parm = TREE_CHAIN (parm);
+  clone_parm = TREE_CHAIN (clone_parm);
+  if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+    parm = TREE_CHAIN (parm);
+  if (DECL_HAS_VTT_PARM_P (fn))
+    parm = TREE_CHAIN (parm);
+  if (DECL_HAS_VTT_PARM_P (clone))
+    clone_parm = TREE_CHAIN (clone_parm);
+  for (; parm;
+       parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
+    {
+      if (DECL_INITIAL (parm) && !DECL_INITIAL (clone_parm))
+	DECL_INITIAL (clone_parm) = DECL_INITIAL (parm);
+      else
+	DECL_INITIAL (parm) = DECL_INITIAL (clone_parm);
+
+      /* Update this parameter.  */
+      update_cloned_parm (parm, clone_parm, first);
+    }
+}
+
 /* FN is a function that has a complete body.  Clone the body as
    necessary.  Returns nonzero if there's no longer any need to
    process the main body.  */
@@ -115,23 +149,7 @@ maybe_clone_body (tree fn)
       DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
       DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
 
-      /* Adjust the parameter names and locations.  */
-      parm = DECL_ARGUMENTS (fn);
-      clone_parm = DECL_ARGUMENTS (clone);
-      /* Update the `this' parameter, which is always first.  */
-      update_cloned_parm (parm, clone_parm, first);
-      parm = TREE_CHAIN (parm);
-      clone_parm = TREE_CHAIN (clone_parm);
-      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
-	parm = TREE_CHAIN (parm);
-      if (DECL_HAS_VTT_PARM_P (fn))
-	parm = TREE_CHAIN (parm);
-      if (DECL_HAS_VTT_PARM_P (clone))
-	clone_parm = TREE_CHAIN (clone_parm);
-      for (; parm;
-	   parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
-	/* Update this parameter.  */
-	update_cloned_parm (parm, clone_parm, first);
+      update_cloned_parms (clone, fn, first);
 
       /* Start processing the function.  */
       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 114535)
+++ cp/parser.c	(working copy)
@@ -15921,10 +15921,10 @@ cp_parser_save_default_args (cp_parser* 
 {
   tree probe;
 
-  for (probe = TYPE_ARG_TYPES (TREE_TYPE (decl));
+  for (probe = DECL_ARGUMENTS (decl);
        probe;
        probe = TREE_CHAIN (probe))
-    if (TREE_PURPOSE (probe))
+    if (DECL_INITIAL (probe))
       {
 	TREE_PURPOSE (parser->unparsed_functions_queues)
 	  = tree_cons (current_class_type, decl,
@@ -15942,6 +15942,7 @@ static void
 cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 {
   bool saved_local_variables_forbidden_p;
+  tree type;
   tree parm;
 
   /* While we're parsing the default args, we might (due to the
@@ -15956,12 +15957,12 @@ cp_parser_late_parsing_default_args (cp_
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
   parser->local_variables_forbidden_p = true;
 
-  for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
-       parm;
-       parm = TREE_CHAIN (parm))
+  for (type = TYPE_ARG_TYPES (TREE_TYPE (fn)), parm = DECL_ARGUMENTS (fn);
+       type && parm;
+       type = TREE_CHAIN (type), parm = TREE_CHAIN (parm))
     {
       cp_token_cache *tokens;
-      tree default_arg = TREE_PURPOSE (parm);
+      tree default_arg = DECL_INITIAL (parm);
       tree parsed_arg;
       VEC(tree,gc) *insts;
       tree copy;
@@ -15984,14 +15985,14 @@ cp_parser_late_parsing_default_args (cp_
       parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
 
       if (!processing_template_decl)
-	parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
+	parsed_arg = check_default_argument (TREE_VALUE (type), parsed_arg);
       
-      TREE_PURPOSE (parm) = parsed_arg;
+      DECL_INITIAL (parm) = parsed_arg;
 
       /* Update any instantiations we've already created.  */
       for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0;
 	   VEC_iterate (tree, insts, ix, copy); ix++)
-	TREE_PURPOSE (copy) = parsed_arg;
+	DECL_INITIAL (copy) = parsed_arg;
 
       /* If the token stream has not been completely used up, then
 	 there was extra junk after the end of the default
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 114535)
+++ cp/pt.c	(working copy)
@@ -111,7 +111,7 @@ static tree add_to_template_args (tree, 
 static tree add_outermost_template_args (tree, tree);
 static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
-static int  type_unification_real (tree, tree, tree, tree,
+static int  type_unification_real (tree, tree, tree, tree, tree,
 				   int, unification_kind_t, int);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
@@ -154,7 +154,6 @@ static tree determine_specialization (tr
 static int template_args_equal (tree, tree);
 static void tsubst_default_arguments (tree);
 static tree for_each_template_parm_r (tree *, int *, void *);
-static tree copy_default_args_to_explicit_spec_1 (tree, tree);
 static void copy_default_args_to_explicit_spec (tree);
 static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
 static int eq_local_specializations (const void *, const void *);
@@ -1596,33 +1595,6 @@ determine_specialization (tree template_
   return TREE_VALUE (templates);
 }
 
-/* Returns a chain of parameter types, exactly like the SPEC_TYPES,
-   but with the default argument values filled in from those in the
-   TMPL_TYPES.  */
-
-static tree
-copy_default_args_to_explicit_spec_1 (tree spec_types,
-				      tree tmpl_types)
-{
-  tree new_spec_types;
-
-  if (!spec_types)
-    return NULL_TREE;
-
-  if (spec_types == void_list_node)
-    return void_list_node;
-
-  /* Substitute into the rest of the list.  */
-  new_spec_types =
-    copy_default_args_to_explicit_spec_1 (TREE_CHAIN (spec_types),
-					  TREE_CHAIN (tmpl_types));
-
-  /* Add the default argument for this parameter.  */
-  return hash_tree_cons (TREE_PURPOSE (tmpl_types),
-			 TREE_VALUE (spec_types),
-			 new_spec_types);
-}
-
 /* DECL is an explicit specialization.  Replicate default arguments
    from the template it specializes.  (That way, code like:
 
@@ -1638,80 +1610,16 @@ static void
 copy_default_args_to_explicit_spec (tree decl)
 {
   tree tmpl;
-  tree spec_types;
-  tree tmpl_types;
-  tree new_spec_types;
-  tree old_type;
-  tree new_type;
-  tree t;
-  tree object_type = NULL_TREE;
-  tree in_charge = NULL_TREE;
-  tree vtt = NULL_TREE;
+  tree tmpl_fn;
+  tree from, to;
 
   /* See if there's anything we need to do.  */
   tmpl = DECL_TI_TEMPLATE (decl);
-  tmpl_types = TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (tmpl)));
-  for (t = tmpl_types; t; t = TREE_CHAIN (t))
-    if (TREE_PURPOSE (t))
-      break;
-  if (!t)
-    return;
-
-  old_type = TREE_TYPE (decl);
-  spec_types = TYPE_ARG_TYPES (old_type);
-
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
-    {
-      /* Remove the this pointer, but remember the object's type for
-	 CV quals.  */
-      object_type = TREE_TYPE (TREE_VALUE (spec_types));
-      spec_types = TREE_CHAIN (spec_types);
-      tmpl_types = TREE_CHAIN (tmpl_types);
-
-      if (DECL_HAS_IN_CHARGE_PARM_P (decl))
-	{
-	  /* DECL may contain more parameters than TMPL due to the extra
-	     in-charge parameter in constructors and destructors.  */
-	  in_charge = spec_types;
-	  spec_types = TREE_CHAIN (spec_types);
-	}
-      if (DECL_HAS_VTT_PARM_P (decl))
-	{
-	  vtt = spec_types;
-	  spec_types = TREE_CHAIN (spec_types);
-	}
-    }
-
-  /* Compute the merged default arguments.  */
-  new_spec_types =
-    copy_default_args_to_explicit_spec_1 (spec_types, tmpl_types);
-
-  /* Compute the new FUNCTION_TYPE.  */
-  if (object_type)
-    {
-      if (vtt)
-	new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
-					 TREE_VALUE (vtt),
-					 new_spec_types);
-
-      if (in_charge)
-	/* Put the in-charge parameter back.  */
-	new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),
-					 TREE_VALUE (in_charge),
-					 new_spec_types);
-
-      new_type = build_method_type_directly (object_type,
-					     TREE_TYPE (old_type),
-					     new_spec_types);
-    }
-  else
-    new_type = build_function_type (TREE_TYPE (old_type),
-				    new_spec_types);
-  new_type = cp_build_type_attribute_variant (new_type,
-					      TYPE_ATTRIBUTES (old_type));
-  new_type = build_exception_variant (new_type,
-				      TYPE_RAISES_EXCEPTIONS (old_type));
-  TREE_TYPE (decl) = new_type;
+  tmpl_fn = DECL_TEMPLATE_RESULT (tmpl);
+  for (from = DECL_ARGUMENTS (tmpl_fn), to = DECL_ARGUMENTS (decl);
+       from && to;
+       from = TREE_CHAIN (from), to = TREE_CHAIN (to))
+    DECL_INITIAL (to) = DECL_INITIAL (from);
 }
 
 /* Check to see if the function just declared, as indicated in
@@ -1875,9 +1783,9 @@ check_explicit_specialization (tree decl
 
   if (specialization || member_specialization)
     {
-      tree t = TYPE_ARG_TYPES (TREE_TYPE (decl));
+      tree t = DECL_ARGUMENTS (decl);
       for (; t; t = TREE_CHAIN (t))
-	if (TREE_PURPOSE (t))
+	if (DECL_INITIAL (t))
 	  {
 	    pedwarn
 	      ("default argument specified in explicit specialization");
@@ -6188,6 +6096,7 @@ static void
 tsubst_default_arguments (tree fn)
 {
   tree arg;
+  tree type;
   tree tmpl_args;
 
   tmpl_args = DECL_TI_ARGS (fn);
@@ -6197,13 +6106,13 @@ tsubst_default_arguments (tree fn)
   if (uses_template_parms (tmpl_args))
     return;
 
-  for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
-       arg;
-       arg = TREE_CHAIN (arg))
-    if (TREE_PURPOSE (arg))
-      TREE_PURPOSE (arg) = tsubst_default_argument (fn,
-						    TREE_VALUE (arg),
-						    TREE_PURPOSE (arg));
+  for (type = TYPE_ARG_TYPES (TREE_TYPE (fn)), arg = DECL_ARGUMENTS (fn);
+       type && arg;
+       type = TREE_CHAIN (type), arg = TREE_CHAIN (arg))
+    if (DECL_INITIAL (arg))
+      DECL_INITIAL (arg) = tsubst_default_argument (fn,
+						    TREE_VALUE (type),
+						    DECL_INITIAL (arg));
 }
 
 /* Substitute the ARGS into the T, which is a _DECL.  Return the
@@ -6573,18 +6482,26 @@ tsubst_decl (tree t, tree args, tsubst_f
 
     case PARM_DECL:
       {
-	tree type;
+	tree type, initial;
 
 	r = copy_node (t);
 	if (DECL_TEMPLATE_PARM_P (t))
 	  SET_DECL_TEMPLATE_PARM_P (r);
 
+	/* Add PARMS to DEFARG_INSTANTIATIONS of its DECL_INITIAL if
+	   late parsing is required.  */
+	initial = DECL_INITIAL (r);
+	if (initial && TREE_CODE (initial) == DEFAULT_ARG)
+	  VEC_safe_push (tree, gc,
+			 DEFARG_INSTANTIATIONS (initial), r);
+
+
 	type = tsubst (TREE_TYPE (t), args, complain, in_decl);
 	type = type_decays_to (type);
 	TREE_TYPE (r) = type;
 	cp_apply_type_quals_to_decl (cp_type_quals (type), r);
 
-	if (DECL_INITIAL (r))
+	if (DECL_TEMPLATE_PARM_P (r) && DECL_INITIAL (r))
 	  {
 	    if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
 	      DECL_INITIAL (r) = TREE_TYPE (r);
@@ -6781,7 +6698,6 @@ tsubst_arg_types (tree arg_types,
 {
   tree remaining_arg_types;
   tree type;
-  tree default_arg;
   tree result = NULL_TREE;
 
   if (!arg_types || arg_types == void_list_node)
@@ -6810,22 +6726,7 @@ tsubst_arg_types (tree arg_types,
      top-level qualifiers as required.  */
   type = TYPE_MAIN_VARIANT (type_decays_to (type));
 
-  /* We do not substitute into default arguments here.  The standard
-     mandates that they be instantiated only when needed, which is
-     done in build_over_call.  */
-  default_arg = TREE_PURPOSE (arg_types);
-
-  if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG)
-    {
-      /* We've instantiated a template before its default arguments
-	 have been parsed.  This can happen for a nested template
-	 class, and is not an error unless we require the default
-	 argument in a call of this function.  */
-      result = tree_cons (default_arg, type, remaining_arg_types);
-      VEC_safe_push (tree, gc, DEFARG_INSTANTIATIONS (default_arg), result);
-    }
-  else
-    result = hash_tree_cons (default_arg, type, remaining_arg_types);
+  result = hash_tree_cons (NULL_TREE, type, remaining_arg_types);
 
   return result;
 }
@@ -9415,7 +9316,7 @@ fn_type_unification (tree fn,
      because the standard doesn't seem to explicitly prohibit it.  Our
      callers must be ready to deal with unification failures in any
      event.  */
-  result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+  result = type_unification_real (fn, DECL_INNERMOST_TEMPLATE_PARMS (fn),
 				  targs, parms, args, /*subr=*/0,
 				  strict, flags);
 
@@ -9528,7 +9429,8 @@ maybe_adjust_types_for_deduction (unific
    template). */
 
 static int
-type_unification_real (tree tparms,
+type_unification_real (tree fn,
+		       tree tparms,
 		       tree targs,
 		       tree xparms,
 		       tree xargs,
@@ -9542,12 +9444,28 @@ type_unification_real (tree tparms,
   int sub_strict;
   int saw_undeduced = 0;
   tree parms, args;
+  tree xparmdecls, parmdecls;
 
   gcc_assert (TREE_CODE (tparms) == TREE_VEC);
   gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
   gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
   gcc_assert (ntparms > 0);
 
+  if (fn)
+    {
+      if (DECL_FUNCTION_TEMPLATE_P (fn))
+	fn = DECL_TEMPLATE_RESULT (fn);
+      gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
+
+      xparmdecls = DECL_ARGUMENTS (fn);
+
+      /* Never do unification on the 'this' parameter.  */
+      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+	xparmdecls = TREE_CHAIN (xparmdecls);
+    }
+  else
+    xparmdecls = NULL_TREE;
+
   switch (strict)
     {
     case DEDUCE_CALL:
@@ -9570,6 +9488,7 @@ type_unification_real (tree tparms,
  again:
   parms = xparms;
   args = xargs;
+  parmdecls = xparmdecls;
 
   while (parms && parms != void_list_node
 	 && args && args != void_list_node)
@@ -9578,6 +9497,8 @@ type_unification_real (tree tparms,
       parms = TREE_CHAIN (parms);
       arg = TREE_VALUE (args);
       args = TREE_CHAIN (args);
+      if (parmdecls)
+	parmdecls = TREE_CHAIN (parmdecls);
 
       if (arg == error_mark_node)
 	return 1;
@@ -9648,7 +9569,7 @@ type_unification_real (tree tparms,
     return 1;
   /* Fail if parms are left and they don't have default values.  */
   if (parms && parms != void_list_node
-      && TREE_PURPOSE (parms) == NULL_TREE)
+      && parmdecls && DECL_INITIAL (parmdecls) == NULL_TREE)
     return 1;
 
   if (!subr)
@@ -10505,7 +10426,7 @@ unify (tree tparms, tree targs, tree par
       if (unify (tparms, targs, TREE_TYPE (parm),
 		 TREE_TYPE (arg), UNIFY_ALLOW_NONE))
 	return 1;
-      return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+      return type_unification_real (NULL, tparms, targs, TYPE_ARG_TYPES (parm),
 				    TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
 				    LOOKUP_NORMAL);
 
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 114535)
+++ cp/typeck.c	(working copy)
@@ -190,25 +190,6 @@ commonparms (tree p1, tree p2)
   for (i = 0; p1;
        p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n), i++)
     {
-      if (TREE_PURPOSE (p1) && !TREE_PURPOSE (p2))
-	{
-	  TREE_PURPOSE (n) = TREE_PURPOSE (p1);
-	  any_change = 1;
-	}
-      else if (! TREE_PURPOSE (p1))
-	{
-	  if (TREE_PURPOSE (p2))
-	    {
-	      TREE_PURPOSE (n) = TREE_PURPOSE (p2);
-	      any_change = 1;
-	    }
-	}
-      else
-	{
-	  if (1 != simple_cst_equal (TREE_PURPOSE (p1), TREE_PURPOSE (p2)))
-	    any_change = 1;
-	  TREE_PURPOSE (n) = TREE_PURPOSE (p2);
-	}
       if (TREE_VALUE (p1) != TREE_VALUE (p2))
 	{
 	  any_change = 1;
@@ -2711,6 +2692,7 @@ build_function_call (tree function, tree
 static tree
 convert_arguments (tree typelist, tree values, tree fndecl, int flags)
 {
+  tree parm = NULL_TREE;
   tree typetail, valtail;
   tree result = NULL_TREE;
   const char *called_thing = 0;
@@ -2721,6 +2703,8 @@ convert_arguments (tree typelist, tree v
 
   if (fndecl)
     {
+      parm = DECL_ARGUMENTS (fndecl);
+
       if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
 	{
 	  if (DECL_NAME (fndecl) == NULL_TREE
@@ -2820,19 +2804,22 @@ convert_arguments (tree typelist, tree v
 
       if (typetail)
 	typetail = TREE_CHAIN (typetail);
+      if (parm)
+	parm = TREE_CHAIN (parm);
     }
 
   if (typetail != 0 && typetail != void_list_node)
     {
       /* See if there are default arguments that can be used.  */
-      if (TREE_PURPOSE (typetail)
-	  && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
+      if (parm
+	  && DECL_INITIAL (parm)
+	  && TREE_CODE (DECL_INITIAL (parm)) != DEFAULT_ARG)
 	{
 	  for (; typetail != void_list_node; ++i)
 	    {
 	      tree parmval
 		= convert_default_arg (TREE_VALUE (typetail),
-				       TREE_PURPOSE (typetail),
+				       DECL_INITIAL (parm),
 				       fndecl, i);
 
 	      if (parmval == error_mark_node)
@@ -2840,9 +2827,12 @@ convert_arguments (tree typelist, tree v
 
 	      result = tree_cons (0, parmval, result);
 	      typetail = TREE_CHAIN (typetail);
+	      parm = TREE_CHAIN (parm);
 	      /* ends with `...'.  */
 	      if (typetail == NULL_TREE)
 		break;
+	      if (parm == NULL_TREE)
+		break;
 	    }
 	}
       else


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