diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-05-05 23:09:16 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2009-05-05 23:09:16 +0200 |
commit | 32f579f6ebde02d94ac8fbd0379b1d0207dd9ac5 (patch) | |
tree | 04135baa9f723c92400dc6a7d81d23fdc587597b /gcc/gimplify.c | |
parent | 6e57a01df44693719cdaa9c552bfc3d729f5c095 (diff) | |
download | gcc-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.c | 61 |
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); |