This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
revised PATCH: CALL_EXPR representation changes, part 6/9 (C++ front end)
- From: Sandra Loosemore <sandra at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Brooks Moses <brooks dot moses at codesourcery dot com>, Lee Millward <lee dot millward at codesourcery dot com>
- Date: Wed, 14 Feb 2007 12:49:09 -0500
- Subject: revised PATCH: CALL_EXPR representation changes, part 6/9 (C++ front end)
2007-02-14 Sandra Loosemore <sandra@codesourcery.com>
Brooks Moses <brooks.moses@codesourcery.com>
Lee Millward <lee.millward@codesourcery.com>
* cp-tree.def (AGGR_INIT_EXPR): Adjust documentation.
Change class to tcc_vl_exp.
* call.c (build_call): Use build_call_list instead
of build3.
(build_over_call): Likewise.
(build_new_method_call): Use build_min_non_dep_call_list
instead of build_min_non_dep.
* error.c (dump_call_expr_args): New function.
(dump_aggr_init_expr_args): New function.
(dump_expr) <AGGR_INIT_EXPR, CALL_EXPR, INDIRECT_REF>: Use them.
Update to use new CALL_EXPR and AGGR_INIT_EXPR accessor macros.
* cvt.c (convert_to_void): Use build_call_array instead
of build3; use new AGGR_INIT_EXPR accessor macros.
* mangle.c (write_expression): Use TREE_OPERAND_LENGTH
instead of TREE_CODE_LENGTH.
* dump.c (cp_dump_tree) <AGGR_INIT_EXPR>: Update to use new
AGGR_INIT_EXPR accessor macros.
* cp-gimplify.c (cp_gimplify_init_expr): Use
AGGR_INIT_EXPR_SLOT to set the slot operand.
* cp-tree.h (AGGR_INIT_EXPR_FN): New macro.
(AGGR_INIT_EXPR_SLOT): New macro.
(AGGR_INIT_EXPR_ARG): New macro.
(aggr_init_expr_nargs): New macro.
(AGGR_INIT_EXPR_ARGP): New macro.
(aggr_init_expr_arg_iterator): New.
(init_aggr_init_expr_arg_iterator): New.
(next_aggr_init_expr_arg): New.
(first_aggr_init_expr_arg): New.
(more_aggr_init_expr_args_p): New.
(FOR_EACH_AGGR_INIT_EXPR_ARG): New.
(stabilize_aggr_init): New declaration.
(build_min_nt_call_list): Likewise.
(build_min_non_dep_call_list): Likewise.
* tree.c (process_aggr_init_operands): New function.
(build_aggr_init_array) New function.
(build_cplus_new): Update to use new CALL_EXPR and
AGGR_INIT_EXPR accessor macros. Replace use of build3 with
build_aggr_init_array.
(build_min_nt_call_list): New function.
(build_min_non_dep_call_list) Likewise.
(build_min_nt): Assert input code parameter is not a variable
length expression class.
(build_min, build_min_non_dep): Likewise.
(cp_tree_equal) <CALL_EXPR>: Iterate through the arguments
to check for equality instead of recursing. Handle tcc_vl_exp
tree code classes.
(stabilize_call): Update to only handle CALL_EXPRs, not
AGGR_INIT_EXPRs; use new CALL_EXPR accessor macros.
(stabilize_aggr_init): New function.
(stabilize_init): Use it.
* cxx-pretty-print.c (pp_cxx_postfix_expression)
<AGGR_INIT_EXPR, CALL_EXPR>: Update to use new CALL_EXPR and
AGGR_INIT_EXPR accessor macros and argument iterators.
* pt.c (tsubst_copy) <CALL_EXPR>: Replace build_nt with
build_vl_exp. Iterate through the operands, recursively
processing each one.
(tsubst_copy_and_build) <CALL_EXPR>: Update to use new
CALL_EXPR accessor macros.
(value_dependent_expression_p) <default>: Handle tcc_vl_exp
tree code classes. Use TREE_OPERAND_LENGTH instead of
TREE_CODE_LENGTH.
* semantics.c (finish_call_expr): Use build_nt_call_list
instead of build_nt.
(simplify_aggr_init_expr): Update to use new AGGR_INIT_EXPR
accessor macros. Use build_call_array to construct the
CALL_EXPR node instead of build3
* decl2.c (build_offset_ref_call_from_tree): Use
buil_nt_call_list and build_min_non_dep_call_list instead
of build_min_nt and build_min_non_dep.
* parser.c (cp_parser_postfix_expression) <CPP_OPEN_PAREN>:
Use build_min_nt_call_list instead of build_min_nt.
Index: gcc/cp/cp-tree.def
===================================================================
*** gcc/cp/cp-tree.def (revision 121818)
--- gcc/cp/cp-tree.def (working copy)
*************** DEFTREECODE (MEMBER_REF, "member_ref", t
*** 74,83 ****
operator converts to. Operand is expression to be converted. */
DEFTREECODE (TYPE_EXPR, "type_expr", tcc_expression, 1)
! /* For AGGR_INIT_EXPR, operand 0 is function which performs initialization,
! operand 1 is argument list to initialization function,
! and operand 2 is the slot which was allocated for this expression. */
! DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_expression, 3)
/* A throw expression. operand 0 is the expression, if there was one,
else it is NULL_TREE. */
--- 74,85 ----
operator converts to. Operand is expression to be converted. */
DEFTREECODE (TYPE_EXPR, "type_expr", tcc_expression, 1)
! /* AGGR_INIT_EXPRs have a variably-sized representation similar to
! that of CALL_EXPRs. Operand 0 is an INTEGER_CST node containing the
! operand count, operand 1 is the function which performs initialization,
! operand 2 is the slot which was allocated for this expression, and
! the remaining operands are the arguments to the initialization function. */
! DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_vl_exp, 3)
/* A throw expression. operand 0 is the expression, if there was one,
else it is NULL_TREE. */
Index: gcc/cp/call.c
===================================================================
*** gcc/cp/call.c (revision 121818)
--- gcc/cp/call.c (working copy)
*************** build_call (tree function, tree parms)
*** 336,342 ****
TREE_VALUE (tmp), t);
}
! function = build3 (CALL_EXPR, result_type, function, parms, NULL_TREE);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow;
--- 336,342 ----
TREE_VALUE (tmp), t);
}
! function = build_call_list (result_type, function, parms);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow;
*************** build_over_call (struct z_candidate *can
*** 4732,4738 ****
tree expr;
tree return_type;
return_type = TREE_TYPE (TREE_TYPE (fn));
! expr = build3 (CALL_EXPR, return_type, fn, args, NULL_TREE);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
--- 4732,4738 ----
tree expr;
tree return_type;
return_type = TREE_TYPE (TREE_TYPE (fn));
! expr = build_call_list (return_type, fn, args);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
*************** build_java_interface_fn_ref (tree fn, tr
*** 5114,5120 ****
lookup_fn = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
java_iface_lookup_fn);
! return build3 (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE);
}
/* Returns the value to use for the in-charge parameter when making a
--- 5114,5120 ----
lookup_fn = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
java_iface_lookup_fn);
! return build_call_list (ptr_type_node, lookup_fn, lookup_args);
}
/* Returns the value to use for the in-charge parameter when making a
*************** build_new_method_call (tree instance, tr
*** 5525,5534 ****
}
if (processing_template_decl && call != error_mark_node)
! call = (build_min_non_dep
! (CALL_EXPR, call,
build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE),
! orig_args, NULL_TREE));
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
--- 5525,5534 ----
}
if (processing_template_decl && call != error_mark_node)
! call = (build_min_non_dep_call_list
! (call,
build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE),
! orig_args));
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
Index: gcc/cp/error.c
===================================================================
*** gcc/cp/error.c (revision 121818)
--- gcc/cp/error.c (working copy)
*************** static void dump_aggr_type (tree, int);
*** 66,71 ****
--- 66,73 ----
static void dump_type_prefix (tree, int);
static void dump_type_suffix (tree, int);
static void dump_function_name (tree, int);
+ static void dump_call_expr_args (tree, int, bool);
+ static void dump_aggr_init_expr_args (tree, int, bool);
static void dump_expr_list (tree, int);
static void dump_global_iord (tree);
static void dump_parameters (tree, int);
*************** dump_template_parms (tree info, int prim
*** 1265,1270 ****
--- 1267,1321 ----
pp_cxx_end_template_argument_list (cxx_pp);
}
+ /* Print out the arguments of CALL_EXPR T as a parenthesized list using
+ flags FLAGS. Skip over the first argument if SKIPFIRST is true. */
+
+ static void
+ dump_call_expr_args (tree t, int flags, bool skipfirst)
+ {
+ tree arg;
+ call_expr_arg_iterator iter;
+
+ pp_cxx_left_paren (cxx_pp);
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
+ {
+ if (skipfirst)
+ skipfirst = false;
+ else
+ {
+ dump_expr (arg, flags | TFF_EXPR_IN_PARENS);
+ if (more_call_expr_args_p (&iter))
+ pp_separate_with_comma (cxx_pp);
+ }
+ }
+ pp_cxx_right_paren (cxx_pp);
+ }
+
+ /* Print out the arguments of AGGR_INIT_EXPR T as a parenthesized list
+ using flags FLAGS. Skip over the first argument if SKIPFIRST is
+ true. */
+
+ static void
+ dump_aggr_init_expr_args (tree t, int flags, bool skipfirst)
+ {
+ tree arg;
+ aggr_init_expr_arg_iterator iter;
+
+ pp_cxx_left_paren (cxx_pp);
+ FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
+ {
+ if (skipfirst)
+ skipfirst = false;
+ else
+ {
+ dump_expr (arg, flags | TFF_EXPR_IN_PARENS);
+ if (more_aggr_init_expr_args_p (&iter))
+ pp_separate_with_comma (cxx_pp);
+ }
+ }
+ pp_cxx_right_paren (cxx_pp);
+ }
+
/* Print out a list of initializers (subr of dump_expr). */
static void
*************** dump_expr (tree t, int flags)
*** 1387,1394 ****
{
tree fn = NULL_TREE;
! if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
! fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
if (fn && TREE_CODE (fn) == FUNCTION_DECL)
{
--- 1438,1445 ----
{
tree fn = NULL_TREE;
! if (TREE_CODE (AGGR_INIT_EXPR_FN (t)) == ADDR_EXPR)
! fn = TREE_OPERAND (AGGR_INIT_EXPR_FN (t), 0);
if (fn && TREE_CODE (fn) == FUNCTION_DECL)
{
*************** dump_expr (tree t, int flags)
*** 1398,1415 ****
dump_decl (fn, 0);
}
else
! dump_expr (TREE_OPERAND (t, 0), 0);
}
! pp_cxx_left_paren (cxx_pp);
! if (TREE_OPERAND (t, 1))
! dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
! pp_cxx_right_paren (cxx_pp);
break;
case CALL_EXPR:
{
! tree fn = TREE_OPERAND (t, 0);
! tree args = TREE_OPERAND (t, 1);
if (TREE_CODE (fn) == ADDR_EXPR)
fn = TREE_OPERAND (fn, 0);
--- 1449,1463 ----
dump_decl (fn, 0);
}
else
! dump_expr (AGGR_INIT_EXPR_FN (t), 0);
}
! dump_aggr_init_expr_args (t, flags, false);
break;
case CALL_EXPR:
{
! tree fn = CALL_EXPR_FN (t);
! bool skipfirst = false;
if (TREE_CODE (fn) == ADDR_EXPR)
fn = TREE_OPERAND (fn, 0);
*************** dump_expr (tree t, int flags)
*** 1420,1426 ****
if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
{
! tree ob = TREE_VALUE (args);
if (TREE_CODE (ob) == ADDR_EXPR)
{
dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
--- 1468,1474 ----
if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
{
! tree ob = CALL_EXPR_ARG (t, 0);
if (TREE_CODE (ob) == ADDR_EXPR)
{
dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
*************** dump_expr (tree t, int flags)
*** 1432,1443 ****
dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
pp_arrow (cxx_pp);
}
! args = TREE_CHAIN (args);
}
dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
! pp_cxx_left_paren (cxx_pp);
! dump_expr_list (args, flags);
! pp_cxx_right_paren (cxx_pp);
}
break;
--- 1480,1489 ----
dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
pp_arrow (cxx_pp);
}
! skipfirst = true;
}
dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
! dump_call_expr_args (t, flags, skipfirst);
}
break;
*************** dump_expr (tree t, int flags)
*** 1581,1590 ****
{
t = TREE_OPERAND (t, 0);
gcc_assert (TREE_CODE (t) == CALL_EXPR);
! dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
! pp_cxx_left_paren (cxx_pp);
! dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
! pp_cxx_right_paren (cxx_pp);
}
else
{
--- 1627,1634 ----
{
t = TREE_OPERAND (t, 0);
gcc_assert (TREE_CODE (t) == CALL_EXPR);
! dump_expr (CALL_EXPR_FN (t), flags | TFF_EXPR_IN_PARENS);
! dump_call_expr_args (t, flags, true);
}
else
{
Index: gcc/cp/cvt.c
===================================================================
*** gcc/cp/cvt.c (revision 121818)
--- gcc/cp/cvt.c (working copy)
*************** convert_to_void (tree expr, const char *
*** 902,910 ****
if (TREE_CODE (init) == AGGR_INIT_EXPR
&& !AGGR_INIT_VIA_CTOR_P (init))
{
! tree fn = TREE_OPERAND (init, 0);
! expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! fn, TREE_OPERAND (init, 1), NULL_TREE);
}
}
break;
--- 902,912 ----
if (TREE_CODE (init) == AGGR_INIT_EXPR
&& !AGGR_INIT_VIA_CTOR_P (init))
{
! tree fn = AGGR_INIT_EXPR_FN (init);
! expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! fn,
! aggr_init_expr_nargs (init),
! AGGR_INIT_EXPR_ARGP (init));
}
}
break;
Index: gcc/cp/mangle.c
===================================================================
*** gcc/cp/mangle.c (revision 121818)
--- gcc/cp/mangle.c (working copy)
*************** write_expression (tree expr)
*** 2206,2212 ****
break;
default:
! for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
{
tree operand = TREE_OPERAND (expr, i);
/* As a GNU extension, the middle operand of a
--- 2206,2212 ----
break;
default:
! for (i = 0; i < TREE_OPERAND_LENGTH (expr); ++i)
{
tree operand = TREE_OPERAND (expr, i);
/* As a GNU extension, the middle operand of a
Index: gcc/cp/dump.c
===================================================================
*** gcc/cp/dump.c (revision 121818)
--- gcc/cp/dump.c (working copy)
*************** cp_dump_tree (void* dump_info, tree t)
*** 388,397 ****
break;
case AGGR_INIT_EXPR:
! dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
! dump_child ("fn", TREE_OPERAND (t, 0));
! dump_child ("args", TREE_OPERAND (t, 1));
! dump_child ("decl", TREE_OPERAND (t, 2));
break;
case HANDLER:
--- 388,408 ----
break;
case AGGR_INIT_EXPR:
! {
! int i = 0;
! tree arg;
! aggr_init_expr_arg_iterator iter;
! dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t));
! dump_child ("fn", AGGR_INIT_EXPR_FN (t));
! FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
! {
! char buffer[32];
! sprintf (buffer, "%u", i);
! dump_child (buffer, arg);
! i++;
! }
! dump_child ("decl", AGGR_INIT_EXPR_SLOT (t));
! }
break;
case HANDLER:
Index: gcc/cp/cp-gimplify.c
===================================================================
*** gcc/cp/cp-gimplify.c (revision 121818)
--- gcc/cp/cp-gimplify.c (working copy)
*************** cp_gimplify_init_expr (tree *expr_p, tre
*** 410,416 ****
if (TREE_CODE (sub) == AGGR_INIT_EXPR)
{
gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
! TREE_OPERAND (sub, 2) = to;
*expr_p = from;
/* The initialization is now a side-effect, so the container can
--- 410,416 ----
if (TREE_CODE (sub) == AGGR_INIT_EXPR)
{
gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
! AGGR_INIT_EXPR_SLOT (sub) = to;
*expr_p = from;
/* The initialization is now a side-effect, so the container can
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h (revision 121818)
--- gcc/cp/cp-tree.h (working copy)
*************** extern void decl_shadowed_for_var_insert
*** 2331,2336 ****
--- 2331,2415 ----
#define AGGR_INIT_VIA_CTOR_P(NODE) \
TREE_LANG_FLAG_0 (AGGR_INIT_EXPR_CHECK (NODE))
+ /* AGGR_INIT_EXPR accessors. These are equivalent to the CALL_EXPR
+ accessors, except for AGGR_INIT_EXPR_SLOT (which takes the place of
+ CALL_EXPR_STATIC_CHAIN). */
+
+ #define AGGR_INIT_EXPR_FN(NODE) TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), 1)
+ #define AGGR_INIT_EXPR_SLOT(NODE) \
+ TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), 2)
+ #define AGGR_INIT_EXPR_ARG(NODE, I) \
+ TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), (I) + 3)
+ #define aggr_init_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH(NODE) - 3)
+
+ /* AGGR_INIT_EXPR_ARGP returns a pointer to the argument vector for NODE.
+ We can't use &AGGR_INIT_EXPR_ARG (NODE, 0) because that will complain if
+ the argument count is zero when checking is enabled. Instead, do
+ the pointer arithmetic to advance past the 3 fixed operands in a
+ AGGR_INIT_EXPR. That produces a valid pointer to just past the end of
+ the operand array, even if it's not valid to dereference it. */
+ #define AGGR_INIT_EXPR_ARGP(NODE) \
+ (&(TREE_OPERAND (AGGR_INIT_EXPR_CHECK (NODE), 0)) + 3)
+
+ /* Abstract iterators for AGGR_INIT_EXPRs. */
+
+ /* Structure containing iterator state. */
+ typedef struct aggr_init_expr_arg_iterator_d GTY (())
+ {
+ tree t; /* the aggr_init_expr */
+ int n; /* argument count */
+ int i; /* next argument index */
+ } aggr_init_expr_arg_iterator;
+
+ /* Initialize the abstract argument list iterator object ITER with the
+ arguments from AGGR_INIT_EXPR node EXP. */
+ static inline void
+ init_aggr_init_expr_arg_iterator (tree exp,
+ aggr_init_expr_arg_iterator *iter)
+ {
+ iter->t = exp;
+ iter->n = aggr_init_expr_nargs (exp);
+ iter->i = 0;
+ }
+
+ /* Return the next argument from abstract argument list iterator object ITER,
+ and advance its state. Return NULL_TREE if there are no more arguments. */
+ static inline tree
+ next_aggr_init_expr_arg (aggr_init_expr_arg_iterator *iter)
+ {
+ tree result;
+ if (iter->i >= iter->n)
+ return NULL_TREE;
+ result = AGGR_INIT_EXPR_ARG (iter->t, iter->i);
+ iter->i++;
+ return result;
+ }
+
+ /* Initialize the abstract argument list iterator object ITER, then advance
+ past and return the first argument. Useful in for expressions, e.g.
+ for (arg = first_aggr_init_expr_arg (exp, &iter); arg;
+ arg = next_aggr_init_expr_arg (&iter)) */
+ static inline tree
+ first_aggr_init_expr_arg (tree exp, aggr_init_expr_arg_iterator *iter)
+ {
+ init_aggr_init_expr_arg_iterator (exp, iter);
+ return next_aggr_init_expr_arg (iter);
+ }
+
+ /* Test whether there are more arguments in abstract argument list iterator
+ ITER, without changing its state. */
+ static inline bool
+ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
+ {
+ return (iter->i < iter->n);
+ }
+
+ /* Iterate through each argument ARG of AGGR_INIT_EXPR CALL, using variable
+ ITER (of type aggr_init_expr_arg_iterator) to hold the iteration state. */
+ #define FOR_EACH_AGGR_INIT_EXPR_ARG(arg, iter, call) \
+ for ((arg) = first_aggr_init_expr_arg ((call), &(iter)); (arg); \
+ (arg) = next_aggr_init_expr_arg (&(iter)))
+
/* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a
TEMPLATE_DECL. This macro determines whether or not a given class
type is really a template type, as opposed to an instantiation or
*************** extern void lang_check_failed (const c
*** 4375,4380 ****
--- 4454,4460 ----
const char *) ATTRIBUTE_NORETURN;
extern tree stabilize_expr (tree, tree *);
extern void stabilize_call (tree, tree *);
+ extern void stabilize_aggr_init (tree, tree *);
extern bool stabilize_init (tree, tree *);
extern tree add_stmt_to_compound (tree, tree);
extern tree cxx_maybe_build_cleanup (tree);
*************** extern cp_lvalue_kind real_lvalue_p (tr
*** 4389,4395 ****
--- 4469,4477 ----
extern bool builtin_valid_in_constant_expr_p (tree);
extern tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...);
+ extern tree build_min_nt_call_list (tree, tree);
extern tree build_min_non_dep (enum tree_code, tree, ...);
+ extern tree build_min_non_dep_call_list (tree, tree, tree);
extern tree build_cplus_new (tree, tree);
extern tree get_target_expr (tree);
extern tree build_cplus_array_type (tree, tree);
Index: gcc/cp/tree.c
===================================================================
*** gcc/cp/tree.c (revision 121818)
--- gcc/cp/tree.c (working copy)
*************** build_local_temp (tree type)
*** 261,268 ****
return slot;
}
! /* INIT is a CALL_EXPR which needs info about its target.
! TYPE is the type that this initialization should appear to have.
Build an encapsulation of the initialization to perform
and return it so that it can be processed by language-independent
--- 261,315 ----
return slot;
}
! /* Set various status flags when building an AGGR_INIT_EXPR object T. */
!
! static void
! process_aggr_init_operands (tree t)
! {
! bool side_effects;
!
! side_effects = TREE_SIDE_EFFECTS (t);
! if (!side_effects)
! {
! int i, n;
! n = TREE_OPERAND_LENGTH (t);
! for (i = 1; i < n; i++)
! {
! tree op = TREE_OPERAND (t, i);
! if (op && TREE_SIDE_EFFECTS (op))
! {
! side_effects = 1;
! break;
! }
! }
! }
! TREE_SIDE_EFFECTS (t) = side_effects;
! }
!
! /* Build an AGGR_INIT_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE,
! FN, and SLOT. NARGS is the number of call arguments which are specified
! as a tree array ARGS. */
!
! static tree
! build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
! tree *args)
! {
! tree t;
! int i;
!
! t = build_vl_exp (AGGR_INIT_EXPR, nargs + 3);
! TREE_TYPE (t) = return_type;
! AGGR_INIT_EXPR_FN (t) = fn;
! AGGR_INIT_EXPR_SLOT (t) = slot;
! for (i = 0; i < nargs; i++)
! AGGR_INIT_EXPR_ARG (t, i) = args[i];
! process_aggr_init_operands (t);
! return t;
! }
!
! /* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
! target. TYPE is the type that this initialization should appear to
! have.
Build an encapsulation of the initialization to perform
and return it so that it can be processed by language-independent
*************** build_cplus_new (tree type, tree init)
*** 280,289 ****
abstract class. */
abstract_virtuals_error (NULL_TREE, type);
! if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return convert (type, init);
- fn = TREE_OPERAND (init, 0);
is_ctor = (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
--- 327,339 ----
abstract class. */
abstract_virtuals_error (NULL_TREE, type);
! if (TREE_CODE (init) == CALL_EXPR)
! fn = CALL_EXPR_FN (init);
! else if (TREE_CODE (init) == AGGR_INIT_EXPR)
! fn = AGGR_INIT_EXPR_FN (init);
! else
return convert (type, init);
is_ctor = (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
*************** build_cplus_new (tree type, tree init)
*** 303,310 ****
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
! rval = build3 (AGGR_INIT_EXPR, void_type_node, fn,
! TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
}
--- 353,366 ----
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
! if (TREE_CODE(init) == CALL_EXPR)
! rval = build_aggr_init_array (void_type_node, fn, slot,
! call_expr_nargs (init),
! CALL_EXPR_ARGP (init));
! else
! rval = build_aggr_init_array (void_type_node, fn, slot,
! aggr_init_expr_nargs (init),
! AGGR_INIT_EXPR_ARGP (init));
TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
}
*************** build_min_nt (enum tree_code code, ...)
*** 1420,1425 ****
--- 1476,1483 ----
int i;
va_list p;
+ gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
+
va_start (p, code);
t = make_node (code);
*************** build_min_nt (enum tree_code code, ...)
*** 1435,1440 ****
--- 1493,1507 ----
return t;
}
+ /* Similar to `build_nt_call_list', but for template definitions of
+ dependent expressions. */
+ tree
+ build_min_nt_call_list (tree fn, tree arglist)
+ {
+ return build_nt_call_list (fn, arglist);
+ }
+
+
/* Similar to `build', but for template definitions. */
tree
*************** build_min (enum tree_code code, tree tt,
*** 1445,1450 ****
--- 1512,1519 ----
int i;
va_list p;
+ gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
+
va_start (p, tt);
t = make_node (code);
*************** build_min_non_dep (enum tree_code code,
*** 1475,1480 ****
--- 1544,1551 ----
int i;
va_list p;
+ gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
+
va_start (p, non_dep);
t = make_node (code);
*************** build_min_non_dep (enum tree_code code,
*** 1497,1502 ****
--- 1568,1586 ----
return t;
}
+ /* Similar to `build_call_list', but for template definitions of non-dependent
+ expressions. NON_DEP is the non-dependent expression that has been
+ built. */
+
+ tree
+ build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist)
+ {
+ tree t = build_nt_call_list (fn, arglist);
+ TREE_TYPE (t) = TREE_TYPE (non_dep);
+ TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
+ return t;
+ }
+
tree
get_type_decl (tree t)
{
*************** cp_tree_equal (tree t1, tree t2)
*** 1615,1623 ****
return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
case CALL_EXPR:
! if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
! return false;
! return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TARGET_EXPR:
{
--- 1699,1718 ----
return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
case CALL_EXPR:
! {
! tree arg1, arg2;
! call_expr_arg_iterator iter1, iter2;
! if (!cp_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
! return false;
! for (arg1 = first_call_expr_arg (t1, &iter1),
! arg2 = first_call_expr_arg (t2, &iter2);
! arg1 && arg2;
! arg1 = next_call_expr_arg (&iter1),
! arg2 = next_call_expr_arg (&iter2))
! if (!cp_tree_equal (arg1, arg2))
! return false;
! return (arg1 || arg2);
! }
case TARGET_EXPR:
{
*************** cp_tree_equal (tree t1, tree t2)
*** 1747,1758 ****
case tcc_binary:
case tcc_comparison:
case tcc_expression:
case tcc_reference:
case tcc_statement:
{
! int i;
! for (i = 0; i < TREE_CODE_LENGTH (code1); ++i)
if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
return false;
--- 1842,1859 ----
case tcc_binary:
case tcc_comparison:
case tcc_expression:
+ case tcc_vl_exp:
case tcc_reference:
case tcc_statement:
{
! int i, n;
!
! n = TREE_OPERAND_LENGTH (t1);
! if (TREE_CODE_CLASS (code1) == tcc_vl_exp
! && n != TREE_OPERAND_LENGTH (t2))
! return false;
! for (i = 0; i < n; ++i)
if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
return false;
*************** void
*** 2442,2462 ****
stabilize_call (tree call, tree *initp)
{
tree inits = NULL_TREE;
! tree t;
if (call == error_mark_node)
return;
! gcc_assert (TREE_CODE (call) == CALL_EXPR
! || TREE_CODE (call) == AGGR_INIT_EXPR);
! for (t = TREE_OPERAND (call, 1); t; t = TREE_CHAIN (t))
! if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
! {
! tree init;
! TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
! inits = add_stmt_to_compound (inits, init);
! }
*initp = inits;
}
--- 2543,2591 ----
stabilize_call (tree call, tree *initp)
{
tree inits = NULL_TREE;
! int i;
! int nargs = call_expr_nargs (call);
if (call == error_mark_node)
return;
! gcc_assert (TREE_CODE (call) == CALL_EXPR);
! for (i = 0; i < nargs; i++)
! {
! tree init;
! CALL_EXPR_ARG (call, i) =
! stabilize_expr (CALL_EXPR_ARG (call, i), &init);
! inits = add_stmt_to_compound (inits, init);
! }
!
! *initp = inits;
! }
!
! /* Like stabilize_expr, but for an AGGR_INIT_EXPR whose arguments we want
! to pre-evaluate. CALL is modified in place to use the pre-evaluated
! arguments, while, upon return, *INITP contains an expression to
! compute the arguments. */
!
! void
! stabilize_aggr_init (tree call, tree *initp)
! {
! tree inits = NULL_TREE;
! int i;
! int nargs = aggr_init_expr_nargs (call);
!
! if (call == error_mark_node)
! return;
!
! gcc_assert (TREE_CODE (call) == AGGR_INIT_EXPR);
!
! for (i = 0; i < nargs; i++)
! {
! tree init;
! AGGR_INIT_EXPR_ARG (call, i) =
! stabilize_expr (AGGR_INIT_EXPR_ARG (call, i), &init);
! inits = add_stmt_to_compound (inits, init);
! }
*initp = inits;
}
*************** stabilize_init (tree init, tree *initp)
*** 2503,2515 ****
if (TREE_CODE (t) == COND_EXPR)
return false;
! if (TREE_CODE (t) == CALL_EXPR
! || TREE_CODE (t) == AGGR_INIT_EXPR)
{
stabilize_call (t, initp);
return true;
}
/* The initialization is being performed via a bitwise copy -- and
the item copied may have side effects. */
return TREE_SIDE_EFFECTS (init);
--- 2632,2649 ----
if (TREE_CODE (t) == COND_EXPR)
return false;
! if (TREE_CODE (t) == CALL_EXPR)
{
stabilize_call (t, initp);
return true;
}
+ if (TREE_CODE (t) == AGGR_INIT_EXPR)
+ {
+ stabilize_aggr_init (t, initp);
+ return true;
+ }
+
/* The initialization is being performed via a bitwise copy -- and
the item copied may have side effects. */
return TREE_SIDE_EFFECTS (init);
Index: gcc/cp/cxx-pretty-print.c
===================================================================
*** gcc/cp/cxx-pretty-print.c (revision 121818)
--- gcc/cp/cxx-pretty-print.c (working copy)
*************** pp_cxx_postfix_expression (cxx_pretty_pr
*** 412,420 ****
case AGGR_INIT_EXPR:
case CALL_EXPR:
{
! tree fun = TREE_OPERAND (t, 0);
! tree args = TREE_OPERAND (t, 1);
tree saved_scope = pp->enclosing_scope;
if (TREE_CODE (fun) == ADDR_EXPR)
fun = TREE_OPERAND (fun, 0);
--- 412,422 ----
case AGGR_INIT_EXPR:
case CALL_EXPR:
{
! tree fun = (code == AGGR_INIT_EXPR ? AGGR_INIT_EXPR_FN (t)
! : CALL_EXPR_FN (t));
tree saved_scope = pp->enclosing_scope;
+ bool skipfirst = false;
+ tree arg;
if (TREE_CODE (fun) == ADDR_EXPR)
fun = TREE_OPERAND (fun, 0);
*************** pp_cxx_postfix_expression (cxx_pretty_pr
*** 427,435 ****
;
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun))
{
! tree object = code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t)
! ? TREE_OPERAND (t, 2)
! : TREE_VALUE (args);
while (TREE_CODE (object) == NOP_EXPR)
object = TREE_OPERAND (object, 0);
--- 429,439 ----
;
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun))
{
! tree object = (code == AGGR_INIT_EXPR
! ? (AGGR_INIT_VIA_CTOR_P (t)
! ? AGGR_INIT_EXPR_SLOT (t)
! : AGGR_INIT_EXPR_ARG (t, 0))
! : CALL_EXPR_ARG (t, 0));
while (TREE_CODE (object) == NOP_EXPR)
object = TREE_OPERAND (object, 0);
*************** pp_cxx_postfix_expression (cxx_pretty_pr
*** 447,464 ****
pp_cxx_postfix_expression (pp, object);
pp_cxx_arrow (pp);
}
! args = TREE_CHAIN (args);
pp->enclosing_scope = strip_pointer_operator (TREE_TYPE (object));
}
pp_cxx_postfix_expression (pp, fun);
pp->enclosing_scope = saved_scope;
! pp_cxx_call_argument_list (pp, args);
}
if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t))
{
pp_cxx_separate_with (pp, ',');
! pp_cxx_postfix_expression (pp, TREE_OPERAND (t, 2));
}
break;
--- 451,499 ----
pp_cxx_postfix_expression (pp, object);
pp_cxx_arrow (pp);
}
! skipfirst = true;
pp->enclosing_scope = strip_pointer_operator (TREE_TYPE (object));
}
pp_cxx_postfix_expression (pp, fun);
pp->enclosing_scope = saved_scope;
! pp_cxx_left_paren (pp);
! if (code == AGGR_INIT_EXPR)
! {
! aggr_init_expr_arg_iterator iter;
! FOR_EACH_AGGR_INIT_EXPR_ARG (arg, iter, t)
! {
! if (skipfirst)
! skipfirst = false;
! else
! {
! pp_cxx_expression (pp, arg);
! if (more_aggr_init_expr_args_p (&iter))
! pp_cxx_separate_with (pp, ',');
! }
! }
! }
! else
! {
! call_expr_arg_iterator iter;
! FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
! {
! if (skipfirst)
! skipfirst = false;
! else
! {
! pp_cxx_expression (pp, arg);
! if (more_call_expr_args_p (&iter))
! pp_cxx_separate_with (pp, ',');
! }
! }
! }
! pp_cxx_right_paren (pp);
}
if (code == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P (t))
{
pp_cxx_separate_with (pp, ',');
! pp_cxx_postfix_expression (pp, AGGR_INIT_EXPR_SLOT (t));
}
break;
Index: gcc/cp/pt.c
===================================================================
*** gcc/cp/pt.c (revision 121818)
--- gcc/cp/pt.c (working copy)
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 8347,8358 ****
NULL_TREE, NULL_TREE);
case CALL_EXPR:
! return build_nt (code,
! tsubst_copy (TREE_OPERAND (t, 0), args,
! complain, in_decl),
! tsubst_copy (TREE_OPERAND (t, 1), args, complain,
! in_decl),
! NULL_TREE);
case COND_EXPR:
case MODOP_EXPR:
--- 8347,8361 ----
NULL_TREE, NULL_TREE);
case CALL_EXPR:
! {
! int n = VL_EXP_OPERAND_LENGTH (t);
! tree result = build_vl_exp (CALL_EXPR, n);
! int i;
! for (i = 0; i < n; i++)
! TREE_OPERAND (t, i) = tsubst_copy (TREE_OPERAND (t, i), args,
! complain, in_decl);
! return result;
! }
case COND_EXPR:
case MODOP_EXPR:
*************** tsubst_copy_and_build (tree t,
*** 9268,9274 ****
bool qualified_p;
bool koenig_p;
! function = TREE_OPERAND (t, 0);
/* When we parsed the expression, we determined whether or
not Koenig lookup should be performed. */
koenig_p = KOENIG_LOOKUP_P (t);
--- 9271,9277 ----
bool qualified_p;
bool koenig_p;
! function = CALL_EXPR_FN (t);
/* When we parsed the expression, we determined whether or
not Koenig lookup should be performed. */
koenig_p = KOENIG_LOOKUP_P (t);
*************** tsubst_copy_and_build (tree t,
*** 9301,9307 ****
qualified_p = true;
}
! call_args = RECUR (TREE_OPERAND (t, 1));
/* We do not perform argument-dependent lookup if normal
lookup finds a non-function, in accordance with the
--- 9304,9311 ----
qualified_p = true;
}
! /* FIXME: Rewrite this so as not to construct an arglist. */
! call_args = RECUR (CALL_EXPR_ARGS (t));
/* We do not perform argument-dependent lookup if normal
lookup finds a non-function, in accordance with the
*************** value_dependent_expression_p (tree expre
*** 13057,13065 ****
(TREE_OPERAND (expression, 1))));
case tcc_expression:
{
int i;
! for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (expression)); ++i)
/* In some cases, some of the operands may be missing.
(For example, in the case of PREDECREMENT_EXPR, the
amount to increment by may be missing.) That doesn't
--- 13061,13070 ----
(TREE_OPERAND (expression, 1))));
case tcc_expression:
+ case tcc_vl_exp:
{
int i;
! for (i = 0; i < TREE_OPERAND_LENGTH (expression); ++i)
/* In some cases, some of the operands may be missing.
(For example, in the case of PREDECREMENT_EXPR, the
amount to increment by may be missing.) That doesn't
Index: gcc/cp/semantics.c
===================================================================
*** gcc/cp/semantics.c (revision 121818)
--- gcc/cp/semantics.c (working copy)
*************** finish_call_expr (tree fn, tree args, bo
*** 1789,1795 ****
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
{
! result = build_nt (CALL_EXPR, fn, args, NULL_TREE);
KOENIG_LOOKUP_P (result) = koenig_p;
return result;
}
--- 1789,1795 ----
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
{
! result = build_nt_call_list (fn, args);
KOENIG_LOOKUP_P (result) = koenig_p;
return result;
}
*************** finish_call_expr (tree fn, tree args, bo
*** 1846,1852 ****
if (processing_template_decl)
{
if (type_dependent_expression_p (object))
! return build_nt (CALL_EXPR, orig_fn, orig_args, NULL_TREE);
object = build_non_dependent_expr (object);
}
--- 1846,1852 ----
if (processing_template_decl)
{
if (type_dependent_expression_p (object))
! return build_nt_call_list (orig_fn, orig_args);
object = build_non_dependent_expr (object);
}
*************** finish_call_expr (tree fn, tree args, bo
*** 1890,1897 ****
if (processing_template_decl)
{
! result = build3 (CALL_EXPR, TREE_TYPE (result), orig_fn,
! orig_args, NULL_TREE);
KOENIG_LOOKUP_P (result) = koenig_p;
}
return result;
--- 1890,1896 ----
if (processing_template_decl)
{
! result = build_call_list (TREE_TYPE (result), orig_fn, orig_args);
KOENIG_LOOKUP_P (result) = koenig_p;
}
return result;
*************** simplify_aggr_init_expr (tree *tp)
*** 2975,2983 ****
tree aggr_init_expr = *tp;
/* Form an appropriate CALL_EXPR. */
! tree fn = TREE_OPERAND (aggr_init_expr, 0);
! tree args = TREE_OPERAND (aggr_init_expr, 1);
! tree slot = TREE_OPERAND (aggr_init_expr, 2);
tree type = TREE_TYPE (slot);
tree call_expr;
--- 2974,2981 ----
tree aggr_init_expr = *tp;
/* Form an appropriate CALL_EXPR. */
! tree fn = AGGR_INIT_EXPR_FN (aggr_init_expr);
! tree slot = AGGR_INIT_EXPR_SLOT (aggr_init_expr);
tree type = TREE_TYPE (slot);
tree call_expr;
*************** simplify_aggr_init_expr (tree *tp)
*** 2995,3017 ****
style = arg;
}
if (style == ctor)
{
/* Replace the first argument to the ctor with the address of the
slot. */
- tree addr;
-
- args = TREE_CHAIN (args);
cxx_mark_addressable (slot);
! addr = build1 (ADDR_EXPR, build_pointer_type (type), slot);
! args = tree_cons (NULL_TREE, addr, args);
}
!
! call_expr = build3 (CALL_EXPR,
! TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! fn, args, NULL_TREE);
!
! if (style == arg)
{
/* Just mark it addressable here, and leave the rest to
expand_call{,_inline}. */
--- 2993,3012 ----
style = arg;
}
+ call_expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
+ fn,
+ aggr_init_expr_nargs (aggr_init_expr),
+ AGGR_INIT_EXPR_ARGP (aggr_init_expr));
+
if (style == ctor)
{
/* Replace the first argument to the ctor with the address of the
slot. */
cxx_mark_addressable (slot);
! CALL_EXPR_ARG (call_expr, 0) =
! build1 (ADDR_EXPR, build_pointer_type (type), slot);
}
! else if (style == arg)
{
/* Just mark it addressable here, and leave the rest to
expand_call{,_inline}. */
Index: gcc/cp/decl2.c
===================================================================
*** gcc/cp/decl2.c (revision 121818)
--- gcc/cp/decl2.c (working copy)
*************** build_offset_ref_call_from_tree (tree fn
*** 3401,3407 ****
|| TREE_CODE (fn) == MEMBER_REF);
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
! return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
/* Transform the arguments and add the implicit "this"
parameter. That must be done before the FN is transformed
--- 3401,3407 ----
|| TREE_CODE (fn) == MEMBER_REF);
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
! return build_min_nt_call_list (fn, args);
/* Transform the arguments and add the implicit "this"
parameter. That must be done before the FN is transformed
*************** build_offset_ref_call_from_tree (tree fn
*** 3431,3437 ****
expr = build_function_call (fn, args);
if (processing_template_decl && expr != error_mark_node)
! return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args, NULL_TREE);
return expr;
}
--- 3431,3437 ----
expr = build_function_call (fn, args);
if (processing_template_decl && expr != error_mark_node)
! return build_min_non_dep_call_list (expr, orig_fn, orig_args);
return expr;
}
Index: gcc/cp/parser.c
===================================================================
*** gcc/cp/parser.c (revision 121818)
--- gcc/cp/parser.c (working copy)
*************** cp_parser_postfix_expression (cp_parser
*** 4443,4450 ****
|| any_type_dependent_arguments_p (args)))
{
postfix_expression
! = build_min_nt (CALL_EXPR, postfix_expression,
! args, NULL_TREE);
break;
}
--- 4443,4449 ----
|| any_type_dependent_arguments_p (args)))
{
postfix_expression
! = build_min_nt_call_list (postfix_expression, args);
break;
}