summaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c91
1 files changed, 68 insertions, 23 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 515c58ed57e..993f7c2ae44 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2449,12 +2449,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
condition is true or false, respectively. If null, we should generate
our own to skip over the evaluation of this specific expression.
+ LOCUS is the source location of the COND_EXPR.
+
This function is the tree equivalent of do_jump.
shortcut_cond_r should only be called by shortcut_cond_expr. */
static tree
-shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
+shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
+ location_t locus)
{
tree local_label = NULL_TREE;
tree t, expr = NULL;
@@ -2464,6 +2467,8 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
shortcut_cond_expr will append the real blocks later. */
if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
{
+ location_t new_locus;
+
/* Turn if (a && b) into
if (a); else goto no;
@@ -2473,15 +2478,20 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
if (false_label_p == NULL)
false_label_p = &local_label;
- t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p);
+ /* Keep the original source location on the first 'if'. */
+ t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus);
append_to_statement_list (t, &expr);
- t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
- false_label_p);
+ /* Set the source location of the && on the second 'if'. */
+ new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+ t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
+ new_locus);
append_to_statement_list (t, &expr);
}
else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
{
+ location_t new_locus;
+
/* Turn if (a || b) into
if (a) goto yes;
@@ -2491,31 +2501,41 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
if (true_label_p == NULL)
true_label_p = &local_label;
- t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL);
+ /* Keep the original source location on the first 'if'. */
+ t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus);
append_to_statement_list (t, &expr);
- t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
- false_label_p);
+ /* Set the source location of the || on the second 'if'. */
+ new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
+ t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
+ new_locus);
append_to_statement_list (t, &expr);
}
else if (TREE_CODE (pred) == COND_EXPR)
{
+ location_t new_locus;
+
/* As long as we're messing with gotos, turn if (a ? b : c) into
if (a)
if (b) goto yes; else goto no;
else
if (c) goto yes; else goto no; */
+
+ /* Keep the original source location on the first 'if'. Set the source
+ location of the ? on the second 'if'. */
+ new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus;
expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
- false_label_p),
+ false_label_p, locus),
shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
- false_label_p));
+ false_label_p, new_locus));
}
else
{
expr = build3 (COND_EXPR, void_type_node, pred,
build_and_jump (true_label_p),
build_and_jump (false_label_p));
+ SET_EXPR_LOCATION (expr, locus);
}
if (local_label)
@@ -2547,14 +2567,24 @@ shortcut_cond_expr (tree expr)
/* First do simple transformations. */
if (!else_se)
{
- /* If there is no 'else', turn (a && b) into if (a) if (b). */
+ /* If there is no 'else', turn
+ if (a && b) then c
+ into
+ if (a) if (b) then c. */
while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
{
+ /* Keep the original source location on the first 'if'. */
+ location_t locus = EXPR_HAS_LOCATION (expr)
+ ? EXPR_LOCATION (expr) : input_location;
TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
+ /* Set the source location of the && on the second 'if'. */
+ if (EXPR_HAS_LOCATION (pred))
+ SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
then_ = shortcut_cond_expr (expr);
then_se = then_ && TREE_SIDE_EFFECTS (then_);
pred = TREE_OPERAND (pred, 0);
expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
+ SET_EXPR_LOCATION (expr, locus);
}
}
@@ -2566,11 +2596,18 @@ shortcut_cond_expr (tree expr)
if (a); else if (b); else d. */
while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
{
+ /* Keep the original source location on the first 'if'. */
+ location_t locus = EXPR_HAS_LOCATION (expr)
+ ? EXPR_LOCATION (expr) : input_location;
TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
+ /* Set the source location of the || on the second 'if'. */
+ if (EXPR_HAS_LOCATION (pred))
+ SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred));
else_ = shortcut_cond_expr (expr);
else_se = else_ && TREE_SIDE_EFFECTS (else_);
pred = TREE_OPERAND (pred, 0);
expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
+ SET_EXPR_LOCATION (expr, locus);
}
}
@@ -2624,17 +2661,19 @@ shortcut_cond_expr (tree expr)
/* If there was nothing else in our arms, just forward the label(s). */
if (!then_se && !else_se)
- return shortcut_cond_r (pred, true_label_p, false_label_p);
+ return shortcut_cond_r (pred, true_label_p, false_label_p,
+ EXPR_HAS_LOCATION (expr)
+ ? EXPR_LOCATION (expr) : input_location);
/* If our last subexpression already has a terminal label, reuse it. */
if (else_se)
- expr = expr_last (else_);
+ t = expr_last (else_);
else if (then_se)
- expr = expr_last (then_);
+ t = expr_last (then_);
else
- expr = NULL;
- if (expr && TREE_CODE (expr) == LABEL_EXPR)
- end_label = LABEL_EXPR_LABEL (expr);
+ t = NULL;
+ if (t && TREE_CODE (t) == LABEL_EXPR)
+ end_label = LABEL_EXPR_LABEL (t);
/* If we don't care about jumping to the 'else' branch, jump to the end
if the condition is false. */
@@ -2655,7 +2694,9 @@ shortcut_cond_expr (tree expr)
non-void function. */
jump_over_else = block_may_fallthru (then_);
- pred = shortcut_cond_r (pred, true_label_p, false_label_p);
+ pred = shortcut_cond_r (pred, true_label_p, false_label_p,
+ EXPR_HAS_LOCATION (expr)
+ ? EXPR_LOCATION (expr) : input_location);
expr = NULL;
append_to_statement_list (pred, &expr);
@@ -2665,7 +2706,10 @@ shortcut_cond_expr (tree expr)
{
if (jump_over_else)
{
+ tree last = expr_last (expr);
t = build_and_jump (&end_label);
+ if (EXPR_HAS_LOCATION (last))
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (last));
append_to_statement_list (t, &expr);
}
if (emit_false)
@@ -4428,13 +4472,11 @@ gimplify_scalar_mode_aggregate_compare (tree *expr_p)
a && b ? true : false
- gimplify_cond_expr will do the rest.
-
- PRE_P points to the list where side effects that must happen before
- *EXPR_P should be stored. */
+ LOCUS is the source location to be put on the generated COND_EXPR.
+ gimplify_cond_expr will do the rest. */
static enum gimplify_status
-gimplify_boolean_expr (tree *expr_p)
+gimplify_boolean_expr (tree *expr_p, location_t locus)
{
/* Preserve the original type of the expression. */
tree type = TREE_TYPE (*expr_p);
@@ -4443,6 +4485,8 @@ gimplify_boolean_expr (tree *expr_p)
fold_convert (type, boolean_true_node),
fold_convert (type, boolean_false_node));
+ SET_EXPR_LOCATION (*expr_p, locus);
+
return GS_OK;
}
@@ -6430,7 +6474,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
- ret = gimplify_boolean_expr (expr_p);
+ /* Pass the source location of the outer expression. */
+ ret = gimplify_boolean_expr (expr_p, saved_location);
break;
case TRUTH_NOT_EXPR: