const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
{
+ gcc_checking_assert (value_range::supports_type_p (type));
r = value_range (type);
}
// The default for fold is to break all ranges into sub-ranges and
// invoke the wi_fold method on each sub-range pair.
-void
+bool
range_operator::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
+ gcc_checking_assert (value_range::supports_type_p (type));
if (empty_range_check (r, lh, rh))
- return;
+ return true;
value_range tmp;
r.set_undefined ();
wi_fold (tmp, type, lh_lb, lh_ub, rh_lb, rh_ub);
r.union_ (tmp);
if (r.varying_p ())
- return;
+ return true;
}
+ return true;
}
// The default for op1_range is to return false.
class operator_equal : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &val) const;
} op_equal;
-void
+bool
operator_equal::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
- return;
+ return true;
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
else
r = range_true_and_false (type);
}
+ return true;
}
bool
class operator_not_equal : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op1) const;
} op_not_equal;
-void
+bool
operator_not_equal::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
- return;
+ return true;
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
else
r = range_true_and_false (type);
}
+ return true;
}
bool
class operator_lt : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op1) const;
} op_lt;
-void
+bool
operator_lt::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
- return;
+ return true;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
r = range_false (type);
else
r = range_true_and_false (type);
+ return true;
}
bool
class operator_le : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op1) const;
} op_le;
-void
+bool
operator_le::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
- return;
+ return true;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
r = range_false (type);
else
r = range_true_and_false (type);
+ return true;
}
bool
class operator_gt : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op1) const;
} op_gt;
-void
+bool
operator_gt::fold_range (value_range &r, tree type,
const value_range &op1, const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
- return;
+ return true;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
r = range_false (type);
else
r = range_true_and_false (type);
+ return true;
}
bool
class operator_ge : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op1) const;
} op_ge;
-void
+bool
operator_ge::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
- return;
+ return true;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
r = range_false (type);
else
r = range_true_and_false (type);
+ return true;
}
bool
const value_range &lhs,
const value_range &op2) const
{
- range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
- return true;
+ return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
}
bool
const value_range &lhs,
const value_range &op1) const
{
- range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
- return true;
+ return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
}
const value_range &lhs,
const value_range &op2) const
{
- range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
- return true;
+ return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
}
bool
const value_range &lhs,
const value_range &op1) const
{
- fold_range (r, type, op1, lhs);
- return true;
+ return fold_range (r, type, op1, lhs);
}
// If op2 is a multiple of 2, we would be able to set some non-zero bits.
if (op2.singleton_p (&offset)
&& !integer_zerop (offset))
- {
- range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2);
- return true;
- }
+ return range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2);
return false;
}
class operator_lshift : public cross_product_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
const wide_int &) const;
} op_lshift;
-void
+bool
operator_lshift::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (undefined_shift_range_check (r, type, op2))
- return;
+ return true;
// Transform left shifts by constants into multiplies.
if (op2.singleton_p ())
bool saved_flag_wrapv_pointer = flag_wrapv_pointer;
flag_wrapv = 1;
flag_wrapv_pointer = 1;
- range_op_handler (MULT_EXPR, type)->fold_range (r, type, op1, mult);
+ bool b = range_op_handler (MULT_EXPR, type)->fold_range (r, type, op1,
+ mult);
flag_wrapv = saved_flag_wrapv;
flag_wrapv_pointer = saved_flag_wrapv_pointer;
- return;
+ return b;
}
-
- // Otherwise, invoke the generic fold routine.
- range_operator::fold_range (r, type, op1, op2);
+ else
+ // Otherwise, invoke the generic fold routine.
+ return range_operator::fold_range (r, type, op1, op2);
}
void
class operator_rshift : public cross_product_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual void wi_fold (value_range &r, tree type,
return false;
}
-void
+bool
operator_rshift::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
+ // Invoke the generic fold routine if not undefined..
if (undefined_shift_range_check (r, type, op2))
- return;
+ return true;
- // Otherwise, invoke the generic fold routine.
- range_operator::fold_range (r, type, op1, op2);
+ return range_operator::fold_range (r, type, op1, op2);
}
void
class operator_cast: public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
} op_convert;
-void
+bool
operator_cast::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
tree inner = lh.type ();
tree outer = rh.type ();
}
}
r = value_range (type);
- return;
+ break;
}
+ return true;
}
bool
class operator_logical_and : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
} op_logical_and;
-void
+bool
operator_logical_and::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
// 0 && anything is 0.
if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0))
r = range_true_and_false (type);
else
r = range_true (type);
+ return true;
}
bool
class operator_logical_or : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op1) const;
} op_logical_or;
-void
+bool
operator_logical_or::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
r = lh;
r.union_ (rh);
+ return true;
}
bool
class operator_logical_not : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
// b_2 = x_1 < 20 [0,0] = x_1 < 20, false, so x_1 == [20, 255]
// which is the result we are looking for.. so.. pass it through.
-void
+bool
operator_logical_not::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
if (lh.varying_p () || lh.undefined_p ())
r = lh;
r.invert ();
}
gcc_checking_assert (lh.type() == type);
- return;
+ return true;
}
bool
class operator_bitwise_not : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op2) const;
} op_bitwise_not;
-void
+bool
operator_bitwise_not::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
// ~X is simply -1 - X.
value_range minusone (type, wi::minus_one (TYPE_PRECISION (type)),
wi::minus_one (TYPE_PRECISION (type)));
- range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, lh);
- return;
+ return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone,
+ lh);
}
bool
const value_range &op2) const
{
// ~X is -1 - X and since bitwise NOT is involutary...do it again.
- fold_range (r, type, lhs, op2);
- return true;
+ return fold_range (r, type, lhs, op2);
}
class operator_cst : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
} op_integer_cst;
-void
+bool
operator_cst::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
r = lh;
+ return true;
}
class operator_identity : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op2) const;
} op_identity;
-void
+bool
operator_identity::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
r = lh;
+ return true;
}
bool
class operator_negate : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op2) const;
} op_negate;
-void
+bool
operator_negate::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
// -X is simply 0 - X.
- range_op_handler (MINUS_EXPR, type)->fold_range (r, type,
- range_zero (type), lh);
+ return range_op_handler (MINUS_EXPR, type)->fold_range (r, type,
+ range_zero (type),
+ lh);
}
bool
const value_range &op2) const
{
// NEGATE is involutory.
- fold_range (r, type, lhs, op2);
- return true;
+ return fold_range (r, type, lhs, op2);
}
class operator_addr_expr : public range_operator
{
public:
- virtual void fold_range (value_range &r, tree type,
+ virtual bool fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &op2) const;
} op_addr;
-void
+bool
operator_addr_expr::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
- return;
+ return true;
// Return a non-null pointer of the LHS type (passed in op2).
if (lh.zero_p ())
r = range_nonzero (type);
else
r = value_range (type);
+ return true;
}
bool
const value_range &lhs,
const value_range &op2) const
{
- operator_addr_expr::fold_range (r, type, lhs, op2);
- return true;
+ return operator_addr_expr::fold_range (r, type, lhs, op2);
}
{
value_range tmp = r;
range_operator *op = range_op_handler (CONVERT_EXPR, type);
- op->fold_range (r, type, tmp, value_range (type));
+ // Call op_convert, if it fails, the result is varying.
+ if (!op->fold_range (r, type, tmp, value_range (type)))
+ r = value_range (type);
}
#if CHECKING_P