diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 91 |
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: |