https://gcc.gnu.org/g:71225cd5c97aa0474b2fbf5b9196c416f2489257
commit 71225cd5c97aa0474b2fbf5b9196c416f2489257 Author: Mikael Morin <[email protected]> Date: Fri Sep 4 13:57:17 2026 +0200 range-op: Check for undefined before accessing range type [PR126532] I hesitated on what the operator reverse range function should do when an operand is undefined: either return false without setting any range or set varying (well, true and false actually) and return true. I have finally chosen varying/true, which matches what is done when the left hand side is undefined. TODO: OK for mainline? -- >8 -- In the reverse range evaluation of the logical and operator, add a check that the range is non-undefined before accessing its type. If the range is undefined, fall back to the default case and return a true and false range. PR tree-optimization/126532 gcc/ChangeLog: * range-op.cc (operator_logical_and::op1_range): Check the range is non-undefined before accessing its type. gcc/testsuite/ChangeLog: * gcc.dg/pr126532.c: New test. Diff: --- gcc/range-op.cc | 3 ++- gcc/testsuite/gcc.dg/pr126532.c | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 350548951f45..ca066c05e381 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -3487,7 +3487,8 @@ operator_logical_and::op1_range (irange &r, tree type, case BRS_FALSE: // A FALSE result when op2 is TRUE, must have op1 FALSE. - if (!op2.contains_p (wi::zero (TYPE_PRECISION (op2.type ())))) + if (!op2.undefined_p () + && !op2.contains_p (wi::zero (TYPE_PRECISION (op2.type ())))) { r = range_false (type); return true; diff --git a/gcc/testsuite/gcc.dg/pr126532.c b/gcc/testsuite/gcc.dg/pr126532.c new file mode 100644 index 000000000000..22fbba0ecebf --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr126532.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -O2 -fno-tree-vrp -fno-tree-dominator-opts" } */ + +/* PR tree-optimization/126532 + The following code used to cause an ICE as the logical and reverse operator + range calculation was accessing a range's type without checking it was + non-undefined. */ + +int f_b, f_r; + +__attribute__((noipa)) void +f (int a) +{ + _Bool t1 = f_b; + if (t1) + { + _Bool t3 = a && t1; + _Bool t39 = t3 ^ t1; + if (t3) + ; + else if (!a) + ; + else + f_r += 7; + if (t39) + f_r += 3; + } +} + +int +main (void) +{ + for (int b = 0; b < 2; b++) + for (int a = -1; a < 2; a++) + { + int e = 0; + f_b = b; + f_r = 0; + f (a); + if (b) + { + int t3 = (a != 0); + int t39 = t3 ^ 1; + if (!t3 && a) + e += 7; + if (t39) + e += 3; + } + if (f_r != e) + __builtin_abort (); + } + return 0; +}
