cp-tree.h (tsubst_copy_and_build): New declaration.

2003-01-16  Jeffrey D. Oldham  <oldham@codesourcery.com>

	* cp-tree.h (tsubst_copy_and_build): New declaration.
	* pt.c (tsubst_copy): Remove 'build_expr_from_tree' from comment.
	(tsubst_expr): Use 'tsubst_copy_and_build'.  Update initial comment.
	(tsubst_copy_and_build): New function.

From-SVN: r61409
This commit is contained in:
Jeffrey D. Oldham 2003-01-16 22:06:04 +00:00 committed by Jeffrey D. Oldham
parent f411c7397a
commit cc23546e32
3 changed files with 517 additions and 7 deletions

View File

@ -1,3 +1,10 @@
2003-01-16 Jeffrey D. Oldham <oldham@codesourcery.com>
* cp-tree.h (tsubst_copy_and_build): New declaration.
* pt.c (tsubst_copy): Remove 'build_expr_from_tree' from comment.
(tsubst_expr): Use 'tsubst_copy_and_build'. Update initial comment.
(tsubst_copy_and_build): New function.
2003-01-16 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_type_class): Remove is_partial_instantiation.

View File

@ -4025,6 +4025,7 @@ extern tree get_innermost_template_args (tree, int);
extern tree tsubst (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_expr (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
extern void maybe_begin_member_template_processing (tree);
extern void maybe_end_member_template_processing (void);
extern tree finish_member_template_decl (tree);

View File

@ -1,6 +1,6 @@
/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002 Free Software Foundation, Inc.
2001, 2002, 2003 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
@ -7360,11 +7360,10 @@ tsubst_copy (t, args, complain, in_decl)
NULL_TREE);
case STMT_EXPR:
/* This processing should really occur in tsubst_expr, However,
/* This processing should really occur in tsubst_expr. However,
tsubst_expr does not recurse into expressions, since it
assumes that there aren't any statements inside them.
Instead, it simply calls build_expr_from_tree. So, we need
to expand the STMT_EXPR here. */
assumes that there aren't any statements inside them. So, we
need to expand the STMT_EXPR here. */
if (!processing_template_decl)
{
tree stmt_expr = begin_stmt_expr ();
@ -7501,7 +7500,8 @@ tsubst_copy (t, args, complain, in_decl)
}
}
/* Like tsubst_copy, but also does semantic processing. */
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
tree
tsubst_expr (t, args, complain, in_decl)
@ -7518,7 +7518,7 @@ tsubst_expr (t, args, complain, in_decl)
return tsubst_copy (t, args, complain, in_decl);
if (!statement_code_p (TREE_CODE (t)))
return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
return tsubst_copy_and_build (t, args, complain, in_decl);
switch (TREE_CODE (t))
{
@ -7827,6 +7827,508 @@ tsubst_expr (t, args, complain, in_decl)
return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
}
/* Like tsubst but deals with expressions and performs semantic
analysis. */
tree
tsubst_copy_and_build (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
tree in_decl;
{
if (t == NULL_TREE || t == error_mark_node)
return t;
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
if (IDENTIFIER_TYPENAME_P (t))
{
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
return do_identifier (mangle_conv_op_name_for_type (new_type),
NULL_TREE);
}
else
return do_identifier (t, NULL_TREE);
case LOOKUP_EXPR:
{
if (LOOKUP_EXPR_GLOBAL (t))
{
tree token
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
}
else
{
t = do_identifier
(tsubst_copy
(TREE_OPERAND (t, 0), args, complain, in_decl),
NULL_TREE);
if (TREE_CODE (t) == ALIAS_DECL)
t = DECL_INITIAL (t);
return t;
}
}
case TEMPLATE_ID_EXPR:
{
tree object;
tree template
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
if (TREE_CODE (template) == COMPONENT_REF)
{
object = TREE_OPERAND (template, 0);
template = TREE_OPERAND (template, 1);
}
else
object = NULL_TREE;
template = lookup_template_function
(template,
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
if (object)
return build (COMPONENT_REF, TREE_TYPE (template),
object, template);
else
return template;
}
case INDIRECT_REF:
return build_x_indirect_ref
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
"unary *");
case CAST_EXPR:
return build_functional_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case CONST_CAST_EXPR:
return build_const_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case DYNAMIC_CAST_EXPR:
return build_dynamic_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case STATIC_CAST_EXPR:
return build_static_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
else
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl));
case NEGATE_EXPR:
case BIT_NOT_EXPR:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
else
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl));
case ABS_EXPR:
if (TREE_TYPE (t))
return t;
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case TRUTH_NOT_EXPR:
case ADDR_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
else
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl));
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
case BIT_AND_EXPR:
case BIT_ANDTC_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case RSHIFT_EXPR:
case LSHIFT_EXPR:
case RROTATE_EXPR:
case LROTATE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
case LE_EXPR:
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
case MEMBER_REF:
return build_x_binary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
case DOTSTAR_EXPR:
return build_m_component_ref
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
case SCOPE_REF:
return build_offset_ref
(tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
case ARRAY_REF:
{
if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
== NULL_TREE)
/* new-type-id */
return build_nt
(ARRAY_REF, NULL_TREE,
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
return grok_array_decl
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
}
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
{
tree r =
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
if (!TYPE_P (r))
return TREE_CODE (t) == SIZEOF_EXPR ?
expr_sizeof (r) : c_alignof_expr (r);
else
return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
}
case MODOP_EXPR:
return build_x_modify_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
TREE_CODE (TREE_OPERAND (t, 1)),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
case ARROW_EXPR:
return build_x_arrow
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case NEW_EXPR:
return build_new
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl),
NEW_EXPR_USE_GLOBAL (t));
case DELETE_EXPR:
return delete_sanity
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
DELETE_EXPR_USE_VEC (t),
DELETE_EXPR_USE_GLOBAL (t));
case COMPOUND_EXPR:
{
if (tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl)
== NULL_TREE)
return build_x_compound_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl));
else
abort ();
}
case METHOD_CALL_EXPR:
{
tree method
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
if (TREE_CODE (method) == SCOPE_REF)
{
tree name = TREE_OPERAND (method, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
TREE_OPERAND (name, 1));
return build_scoped_method_call
(tsubst_copy_and_build
(TREE_OPERAND (t, 1), args, complain, in_decl),
TREE_OPERAND (method, 0),
name,
tsubst_copy_and_build
(TREE_OPERAND (t, 2), args, complain, in_decl));
}
else
{
/* We can get a TEMPLATE_ID_EXPR here on code like:
x->f<2>();
so we must resolve that. However, we can also get things
like a BIT_NOT_EXPR here, when referring to a destructor,
and things like that are not correctly resolved by this
function so just use it when we really need it. */
if (TREE_CODE (method) == TEMPLATE_ID_EXPR)
method = lookup_template_function
(TREE_OPERAND (method, 0),
TREE_OPERAND (method, 1));
return build_method_call
(tsubst_copy_and_build
(TREE_OPERAND (t, 1), args, complain, in_decl),
method,
tsubst_copy_and_build
(TREE_OPERAND (t, 2), args, complain, in_decl),
NULL_TREE, LOOKUP_NORMAL);
}
}
case CALL_EXPR:
{
tree function
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
if (TREE_CODE (function) == SCOPE_REF)
{
tree name = TREE_OPERAND (function, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
TREE_OPERAND (name, 1));
return build_call_from_tree
(resolve_scoped_fn_name (TREE_OPERAND (function, 0), name),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl),
1);
}
else
{
tree name = function;
tree id;
tree copy_args = tsubst_copy_and_build
(TREE_OPERAND (t, 1), args, complain, in_decl);
if (copy_args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (name)
&& (TREE_CODE ((id = TREE_OPERAND (name, 0)))
== IDENTIFIER_NODE)
&& (!current_class_type
|| !lookup_member (current_class_type, id, 0, 0)))
{
/* Do Koenig lookup if there are no class members. */
name = do_identifier (id, copy_args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
if (TREE_CODE (name) == OFFSET_REF)
return build_offset_ref_call_from_tree (name, copy_args);
if (TREE_CODE (name) == COMPONENT_REF)
return finish_object_call_expr (TREE_OPERAND (name, 1),
TREE_OPERAND (name, 0),
copy_args);
name = convert_from_reference (name);
return build_call_from_tree (name, copy_args,
/*disallow_virtual=*/false);
}
}
case COND_EXPR:
return build_x_conditional_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
case PSEUDO_DTOR_EXPR:
return finish_pseudo_destructor_expr
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
case TREE_LIST:
{
tree purpose, value, chain;
if (t == void_list_node)
return t;
purpose = TREE_PURPOSE (t);
if (purpose)
purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
value = TREE_VALUE (t);
if (value)
value = tsubst_copy_and_build (value, args, complain, in_decl);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
chain = tsubst_copy_and_build (chain, args, complain, in_decl);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
return tree_cons (purpose, value, chain);
}
case COMPONENT_REF:
{
tree object =
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
tree member =
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
if (!CLASS_TYPE_P (TREE_TYPE (object)))
{
if (TREE_CODE (member) == BIT_NOT_EXPR)
return finish_pseudo_destructor_expr (object,
NULL_TREE,
TREE_TYPE (object));
else if (TREE_CODE (member) == SCOPE_REF
&& (TREE_CODE (TREE_OPERAND (member, 1)) == BIT_NOT_EXPR))
return finish_pseudo_destructor_expr (object,
object,
TREE_TYPE (object));
}
else if (TREE_CODE (member) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (member, 1)) == TEMPLATE_ID_EXPR)
{
tree tmpl;
tree args;
/* Lookup the template functions now that we know what the
scope is. */
tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
member = lookup_qualified_name (TREE_OPERAND (member, 0),
tmpl,
/*is_type=*/0,
/*flags=*/0);
if (BASELINK_P (member))
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
args);
else
{
error ("`%D' is not a member of `%T'",
tmpl, TREE_TYPE (object));
return error_mark_node;
}
}
return finish_class_member_access_expr (object, member);
}
case THROW_EXPR:
return build_throw
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case CONSTRUCTOR:
{
tree r;
tree elts;
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
bool purpose_p;
/* digest_init will do the wrong thing if we let it. */
if (type && TYPE_PTRMEMFUNC_P (type))
return t;
r = NULL_TREE;
/* We do not want to process the purpose of aggregate
initializers as they are identifier nodes which will be
looked up by digest_init. */
purpose_p = !(type && IS_AGGR_TYPE (type));
for (elts = tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain,
in_decl);
elts;
elts = TREE_CHAIN (elts))
{
tree purpose = TREE_PURPOSE (elts);
tree value = TREE_VALUE (elts);
if (purpose && purpose_p)
purpose
= tsubst_copy_and_build (purpose, args, complain, in_decl);
value = tsubst_copy_and_build (value, args, complain, in_decl);
r = tree_cons (purpose, value, r);
}
r = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (r));
TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
if (type)
return digest_init (type, r, 0);
return r;
}
case TYPEID_EXPR:
{
tree operand_0
= tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl);
if (TYPE_P (operand_0))
return get_typeid (operand_0);
return build_typeid (operand_0);
}
case PARM_DECL:
return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
case VAR_DECL:
return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
case VA_ARG_EXPR:
return build_x_va_arg
(tsubst_copy_and_build
(TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_TYPE (t), args, complain, in_decl));
default:
return tsubst_copy (t, args, complain, in_decl);
}
}
/* Instantiate the indicated variable or function template TMPL with
the template arguments in TARG_PTR. */