2019-08-05 Richard Biener PR middle-end/91169 * fold-const.c (get_array_ctor_element_at_index): Create offset_ints according to the sign of the index type and treat that as signed if it is obviously so. * gnat.dg/array37.adb: New testcase. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 274112) +++ gcc/fold-const.c (working copy) @@ -11850,6 +11850,7 @@ get_array_ctor_element_at_index (tree ct unsigned *ctor_idx) { tree index_type = NULL_TREE; + signop index_sgn = UNSIGNED; offset_int low_bound = 0; if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE) @@ -11860,22 +11861,37 @@ get_array_ctor_element_at_index (tree ct /* Static constructors for variably sized objects makes no sense. */ gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST); index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type)); - low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type)); + /* ??? When it is obvious that the range is signed, treat it so. */ + if (TYPE_UNSIGNED (index_type) + && TYPE_MAX_VALUE (domain_type) + && tree_int_cst_lt (TYPE_MAX_VALUE (domain_type), + TYPE_MIN_VALUE (domain_type))) + { + index_sgn = SIGNED; + low_bound + = offset_int::from (wi::to_wide (TYPE_MIN_VALUE (domain_type)), + SIGNED); + } + else + { + index_sgn = TYPE_SIGN (index_type); + low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type)); + } } } if (index_type) access_index = wi::ext (access_index, TYPE_PRECISION (index_type), - TYPE_SIGN (index_type)); + index_sgn); - offset_int index = low_bound - 1; + offset_int index = low_bound; if (index_type) - index = wi::ext (index, TYPE_PRECISION (index_type), - TYPE_SIGN (index_type)); + index = wi::ext (index, TYPE_PRECISION (index_type), index_sgn); - offset_int max_index; + offset_int max_index = index; unsigned cnt; tree cfield, cval; + bool first_p = true; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval) { @@ -11885,27 +11901,34 @@ get_array_ctor_element_at_index (tree ct if (cfield) { if (TREE_CODE (cfield) == INTEGER_CST) - max_index = index = wi::to_offset (cfield); + max_index = index + = offset_int::from (wi::to_wide (cfield), index_sgn); else { gcc_assert (TREE_CODE (cfield) == RANGE_EXPR); - index = wi::to_offset (TREE_OPERAND (cfield, 0)); - max_index = wi::to_offset (TREE_OPERAND (cfield, 1)); + index = offset_int::from (wi::to_wide (TREE_OPERAND (cfield, 0)), + index_sgn); + max_index + = offset_int::from (wi::to_wide (TREE_OPERAND (cfield, 1)), + index_sgn); + gcc_checking_assert (wi::le_p (index, max_index, index_sgn)); } } - else + else if (!first_p) { - index += 1; + index = max_index + 1; if (index_type) - index = wi::ext (index, TYPE_PRECISION (index_type), - TYPE_SIGN (index_type)); + index = wi::ext (index, TYPE_PRECISION (index_type), index_sgn); + gcc_checking_assert (wi::gt_p (index, max_index, index_sgn)); max_index = index; } + else + first_p = false; /* Do we have match? */ - if (wi::cmpu (access_index, index) >= 0) + if (wi::cmp (access_index, index, index_sgn) >= 0) { - if (wi::cmpu (access_index, max_index) <= 0) + if (wi::cmp (access_index, max_index, index_sgn) <= 0) { if (ctor_idx) *ctor_idx = cnt; Index: gcc/testsuite/gnat.dg/array37.adb =================================================================== --- gcc/testsuite/gnat.dg/array37.adb (revision 0) +++ gcc/testsuite/gnat.dg/array37.adb (working copy) @@ -0,0 +1,19 @@ +-- { dg-do run } +-- { dg-options "-O" } + +procedure Array37 is + + type Arr is array (Integer range -1 .. 1) of Integer; + + A : Arr := (-100, 0, 100); + + function Ident (I : Integer) return Integer IS + begin + return I; + end; + +begin + if Ident (A (1)) <= Ident (A (0)) then + raise Program_Error; + end if; +end;