aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-05-05 23:09:16 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2009-05-05 23:09:16 +0200
commit32f579f6ebde02d94ac8fbd0379b1d0207dd9ac5 (patch)
tree04135baa9f723c92400dc6a7d81d23fdc587597b /gcc/gimplify.c
parent6e57a01df44693719cdaa9c552bfc3d729f5c095 (diff)
downloadgcc-32f579f6ebde02d94ac8fbd0379b1d0207dd9ac5.zip
gcc-32f579f6ebde02d94ac8fbd0379b1d0207dd9ac5.tar.gz
gcc-32f579f6ebde02d94ac8fbd0379b1d0207dd9ac5.tar.bz2
re PR middle-end/39666 (spurious warning with ranged-switch statements)
PR middle-end/39666 * gimplify.c (gimplify_switch_expr): If case labels cover the whole range of the type, but default label is missing, add it with one of the existing labels instead of adding a new label for it. * gcc.dg/pr39666-1.c: New test. * gcc.dg/pr39666-2.c: Likewise. * g++.dg/warn/Wuninitialized-4.C: Likewise. * g++.dg/warn/Wuninitialized-5.C: Likewise. * gfortran.dg/pr39666-1.f90: Likewise. * gfortran.dg/pr39666-2.f90: Likewise. From-SVN: r147136
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c61
1 files changed, 52 insertions, 9 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 0909d31..0c33dab 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1604,20 +1604,63 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
}
len = i;
+ if (!VEC_empty (tree, labels))
+ sort_case_labels (labels);
+
if (!default_case)
{
- gimple new_default;
+ tree type = TREE_TYPE (switch_expr);
/* If the switch has no default label, add one, so that we jump
- around the switch body. */
- default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
- NULL_TREE, create_artificial_label ());
- new_default = gimple_build_label (CASE_LABEL (default_case));
- gimplify_seq_add_stmt (&switch_body_seq, new_default);
- }
+ around the switch body. If the labels already cover the whole
+ range of type, add the default label pointing to one of the
+ existing labels. */
+ if (type == void_type_node)
+ type = TREE_TYPE (SWITCH_COND (switch_expr));
+ if (len
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_MIN_VALUE (type)
+ && TYPE_MAX_VALUE (type)
+ && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
+ TYPE_MIN_VALUE (type)))
+ {
+ tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
+ if (!high)
+ high = CASE_LOW (VEC_index (tree, labels, len - 1));
+ if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type)))
+ {
+ for (i = 1; i < len; i++)
+ {
+ high = CASE_LOW (VEC_index (tree, labels, i));
+ low = CASE_HIGH (VEC_index (tree, labels, i - 1));
+ if (!low)
+ low = CASE_LOW (VEC_index (tree, labels, i - 1));
+ if ((TREE_INT_CST_LOW (low) + 1
+ != TREE_INT_CST_LOW (high))
+ || (TREE_INT_CST_HIGH (low)
+ + (TREE_INT_CST_LOW (high) == 0)
+ != TREE_INT_CST_HIGH (high)))
+ break;
+ }
+ if (i == len)
+ default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+ NULL_TREE, NULL_TREE,
+ CASE_LABEL (VEC_index (tree,
+ labels, 0)));
+ }
+ }
- if (!VEC_empty (tree, labels))
- sort_case_labels (labels);
+ if (!default_case)
+ {
+ gimple new_default;
+
+ default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+ NULL_TREE, NULL_TREE,
+ create_artificial_label ());
+ new_default = gimple_build_label (CASE_LABEL (default_case));
+ gimplify_seq_add_stmt (&switch_body_seq, new_default);
+ }
+ }
gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr),
default_case, labels);