/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@redhat.com>
#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
-#include "c-common.h"
-#include "toplev.h"
+#include "c-family/c-common.h"
#include "tree-iterator.h"
#include "gimple.h"
#include "hashtab.h"
begin_bc_block (enum bc_t bc)
{
tree label = create_artificial_label (input_location);
- TREE_CHAIN (label) = bc_label[bc];
+ DECL_CHAIN (label) = bc_label[bc];
bc_label[bc] = label;
return label;
}
gimple_seq_add_stmt (&body, gimple_build_label (label));
}
- bc_label[bc] = TREE_CHAIN (label);
- TREE_CHAIN (label) = NULL_TREE;
+ bc_label[bc] = DECL_CHAIN (label);
+ DECL_CHAIN (label) = NULL_TREE;
return body;
}
/* Gimplify initialization from an AGGR_INIT_EXPR. */
static void
-cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
+cp_gimplify_init_expr (tree *expr_p)
{
tree from = TREE_OPERAND (*expr_p, 1);
tree to = TREE_OPERAND (*expr_p, 0);
tree t;
- tree slot = NULL_TREE;
/* What about code that pulls out the temp and uses it elsewhere? I
think that such code never uses the TARGET_EXPR as an initializer. If
I'm wrong, we'll abort because the temp won't have any RTL. In that
case, I guess we'll need to replace references somehow. */
if (TREE_CODE (from) == TARGET_EXPR)
- {
- slot = TARGET_EXPR_SLOT (from);
- from = TARGET_EXPR_INITIAL (from);
- }
+ from = TARGET_EXPR_INITIAL (from);
/* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
inside the TARGET_EXPR. */
Should we add a target parm to gimplify_expr instead? No, as in this
case we want to replace the INIT_EXPR. */
- if (TREE_CODE (sub) == AGGR_INIT_EXPR)
+ if (TREE_CODE (sub) == AGGR_INIT_EXPR
+ || TREE_CODE (sub) == VEC_INIT_EXPR)
{
- gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
- AGGR_INIT_EXPR_SLOT (sub) = to;
+ if (TREE_CODE (sub) == AGGR_INIT_EXPR)
+ AGGR_INIT_EXPR_SLOT (sub) = to;
+ else
+ VEC_INIT_EXPR_SLOT (sub) = to;
*expr_p = from;
/* The initialization is now a side-effect, so the container can
tree stmt = *expr_p;
tree temp = voidify_wrapper_expr (stmt, NULL);
tree body = TREE_OPERAND (stmt, 0);
+ gimple_seq try_ = NULL;
+ gimple_seq catch_ = NULL;
+ gimple mnt;
- stmt = build_gimple_eh_filter_tree (body, NULL_TREE,
- build_call_n (terminate_node, 0));
+ gimplify_and_add (body, &try_);
+ mnt = gimple_build_eh_must_not_throw (terminate_node);
+ gimplify_seq_add_stmt (&catch_, mnt);
+ mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
- gimplify_and_add (stmt, pre_p);
+ gimplify_seq_add_stmt (pre_p, mnt);
if (temp)
{
*expr_p = temp;
ret = GS_OK;
break;
+ case VEC_INIT_EXPR:
+ {
+ location_t loc = input_location;
+ tree init = VEC_INIT_EXPR_INIT (*expr_p);
+ int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
+ gcc_assert (EXPR_HAS_LOCATION (*expr_p));
+ input_location = EXPR_LOCATION (*expr_p);
+ *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
+ init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
+ from_array,
+ tf_warning_or_error);
+ ret = GS_OK;
+ input_location = loc;
+ }
+ break;
+
case THROW_EXPR:
/* FIXME communicate throw type to back end, probably by moving
THROW_EXPR into ../tree.def. */
LHS of an assignment might also be involved in the RHS, as in bug
25979. */
case INIT_EXPR:
- cp_gimplify_init_expr (expr_p, pre_p, post_p);
+ cp_gimplify_init_expr (expr_p);
+ if (TREE_CODE (*expr_p) != INIT_EXPR)
+ return GS_OK;
+ /* Otherwise fall through. */
+ case MODIFY_EXPR:
+ {
+ /* If the back end isn't clever enough to know that the lhs and rhs
+ types are the same, add an explicit conversion. */
+ tree op0 = TREE_OPERAND (*expr_p, 0);
+ tree op1 = TREE_OPERAND (*expr_p, 1);
+
+ if (!error_operand_p (op0)
+ && !error_operand_p (op1)
+ && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
+ || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
+ && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
+ TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (op0), op1);
+
+ else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
+ || (TREE_CODE (op1) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (op1) == 0)
+ || (TREE_CODE (op1) == CALL_EXPR
+ && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
+ && is_really_empty_class (TREE_TYPE (op0)))
+ {
+ /* Remove any copies of empty classes. We check that the RHS
+ has a simple form so that TARGET_EXPRs and non-empty
+ CONSTRUCTORs get reduced properly, and we leave the return
+ slot optimization alone because it isn't a copy (FIXME so it
+ shouldn't be represented as one).
+
+ Also drop volatile variables on the RHS to avoid infinite
+ recursion from gimplify_expr trying to load the value. */
+ if (!TREE_SIDE_EFFECTS (op1)
+ || (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
+ *expr_p = op0;
+ else if (TREE_CODE (op1) == MEM_REF
+ && TREE_THIS_VOLATILE (op1))
+ {
+ /* Similarly for volatile MEM_REFs on the RHS. */
+ if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
+ *expr_p = op0;
+ else
+ *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
+ TREE_OPERAND (op1, 0), op0);
+ }
+ else
+ *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
+ op0, op1);
+ }
+ }
ret = GS_OK;
break;
IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
= TREE_OPERAND (stmt, 0);
- TREE_CHAIN (using_directive) = BLOCK_VARS (block);
+ DECL_CHAIN (using_directive) = BLOCK_VARS (block);
BLOCK_VARS (block) = using_directive;
}
/* The USING_STMT won't appear in GENERIC. */
struct cp_genericize_data wtd;
/* Fix up the types of parms passed by invisible reference. */
- for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
+ for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
if (TREE_ADDRESSABLE (TREE_TYPE (t)))
{
/* If a function's arguments are copied to create a thunk,
return NULL;
nargs = list_length (DECL_ARGUMENTS (fn));
- argarray = (tree *) alloca (nargs * sizeof (tree));
+ argarray = XALLOCAVEC (tree, nargs);
defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
if (arg2)
tree var;
if (outer)
- for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var))
+ for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
if (DECL_NAME (decl) == DECL_NAME (var)
&& (TYPE_MAIN_VARIANT (type)
== TYPE_MAIN_VARIANT (TREE_TYPE (var))))