https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- Btw, the anti-ranges can be made "signed" by /* If we have an unsigned anti-range convert it to the respective signed type. */ if (range_type == VR_ANTI_RANGE && TYPE_UNSIGNED (exptype) && wi::les_p (max, min)) { std::swap (max, min); min = min + 1; max = max - 1; range_type = VR_RANGE; } simplifying the anti-range handling to just the signed case. Then you run into the same issue in the signed anti-range handling. else if (wi::les_p (min - 1, wzero)) { /* EXP is not in a negative-positive range. That means EXP is either negative, or greater than max. Since negative sizes are invalid make the range [MAX + 1, TYPE_MAX]. */ min = max + 1; max = wmaxval; } this has to use wi::lts_p (or les_p (min, 0). Suggested cleanup (untested): Index: gcc/calls.c =================================================================== --- gcc/calls.c (revision 251217) +++ gcc/calls.c (working copy) @@ -1279,8 +1279,9 @@ get_size_range (tree exp, tree range[2]) } wide_int min, max; + tree exptype = TREE_TYPE (exp); enum value_range_type range_type - = ((TREE_CODE (exp) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (exp))) + = ((TREE_CODE (exp) == SSA_NAME && INTEGRAL_TYPE_P (exptype)) ? get_range_info (exp, &min, &max) : VR_VARYING); if (range_type == VR_VARYING) @@ -1291,49 +1292,40 @@ get_size_range (tree exp, tree range[2]) return false; } - tree exptype = TREE_TYPE (exp); - unsigned expprec = TYPE_PRECISION (exptype); - wide_int wzero = wi::zero (expprec); - wide_int wmaxval = wide_int (TYPE_MAX_VALUE (exptype)); - - bool signed_p = !TYPE_UNSIGNED (exptype); + /* If we have an unsigned anti-range convert it to the respective + signed type. */ + if (range_type == VR_ANTI_RANGE + && TYPE_UNSIGNED (exptype) + && wi::les_p (max, min)) + { + std::swap (max, min); + min = min + 1; + max = max - 1; + range_type = VR_RANGE; + } if (range_type == VR_ANTI_RANGE) { - if (signed_p) + unsigned expprec = TYPE_PRECISION (exptype); + wide_int wzero = wi::zero (expprec); + wide_int wmaxval = wi::max_value (expprec, TYPE_SIGN (exptype)); + + if (wi::lts_p (max, wzero)) { - if (wi::les_p (max, wzero)) - { - /* EXP is not in a strictly negative range. That means - it must be in some (not necessarily strictly) positive - range which includes zero. Since in signed to unsigned - conversions negative values end up converted to large - positive values, and otherwise they are not valid sizes, - the resulting range is in both cases [0, TYPE_MAX]. */ - min = wzero; - max = wmaxval; - } - else if (wi::les_p (min - 1, wzero)) - { - /* EXP is not in a negative-positive range. That means EXP - is either negative, or greater than max. Since negative - sizes are invalid make the range [MAX + 1, TYPE_MAX]. */ - min = max + 1; - max = wmaxval; - } - else - { - max = min - 1; - min = wzero; - } + /* EXP is not in a strictly negative range. That means + it must be in some (not necessarily strictly) positive + range which includes zero. Since in signed to unsigned + conversions negative values end up converted to large + positive values, and otherwise they are not valid sizes, + the resulting range is in both cases [0, TYPE_MAX]. */ + min = wzero; + max = wmaxval; } - else if (wi::eq_p (wzero, min - 1)) + else if (wi::les_p (min, wzero)) { - /* EXP is unsigned and not in the range [1, MAX]. That means - it's either zero or greater than MAX. Even though 0 would - normally be detected by -Walloc-zero set the range to - [MAX, TYPE_MAX] so that when MAX is greater than the limit - the whole range is diagnosed. */ + /* EXP is not in a negative-positive range. That means EXP + is either negative, or greater than max. Since negative + sizes are invalid make the range [MAX + 1, TYPE_MAX]. */ min = max + 1; max = wmaxval; }