gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
{
tree expr = *expr_p;
- tree type = TREE_TYPE (expr);
- location_t loc = EXPR_LOCATION (expr);
- tree tmp, arm1, arm2;
+ tree tmp, type, arm1, arm2;
enum gimplify_status ret;
tree label_true, label_false, label_cont;
bool have_then_clause_p, have_else_clause_p;
gimple gimple_cond;
enum tree_code pred_code;
gimple_seq seq = NULL;
+ location_t loc = EXPR_LOCATION (*expr_p);
+
+ type = TREE_TYPE (expr);
/* If this COND_EXPR has a value, copy the values into a temporary within
the arms. */
- if (!VOID_TYPE_P (type))
+ if (! VOID_TYPE_P (type))
{
- tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
tree result;
- /* If either an rvalue is ok or we do not require an lvalue, create the
- temporary. But we cannot do that if the type is addressable. */
- if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
+ /* If an rvalue is ok or we do not require an lvalue, avoid creating
+ an addressable temporary. */
+ if (((fallback & fb_rvalue)
+ || !(fallback & fb_lvalue))
&& !TREE_ADDRESSABLE (type))
{
if (gimplify_ctxp->allow_rhs_cond_expr
/* If either branch has side effects or could trap, it can't be
evaluated unconditionally. */
- && !TREE_SIDE_EFFECTS (then_)
- && !generic_expr_could_trap_p (then_)
- && !TREE_SIDE_EFFECTS (else_)
- && !generic_expr_could_trap_p (else_))
+ && !TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1))
+ && !generic_expr_could_trap_p (TREE_OPERAND (*expr_p, 1))
+ && !TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 2))
+ && !generic_expr_could_trap_p (TREE_OPERAND (*expr_p, 2)))
return gimplify_pure_cond_expr (expr_p, pre_p);
- tmp = create_tmp_var (type, "iftmp");
- result = tmp;
+ result = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
+ ret = GS_ALL_DONE;
}
-
- /* Otherwise, only create and copy references to the values. */
else
{
- type = build_pointer_type (type);
+ tree type = build_pointer_type (TREE_TYPE (expr));
- if (!VOID_TYPE_P (TREE_TYPE (then_)))
- then_ = build_fold_addr_expr_loc (loc, then_);
+ if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
+ TREE_OPERAND (expr, 1) =
+ build_fold_addr_expr_loc (loc, TREE_OPERAND (expr, 1));
- if (!VOID_TYPE_P (TREE_TYPE (else_)))
- else_ = build_fold_addr_expr_loc (loc, else_);
-
- expr
- = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
+ if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
+ TREE_OPERAND (expr, 2) =
+ build_fold_addr_expr_loc (loc, TREE_OPERAND (expr, 2));
tmp = create_tmp_var (type, "iftmp");
+
+ expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 2));
+
result = build_fold_indirect_ref_loc (loc, tmp);
}
- /* Build the new then clause, `tmp = then_;'. But don't build the
- assignment if the value is void; in C++ it can be if it's a throw. */
- if (!VOID_TYPE_P (TREE_TYPE (then_)))
- TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_);
+ /* Build the then clause, 't1 = a;'. But don't build an assignment
+ if this branch is void; in C++ it can be, if it's a throw. */
+ if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
+ TREE_OPERAND (expr, 1)
+ = build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, TREE_OPERAND (expr, 1));
- /* Similarly, build the new else clause, `tmp = else_;'. */
- if (!VOID_TYPE_P (TREE_TYPE (else_)))
- TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_);
+ /* Build the else clause, 't1 = b;'. */
+ if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
+ TREE_OPERAND (expr, 2)
+ = build2 (MODIFY_EXPR, TREE_TYPE (tmp), tmp, TREE_OPERAND (expr, 2));
TREE_TYPE (expr) = void_type_node;
recalculate_side_effects (expr);