There is a bug in irange::set_range_from_bitmask where if the bitmask
indicated the result is a singleton, it would simply return that
singleton. It never actually checked to see if that singleton was
actually contained in the range, in which case it should return UNDEFINED.
I haven't been able to reproduce this in the wild, but my upcoming
switch changes triggered this problem. As a result, im not sure this
need to be backported... but I leave that to the maintainers. It
should be harmless to backport to gcc15 and/or gcc 14. the situation was
a = a & 0xF0
switch (a)
{
case 24 ... 28:
}
was being rewritten by the new code to
case 16:
which is blatantly wrong. With the proper UNDEFINED result, the case
will be eliminated. Again, this situation is does not exist prior to
the next set of patches.
Bootstrapped on 86_64-pc-linux-gnu with no regressions. Pushed
Andrew
From ea2cfcbf652c9531aae2af6352c9519d36795cf1 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Tue, 10 Jun 2025 12:11:18 -0400
Subject: [PATCH] Check if constant is a member before returning it.
set_range_from_bitmask checks the new bitmask, and if it is a constant,
simply returns the constant. It never checks if that constant is
actually within the range. If it is not, the result should be UNDEFINED.
* value-range.cc (irange::set_range_from_bitmask): When the bitmask
result is a singleton, check if it is contained in the range.
---
gcc/value-range.cc | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index ed3760fa6ff..e2d75f59c2e 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2268,7 +2268,11 @@ irange::set_range_from_bitmask ()
// If all the bits are known, this is a singleton.
if (m_bitmask.mask () == 0)
{
- set (m_type, m_bitmask.value (), m_bitmask.value ());
+ // Make sure the singleton is within the range.
+ if (contains_p (m_bitmask.value ()))
+ set (m_type, m_bitmask.value (), m_bitmask.value ());
+ else
+ set_undefined ();
return true;
}
--
2.45.0