DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx, DECL_DESTRUCTOR_FOR_PVBASE_P (r));
tsubst_decl (t, args, type, in_decl)     tree t;     tree args;     tree type;     tree in_decl;{  int saved_lineno;  char* saved_filename;  tree r = NULL_TREE;  /* Set the filename and linenumber to improve error-reporting.  */  saved_lineno = lineno;  saved_filename = input_filename;  lineno = DECL_SOURCE_LINE (t);  input_filename = DECL_SOURCE_FILE (t);  switch (TREE_CODE (t))    {    case TEMPLATE_DECL:      {	/* We can get here when processing a member template function	   of a template class.  */	tree decl = DECL_TEMPLATE_RESULT (t);	tree spec;	int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);	if (!is_template_template_parm)	  {	    /* We might already have an instance of this template.	       The ARGS are for the surrounding class type, so the	       full args contain the tsubst'd args for the context,	       plus the innermost args from the template decl.  */	    tree tmpl_args = DECL_CLASS_TEMPLATE_P (t) 	      ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))	      : DECL_TI_ARGS (DECL_RESULT (t));	    tree full_args;	    	    push_momentary ();	    full_args = tsubst_template_arg_vector (tmpl_args, args,						    /*complain=*/1);	    /* tsubst_template_arg_vector doesn't copy the vector if	       nothing changed.  But, *something* should have	       changed.  */	    my_friendly_assert (full_args != tmpl_args, 0);	    spec = retrieve_specialization (t, full_args);	    pop_momentary ();	    if (spec != NULL_TREE)	      {		r = spec;		break;	      }	  }	/* Make a new template decl.  It will be similar to the	   original, but will record the current template arguments. 	   We also create a new function declaration, which is just	   like the old one, but points to this new template, rather	   than the old one.  */	r = copy_node (t);	copy_lang_decl (r);	my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);	TREE_CHAIN (r) = NULL_TREE;	if (is_template_template_parm)	  {	    tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);	    DECL_RESULT (r) = new_decl;	    TREE_TYPE (r) = TREE_TYPE (new_decl);	    break;	  }	DECL_CONTEXT (r) 	  = tsubst_aggr_type (DECL_CONTEXT (t), args, /*complain=*/1,			      in_decl, /*entering_scope=*/1);	DECL_CLASS_CONTEXT (r) 	  = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, 			      /*complain=*/1, in_decl, 			      /*entering_scope=*/1); 	DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);	if (TREE_CODE (decl) == TYPE_DECL)	  {	    tree new_type = tsubst (TREE_TYPE (t), args,				    /*complain=*/1, in_decl);	    TREE_TYPE (r) = new_type;	    CLASSTYPE_TI_TEMPLATE (new_type) = r;	    DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);	    DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);	  }	else	  {	    tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);	    DECL_RESULT (r) = new_decl;	    DECL_TI_TEMPLATE (new_decl) = r;	    TREE_TYPE (r) = TREE_TYPE (new_decl);	    DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);	  }	SET_DECL_IMPLICIT_INSTANTIATION (r);	DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;	DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;	/* The template parameters for this new template are all the	   template parameters for the old template, except the	   outermost level of parameters. */	DECL_TEMPLATE_PARMS (r) 	  = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,				   /*complain=*/1);	if (PRIMARY_TEMPLATE_P (t))	  DECL_PRIMARY_TEMPLATE (r) = r;	/* We don't partially instantiate partial specializations.  */	if (TREE_CODE (decl) == TYPE_DECL)	  break;	for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);	     spec != NULL_TREE;	     spec = TREE_CHAIN (spec))	  {	    /* It helps to consider example here.  Consider:	       template <class T>	       struct S {	         template <class U>		 void f(U u);		 template <>		 void f(T* t) {}	       };	       	       Now, for example, we are instantiating S<int>::f(U u).  	       We want to make a template:	       template <class U>	       void S<int>::f(U);	       It will have a specialization, for the case U = int*, of	       the form:	       template <>	       void S<int>::f<int*>(int*);	       This specialization will be an instantiation of	       the specialization given in the declaration of S, with	       argument list int*.  */	    tree fn = TREE_VALUE (spec);	    tree spec_args;	    tree new_fn;	    if (!DECL_TEMPLATE_SPECIALIZATION (fn))	      /* Instantiations are on the same list, but they're of		 no concern to us.  */	      continue;	    if (TREE_CODE (fn) != TEMPLATE_DECL)	      /* A full specialization.  There's no need to record		 that here.  */	      continue;	    spec_args = tsubst (DECL_TI_ARGS (fn), args,				/*complain=*/1, in_decl); 	    new_fn = tsubst (DECL_RESULT (most_general_template (fn)), 			     spec_args, /*complain=*/1, in_decl); 	    DECL_TI_TEMPLATE (new_fn) = fn;	    register_specialization (new_fn, r, 				     innermost_args (spec_args));	  }	/* Record this partial instantiation.  */	register_specialization (r, t, 				 DECL_TI_ARGS (DECL_RESULT (r)));      }      break;    case FUNCTION_DECL:      {	tree ctx;	tree argvec = NULL_TREE;	tree *friends;	tree gen_tmpl;	int member;	int args_depth;	int parms_depth;	/* Nobody should be tsubst'ing into non-template functions.  */	my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);	if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)	  {	    tree spec;	    /* Allocate template arguments on the momentary obstack,	       in case we don't need to keep them.  */	    push_momentary ();	    /* Calculate the most general template of which R is a	       specialization, and the complete set of arguments used to	       specialize R.  */	    gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));	    argvec 	      = tsubst_template_arg_vector (DECL_TI_ARGS 					    (DECL_TEMPLATE_RESULT (gen_tmpl)),					    args, /*complain=*/1); 	    /* Check to see if we already have this specialization.  */	    spec = retrieve_specialization (gen_tmpl, argvec);	    if (spec)	      {		r = spec;		pop_momentary ();		break;	      }	    /* We're going to need to keep the ARGVEC, so we copy it	       here.  */	    argvec = copy_to_permanent (argvec);	    pop_momentary ();	    /* Here, we deal with the peculiar case:		 template <class T> struct S { 		   template <class U> friend void f();		 };		 template <class U> friend void f() {}		 template S<int>;		 template void f<double>();	       Here, the ARGS for the instantiation of will be {int,	       double}.  But, we only need as many ARGS as there are	       levels of template parameters in CODE_PATTERN.  We are	       careful not to get fooled into reducing the ARGS in	       situations like:		 template <class T> struct S { template <class U> void f(U); }		 template <class T> template <> void S<T>::f(int) {}	       which we can spot because the pattern will be a	       specialization in this case.  */	    args_depth = TMPL_ARGS_DEPTH (args);	    parms_depth = 	      TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t))); 	    if (args_depth > parms_depth		&& !DECL_TEMPLATE_SPECIALIZATION (t))	      {		my_friendly_assert (DECL_FRIEND_P (t), 0);		if (parms_depth > 1)		  {		    int i;		    args = make_temp_vec (parms_depth);		    for (i = 0; i < parms_depth; ++i)		      TREE_VEC_ELT (args, i) = 			TREE_VEC_ELT (args, i + (args_depth - parms_depth));		  }		else		  args = TREE_VEC_ELT (args, args_depth - parms_depth);	      }	  }	else	  {	    /* This special case arises when we have something like this:	         template <class T> struct S { 		   friend void f<int>(int, double); 		 };	       Here, the DECL_TI_TEMPLATE for the friend declaration	       will be a LOOKUP_EXPR or an IDENTIFIER_NODE.  We are	       being called from tsubst_friend_function, and we want	       only to create a new decl (R) with appropriate types so	       that we can call determine_specialization.  */	    my_friendly_assert ((TREE_CODE (DECL_TI_TEMPLATE (t)) 				 == LOOKUP_EXPR)				|| (TREE_CODE (DECL_TI_TEMPLATE (t))				    == IDENTIFIER_NODE), 0);	    gen_tmpl = NULL_TREE;	  }	if (DECL_CLASS_SCOPE_P (t))	  {	    if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t)))	      member = 2;	    else	      member = 1;	    ctx = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, 				    /*complain=*/1, t, 				    /*entering_scope=*/1);	  }	else	  {	    member = 0;	    ctx = NULL_TREE;	  }	type = tsubst (type, args, /*complain=*/1, in_decl);	/* We do NOT check for matching decls pushed separately at this           point, as they may not represent instantiations of this           template, and in any case are considered separate under the           discrete model.  Instead, see add_maybe_template.  */	r = copy_node (t);	copy_lang_decl (r);	DECL_USE_TEMPLATE (r) = 0;	TREE_TYPE (r) = type;	DECL_CONTEXT (r)	  = tsubst_aggr_type (DECL_CONTEXT (t), args, /*complain=*/1, t,			      /*entering_scope=*/1);	DECL_CLASS_CONTEXT (r) = ctx;	if (member && IDENTIFIER_TYPENAME_P (DECL_NAME (r)))	  /* Type-conversion operator.  Reconstruct the name, in	     case it's the name of one of the template's parameters.  */	  DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));	DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,				     /*complain=*/1, t);	DECL_MAIN_VARIANT (r) = r;	DECL_RESULT (r) = NULL_TREE;	TREE_STATIC (r) = 0;	TREE_PUBLIC (r) = TREE_PUBLIC (t);	DECL_EXTERNAL (r) = 1;	DECL_INTERFACE_KNOWN (r) = 0;	DECL_DEFER_OUTPUT (r) = 0;	TREE_CHAIN (r) = NULL_TREE;	DECL_PENDING_INLINE_INFO (r) = 0;	TREE_USED (r) = 0;	/* Set up the DECL_TEMPLATE_INFO for R and compute its mangled	   name.  There's no need to do this in the special friend	   case mentioned above where GEN_TMPL is NULL.  */	if (gen_tmpl)	  {	    /* The ARGVEC was built on the momentary obstack.  Make it	       permanent now.  */	    argvec = copy_to_permanent (argvec);	    DECL_TEMPLATE_INFO (r) 	      = perm_tree_cons (gen_tmpl, argvec, NULL_TREE);	    SET_DECL_IMPLICIT_INSTANTIATION (r);	    register_specialization (r, gen_tmpl, argvec);	    /* Set the mangled name for R.  */	    if (DECL_DESTRUCTOR_P (t))	      DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);	    else 	      {		/* Instantiations of template functions must be mangled		   specially, in order to conform to 14.5.5.1		   [temp.over.link].  */		tree tmpl = DECL_TI_TEMPLATE (t);				/* TMPL will be NULL if this is a specialization of a		   member function of a template class.  */		if (name_mangling_version < 1		    || tmpl == NULL_TREE		    || (member && !is_member_template (tmpl)			&& !DECL_TEMPLATE_INFO (tmpl)))		  set_mangled_name_for_decl (r);		else		  set_mangled_name_for_template_decl (r);	      }	    	    DECL_RTL (r) = 0;	    make_decl_rtl (r, NULL_PTR, 1);	    	    /* Like grokfndecl.  If we don't do this, pushdecl will	       mess up our TREE_CHAIN because it doesn't find a	       previous decl.  Sigh.  */	    if (member		&& ! uses_template_parms (r)		&& (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) 		    == NULL_TREE))	      SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);	  }	/* Copy the list of befriending classes.  */	for (friends = &DECL_BEFRIENDING_CLASSES (r);	     *friends;	     friends = &TREE_CHAIN (*friends)) 	  {	    *friends = copy_node (*friends);	    TREE_VALUE (*friends) = tsubst (TREE_VALUE (*friends),					    args, /*complain=*/1, 					    in_decl);	  }	if (DECL_CONSTRUCTOR_P (r))	  {	    maybe_retrofit_in_chrg (r);	    grok_ctor_properties (ctx, r);	  }	if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))	  grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));      }      break;    case PARM_DECL:      {	r = copy_node (t);	TREE_TYPE (r) = type;	c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);	if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)	  DECL_INITIAL (r) = TREE_TYPE (r);	else	  DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args,				     /*complain=*/1, in_decl);	DECL_CONTEXT (r) = NULL_TREE;#ifdef PROMOTE_PROTOTYPES	if ((TREE_CODE (type) == INTEGER_TYPE	     || TREE_CODE (type) == ENUMERAL_TYPE)	    && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))	  DECL_ARG_TYPE (r) = integer_type_node;#endif	if (TREE_CHAIN (t))	  TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,				   /*complain=*/1, TREE_CHAIN (t));      }      break;    case FIELD_DECL:      {	r = copy_node (t);	copy_lang_decl (r);	TREE_TYPE (r) = type;	c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);	/* We don't have to set DECL_CONTEXT here; it is set by	   finish_member_declaration.  */	DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,					/*complain=*/1, in_decl);	TREE_CHAIN (r) = NULL_TREE;	if (TREE_CODE (type) == VOID_TYPE) 	  cp_error_at ("instantiation of `%D' as type void", r);      }      break;    case USING_DECL:      {	r = copy_node (t);	DECL_INITIAL (r)	  = tsubst_copy (DECL_INITIAL (t), args, /*complain=*/1, in_decl);	TREE_CHAIN (r) = NULL_TREE;      }      break;    case VAR_DECL:      {	tree argvec;	tree gen_tmpl;	tree spec;	tree tmpl;	tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 				     /*complain=*/1,				     in_decl, /*entering_scope=*/1);		/* Nobody should be tsubst'ing into non-template variables.  */	my_friendly_assert (DECL_LANG_SPECIFIC (t) 			    && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);	/* Check to see if we already have this specialization.  */	tmpl = DECL_TI_TEMPLATE (t);	gen_tmpl = most_general_template (tmpl);	argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);	spec = retrieve_specialization (gen_tmpl, argvec);		if (spec)	  {	    r = spec;	    break;	  }	r = copy_node (t);	TREE_TYPE (r) = type;	c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);	DECL_CONTEXT (r) = ctx;	/* Don't try to expand the initializer until someone tries to use	   this variable; otherwise we run into circular dependencies.  */	DECL_INITIAL (r) = NULL_TREE;	DECL_RTL (r) = 0;	DECL_SIZE (r) = 0;	copy_lang_decl (r);	DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);	/* A static data member declaration is always marked external	   when it is declared in-class, even if an initializer is	   present.  We mimic the non-template processing here.  */	DECL_EXTERNAL (r) = 1;	DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);	SET_DECL_IMPLICIT_INSTANTIATION (r);	register_specialization (r, gen_tmpl, argvec);	TREE_CHAIN (r) = NULL_TREE;	if (TREE_CODE (type) == VOID_TYPE)	  cp_error_at ("instantiation of `%D' as type void", r);      }      break;    case TYPE_DECL:      if (t == TYPE_NAME (TREE_TYPE (t)))	r = TYPE_NAME (type);      else	{	  r = copy_node (t);	  TREE_TYPE (r) = type;	  DECL_CONTEXT (r) = current_class_type;	  TREE_CHAIN (r) = NULL_TREE;	}      break;    default:      my_friendly_abort (0);    }   /* Restore the file and line information.  */  lineno = saved_lineno;  input_filename = saved_filename;  return r;}