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> 2003-01-16 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_type_class): Remove is_partial_instantiation. * 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 (tree, tree, tsubst_flags_t, tree);
extern tree tsubst_expr (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 (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_begin_member_template_processing (tree);
extern void maybe_end_member_template_processing (void); extern void maybe_end_member_template_processing (void);
extern tree finish_member_template_decl (tree); extern tree finish_member_template_decl (tree);

View File

@ -1,6 +1,6 @@
/* Handle parameterized types (templates) for GNU C++. /* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 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. Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com). Rewritten by Jason Merrill (jason@cygnus.com).
@ -7360,11 +7360,10 @@ tsubst_copy (t, args, complain, in_decl)
NULL_TREE); NULL_TREE);
case STMT_EXPR: 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 tsubst_expr does not recurse into expressions, since it
assumes that there aren't any statements inside them. assumes that there aren't any statements inside them. So, we
Instead, it simply calls build_expr_from_tree. So, we need need to expand the STMT_EXPR here. */
to expand the STMT_EXPR here. */
if (!processing_template_decl) if (!processing_template_decl)
{ {
tree stmt_expr = begin_stmt_expr (); 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 tree
tsubst_expr (t, args, complain, in_decl) 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); return tsubst_copy (t, args, complain, in_decl);
if (!statement_code_p (TREE_CODE (t))) 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)) 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); 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 /* Instantiate the indicated variable or function template TMPL with
the template arguments in TARG_PTR. */ the template arguments in TARG_PTR. */