tree e2 = tsubst_call_declarator_parms (TREE_OPERAND (t, 1), args, complain, in_decl); tree e3 = tsubst (TREE_TYPE (t), args, complain, in_decl);
tree e2 = (tsubst_call_declarator_parms (CALL_DECLARATOR_PARMS (t), args, complain, in_decl)); tree e3 = tsubst (CALL_DECLARATOR_EXCEPTION_SPEC (t), args, complain, in_decl);
tsubst (t, args, complain, in_decl)     tree t, args;     int complain;     tree in_decl;{  tree type, r;  if (t == NULL_TREE || t == error_mark_node      || t == integer_type_node      || t == void_type_node      || t == char_type_node      || TREE_CODE (t) == NAMESPACE_DECL)    return t;  if (TREE_CODE (t) == IDENTIFIER_NODE)    type = IDENTIFIER_TYPE_VALUE (t);  else    type = TREE_TYPE (t);  if (type == unknown_type_node)    my_friendly_abort (42);  if (type && TREE_CODE (t) != FUNCTION_DECL      && TREE_CODE (t) != TYPENAME_TYPE      && TREE_CODE (t) != TEMPLATE_DECL      && TREE_CODE (t) != IDENTIFIER_NODE      && TREE_CODE (t) != FUNCTION_TYPE      && TREE_CODE (t) != METHOD_TYPE)    type = tsubst (type, args, complain, in_decl);  if (type == error_mark_node)    return error_mark_node;  if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')    return tsubst_decl (t, args, type, in_decl);  switch (TREE_CODE (t))    {    case RECORD_TYPE:    case UNION_TYPE:    case ENUMERAL_TYPE:      return tsubst_aggr_type (t, args, complain, in_decl,			       /*entering_scope=*/0);    case ERROR_MARK:    case IDENTIFIER_NODE:    case OP_IDENTIFIER:    case VOID_TYPE:    case REAL_TYPE:    case COMPLEX_TYPE:    case BOOLEAN_TYPE:    case INTEGER_CST:    case REAL_CST:    case STRING_CST:      return t;    case INTEGER_TYPE:      if (t == integer_type_node)	return t;      if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST	  && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)	return t;      {	tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);	max = tsubst_expr (omax, args, complain, in_decl);	if (max == error_mark_node)	  return error_mark_node;	if (processing_template_decl)	  {	    tree itype = make_node (INTEGER_TYPE);	    TYPE_MIN_VALUE (itype) = size_zero_node;	    TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,						integer_one_node);	    return itype;	  }	if (integer_zerop (omax))	  {	    /* Still allow an explicit array of size zero.  */	    if (pedantic)	      pedwarn ("creating array with size zero");	  }	else if (integer_zerop (max) || INT_CST_LT (max, integer_zero_node))	  {	    /* [temp.deduct]	       Type deduction may fail for any of the following	       reasons:  		 Attempting to create an array with a size that is		 zero or negative.  */	    if (complain)	      cp_error ("creating array with size `%E'", max);	    return error_mark_node;	  }	max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node));	if (!TREE_PERMANENT (max) && !allocation_temporary_p ())	  max = copy_to_permanent (max);	return build_index_type (max);      }    case TEMPLATE_TYPE_PARM:    case TEMPLATE_TEMPLATE_PARM:    case TEMPLATE_PARM_INDEX:      {	int idx;	int level;	int levels;	r = NULL_TREE;	if (TREE_CODE (t) == TEMPLATE_TYPE_PARM	    || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)	  {	    idx = TEMPLATE_TYPE_IDX (t);	    level = TEMPLATE_TYPE_LEVEL (t);	  }	else	  {	    idx = TEMPLATE_PARM_IDX (t);	    level = TEMPLATE_PARM_LEVEL (t);	  }	if (TREE_VEC_LENGTH (args) > 0)	  {	    tree arg = NULL_TREE;	    levels = TMPL_ARGS_DEPTH (args);	    if (level <= levels)	      arg = TMPL_ARG (args, level, idx);	    if (arg == error_mark_node)	      return error_mark_node;	    else if (arg != NULL_TREE)	      {		if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)		  {		    my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))					== 't', 0);		    return cp_build_qualified_type		      (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t));		  }		else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)		  {		    if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))		      {			/* We are processing a type constructed from			   a template template parameter */			tree argvec = tsubst (TYPE_TI_ARGS (t),					      args, complain, in_decl);			if (argvec == error_mark_node)			  return error_mark_node;						/* We can get a TEMPLATE_TEMPLATE_PARM here when 			   we are resolving nested-types in the signature of 			   a member function templates.			   Otherwise ARG is a TEMPLATE_DECL and is the real 			   template to be instantiated.  */			if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)			  arg = TYPE_NAME (arg);			r = lookup_template_class (DECL_NAME (arg), 						   argvec, in_decl, 						   DECL_CONTEXT (arg),						   /*entering_scope=*/0);			return cp_build_qualified_type (r, TYPE_QUALS (t));		      }		    else		      /* We are processing a template argument list.  */ 		      return arg;		  }		else		  return arg;	      }	  }	else	  my_friendly_abort (981018);	if (level == 1)	  /* This can happen during the attempted tsubst'ing in	     unify.  This means that we don't yet have any information	     about the template parameter in question.  */	  return t;	/* If we get here, we must have been looking at a parm for a	   more deeply nested template.  Make a new version of this	   template parameter, but with a lower level.  */	switch (TREE_CODE (t))	  {	  case TEMPLATE_TYPE_PARM:	  case TEMPLATE_TEMPLATE_PARM:	    r = copy_node (t);	    TEMPLATE_TYPE_PARM_INDEX (r)	      = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),					    r, levels);	    TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);	    TYPE_MAIN_VARIANT (r) = r;	    TYPE_POINTER_TO (r) = NULL_TREE;	    TYPE_REFERENCE_TO (r) = NULL_TREE;	    if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM		&& TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))	      {		tree argvec = tsubst (TYPE_TI_ARGS (t), args,				      complain, in_decl); 		if (argvec == error_mark_node)		  return error_mark_node;		TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)		  = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);	      }	    break;	  case TEMPLATE_PARM_INDEX:	    r = reduce_template_parm_level (t, type, levels);	    break;	   	  default:	    my_friendly_abort (0);	  }	return r;      }    case TREE_LIST:      {	tree purpose, value, chain, result;	if (t == void_list_node)	  return t;	purpose = TREE_PURPOSE (t);	if (purpose)	  {	    purpose = tsubst (purpose, args, complain, in_decl);	    if (purpose == error_mark_node)	      return error_mark_node;	  }	value = TREE_VALUE (t);	if (value)	  {	    value = tsubst (value, args, complain, in_decl);	    if (value == error_mark_node)	      return error_mark_node;	  }	chain = TREE_CHAIN (t);	if (chain && chain != void_type_node)	  {	    chain = tsubst (chain, args, complain, in_decl);	    if (chain == error_mark_node)	      return error_mark_node;	  }	if (purpose == TREE_PURPOSE (t)	    && value == TREE_VALUE (t)	    && chain == TREE_CHAIN (t))	  return t;	result = hash_tree_cons (purpose, value, chain);	TREE_PARMLIST (result) = TREE_PARMLIST (t);	return result;      }    case TREE_VEC:      if (type != NULL_TREE)	{	  /* A binfo node.  We always need to make a copy, of the node	     itself and of its BINFO_BASETYPES.  */	  t = copy_node (t);	  /* Make sure type isn't a typedef copy.  */	  type = BINFO_TYPE (TYPE_BINFO (type));	  TREE_TYPE (t) = complete_type (type);	  if (IS_AGGR_TYPE (type))	    {	      BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (type);	      BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (type);	      if (TYPE_BINFO_BASETYPES (type) != NULL_TREE)		BINFO_BASETYPES (t) = copy_node (TYPE_BINFO_BASETYPES (type));	    }	  return t;	}      /* Otherwise, a vector of template arguments.  */      return tsubst_template_arg_vector (t, args, complain);    case POINTER_TYPE:    case REFERENCE_TYPE:      {	enum tree_code code;	if (type == TREE_TYPE (t))	  return t;	code = TREE_CODE (t);	/* [temp.deduct]	   	   Type deduction may fail for any of the following	   reasons:  	   -- Attempting to create a pointer to reference type.	   -- Attempting to create a reference to a reference type or	      a reference to void.  */	if (TREE_CODE (type) == REFERENCE_TYPE	    || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))	  {	    static int   last_line = 0;	    static char* last_file = 0;	    /* We keep track of the last time we issued this error	       message to avoid spewing a ton of messages during a	       single bad template instantiation.  */	    if (complain && (last_line != lineno ||			     last_file != input_filename))	      {		if (TREE_CODE (type) == VOID_TYPE)		  cp_error ("forming reference to void");		else		  cp_error ("forming %s to reference type `%T'",			    (code == POINTER_TYPE) ? "pointer" : "reference",			    type);		last_line = lineno;		last_file = input_filename;	      }	    return error_mark_node;	  }	else if (code == POINTER_TYPE)	  r = build_pointer_type (type);	else	  r = build_reference_type (type);	r = cp_build_qualified_type (r, TYPE_QUALS (t));	/* Will this ever be needed for TYPE_..._TO values?  */	layout_type (r);	return r;      }    case OFFSET_TYPE:      {	r = tsubst (TYPE_OFFSET_BASETYPE (t), args, complain, in_decl);	if (r == error_mark_node || !IS_AGGR_TYPE (r))	  {	    /* [temp.deduct]	       Type deduction may fail for any of the following	       reasons:	       	       -- Attempting to create "pointer to member of T" when T	          is not a class type.  */	    if (complain)	      cp_error ("creating pointer to member of non-class type `%T'", 			r);	    return error_mark_node;	  }	return build_offset_type (r, type);      }    case FUNCTION_TYPE:    case METHOD_TYPE:      {	tree fntype;	tree raises;	fntype = tsubst_function_type (t, args, complain, in_decl);	if (fntype == error_mark_node)	  return error_mark_node;	/* Substitue the exception specification. */	raises = TYPE_RAISES_EXCEPTIONS (t);	if (raises)	  {	    raises = tsubst (raises, args, complain, in_decl);	    if (raises == error_mark_node)	      return raises;	    fntype = build_exception_variant (fntype, raises);	  }	return fntype;      }    case ARRAY_TYPE:      {	tree domain = tsubst (TYPE_DOMAIN (t), args, complain, in_decl);	if (domain == error_mark_node)	  return error_mark_node;	/* As an optimization, we avoid regenerating the array type if	   it will obviously be the same as T.  */	if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))	  return t;	/* These checks should match the ones in grokdeclarator.  	   [temp.deduct] 		   The deduction may fail for any of the following reasons: 	   -- Attempting to create an array with an element type that	      is void, a function type, or a reference type.  */	if (TREE_CODE (type) == VOID_TYPE 	    || TREE_CODE (type) == FUNCTION_TYPE	    || TREE_CODE (type) == REFERENCE_TYPE)	  {	    if (complain)	      cp_error ("creating array of `%T'", type);	    return error_mark_node;	  }	r = build_cplus_array_type (type, domain);	return r;      }    case PLUS_EXPR:    case MINUS_EXPR:      {	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,			  in_decl);	tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain,			  in_decl);	if (e1 == error_mark_node || e2 == error_mark_node)	  return error_mark_node;	return fold (build (TREE_CODE (t), TREE_TYPE (t), e1, e2));      }    case NEGATE_EXPR:    case NOP_EXPR:      {	tree e = tsubst (TREE_OPERAND (t, 0), args, complain,			  in_decl);	if (e == error_mark_node)	  return error_mark_node;	return fold (build (TREE_CODE (t), TREE_TYPE (t), e));      }    case TYPENAME_TYPE:      {	tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,				     in_decl, /*entering_scope=*/1);	tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args,			      complain, in_decl); 	if (ctx == error_mark_node || f == error_mark_node)	  return error_mark_node;	if (!IS_AGGR_TYPE (ctx))	  {	    if (complain)	      cp_error ("`%T' is not a class, struct, or union type",			ctx);	    return error_mark_node;	  }	else if (!uses_template_parms (ctx) && !TYPE_BEING_DEFINED (ctx))	  {	    /* Normally, make_typename_type does not require that the CTX	       have complete type in order to allow things like:	     	         template <class T> struct S { typename S<T>::X Y; };	       But, such constructs have already been resolved by this	       point, so here CTX really should have complete type, unless	       it's a partial instantiation.  */	    ctx = complete_type (ctx);	    if (!TYPE_SIZE (ctx))	      {		if (complain)		  incomplete_type_error (NULL_TREE, ctx);		return error_mark_node;	      }	  }	f = make_typename_type (ctx, f);	return cp_build_qualified_type (f, 					CP_TYPE_QUALS (f) 					| CP_TYPE_QUALS (t));      }    case INDIRECT_REF:      {	tree e = tsubst (TREE_OPERAND (t, 0), args, complain,			 in_decl);	if (e == error_mark_node)	  return error_mark_node;	return make_pointer_declarator (type, e);      }    case ADDR_EXPR:      {	tree e = tsubst (TREE_OPERAND (t, 0), args, complain,			 in_decl);	if (e == error_mark_node)	  return error_mark_node;	return make_reference_declarator (type, e);      }    case ARRAY_REF:      {	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,			  in_decl);	tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain,			       in_decl);	if (e1 == error_mark_node || e2 == error_mark_node)	  return error_mark_node;	return build_parse_node (ARRAY_REF, e1, e2, tsubst_expr);      }    case CALL_EXPR:      {	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,			  in_decl);	tree e2 = tsubst_call_declarator_parms (TREE_OPERAND (t, 1), args, 						complain, in_decl);	tree e3 = tsubst (TREE_TYPE (t), args, complain, in_decl);	if (e1 == error_mark_node || e2 == error_mark_node 	    || e3 == error_mark_node)	  return error_mark_node;	return make_call_declarator (e1, e2, TREE_OPERAND (t, 2), e3);      }    case SCOPE_REF:      {	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,				  in_decl);	tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);	if (e1 == error_mark_node || e2 == error_mark_node)	  return error_mark_node;	return build_parse_node (TREE_CODE (t), e1, e2);      }    case TYPEOF_TYPE:      {	tree e1 = tsubst_expr (TYPE_FIELDS (t), args, complain,			       in_decl);	if (e1 == error_mark_node)	  return error_mark_node;	return TREE_TYPE (e1);       }    default:      sorry ("use of `%s' in template",	     tree_code_name [(int) TREE_CODE (t)]);      return error_mark_node;    }}