dump_bound_with_infinite_markers (FILE *file, tree bound)
{
tree type = TREE_TYPE (bound);
+ wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+
if (INTEGRAL_TYPE_P (type)
&& !TYPE_UNSIGNED (type)
- && vrp_val_is_min (bound)
+ && TREE_CODE (bound) == INTEGER_CST
+ && wi::to_wide (bound) == type_min
&& TYPE_PRECISION (type) != 1)
fprintf (file, "-INF");
- else if (vrp_val_is_max (bound)
+ else if (TREE_CODE (bound) == INTEGER_CST
+ && wi::to_wide (bound) == type_max
&& TYPE_PRECISION (type) != 1)
fprintf (file, "+INF");
else
}
}
+// Simulate -fstrict-enums where the domain of a type is less than the
+// underlying type.
+
+static void
+range_tests_strict_enum ()
+{
+ // The enum can only hold [0, 3].
+ tree rtype = copy_node (unsigned_type_node);
+ TYPE_MIN_VALUE (rtype) = build_int_cstu (rtype, 0);
+ TYPE_MAX_VALUE (rtype) = build_int_cstu (rtype, 3);
+
+ // Test that even though vr1 covers the strict enum domain ([0, 3]),
+ // it does not cover the domain of the underlying type.
+ int_range<1> vr1 (build_int_cstu (rtype, 0), build_int_cstu (rtype, 1));
+ int_range<1> vr2 (build_int_cstu (rtype, 2), build_int_cstu (rtype, 3));
+ vr1.union_ (vr2);
+ ASSERT_TRUE (vr1 == int_range<1> (build_int_cstu (rtype, 0),
+ build_int_cstu (rtype, 3)));
+ ASSERT_FALSE (vr1.varying_p ());
+
+ // Test that copying to a multi-range does not change things.
+ int_range<2> ir1 (vr1);
+ ASSERT_TRUE (ir1 == vr1);
+ ASSERT_FALSE (ir1.varying_p ());
+
+ // The same test as above, but using TYPE_{MIN,MAX}_VALUE instead of [0,3].
+ vr1 = int_range<1> (TYPE_MIN_VALUE (rtype), TYPE_MAX_VALUE (rtype));
+ ir1 = vr1;
+ ASSERT_TRUE (ir1 == vr1);
+ ASSERT_FALSE (ir1.varying_p ());
+}
+
static void
range_tests_misc ()
{
range_tests_legacy ();
range_tests_irange3 ();
range_tests_int_range_max ();
+ range_tests_strict_enum ();
range_tests_misc ();
}
tree l = m_base[0];
tree u = m_base[1];
tree t = TREE_TYPE (l);
+ unsigned prec = TYPE_PRECISION (t);
+ signop sign = TYPE_SIGN (t);
if (INTEGRAL_TYPE_P (t))
- return l == TYPE_MIN_VALUE (t) && u == TYPE_MAX_VALUE (t);
+ return (wi::to_wide (l) == wi::min_value (prec, sign)
+ && wi::to_wide (u) == wi::max_value (prec, sign));
if (POINTER_TYPE_P (t))
- return wi::to_wide (l) == 0
- && wi::to_wide (u) == wi::max_value (TYPE_PRECISION (t),
- TYPE_SIGN (t));
+ return (wi::to_wide (l) == 0
+ && wi::to_wide (u) == wi::max_value (prec, sign));
return true;
}
m_num_ranges = 1;
if (INTEGRAL_TYPE_P (type))
{
- m_base[0] = TYPE_MIN_VALUE (type);
- m_base[1] = TYPE_MAX_VALUE (type);
+ wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ m_base[0] = wide_int_to_tree (type, min);
+ m_base[1] = wide_int_to_tree (type, max);
}
else if (POINTER_TYPE_P (type))
{
}
// Normalize a range to VARYING or UNDEFINED if possible.
-//
-// Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can
-// restrict those to a subset of what actually fits in the type.
-// Instead use the extremes of the type precision which will allow
-// compare_range_with_value() to check if a value is inside a range,
-// whereas if we used TYPE_*_VAL, said function would just punt upon
-// seeing a VARYING.
inline void
irange::normalize_min_max ()