const frange &) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check op1 and op2 for compatibility.
+ bool operand_check_p (tree, tree t1, tree t2) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
class operator_not_equal : public range_operator
const frange &) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check op1 and op2 for compatibility.
+ bool operand_check_p (tree, tree t1, tree t2) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
class operator_lt : public range_operator
const frange &) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check op1 and op2 for compatibility.
+ bool operand_check_p (tree, tree t1, tree t2) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
class operator_le : public range_operator
const frange &) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check op1 and op2 for compatibility.
+ bool operand_check_p (tree, tree t1, tree t2) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
class operator_gt : public range_operator
const frange &) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check op1 and op2 for compatibility.
+ bool operand_check_p (tree, tree t1, tree t2) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
class operator_ge : public range_operator
const frange &) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check op1 and op2 for compatibility.
+ bool operand_check_p (tree, tree t1, tree t2) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
class operator_identity : public range_operator
virtual bool overflow_free_p (const irange &lh, const irange &rh,
relation_trio = TRIO_VARYING) const;
-
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
private:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
relation_trio rel = TRIO_VARYING) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check compatibility of LHS and op1.
+ bool operand_check_p (tree t1, tree t2, tree) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
private:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
virtual bool overflow_free_p (const irange &lh, const irange &rh,
relation_trio = TRIO_VARYING) const;
-
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
private:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
bool op1_range (frange &r, tree type,
const frange &lhs, const frange &op2,
relation_trio rel = TRIO_VARYING) const final override;
+ // Check compatibility of LHS and op1.
+ bool operand_check_p (tree t1, tree t2, tree) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
};
relation_kind kind) const final override;
virtual bool overflow_free_p (const irange &lh, const irange &rh,
relation_trio = TRIO_VARYING) const;
-
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
};
class operator_addr_expr : public range_operator
relation_trio rel = TRIO_VARYING) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
};
class operator_bitwise_xor : public range_operator
relation_kind rel) const final override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
private:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
relation_kind) const override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const override;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
protected:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
relation_trio rel = TRIO_VARYING) const override;
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const override;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
protected:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
public:
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const override;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
protected:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
public:
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const override;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
protected:
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
const wide_int &lh_ub, const wide_int &rh_lb,
relation_trio rel) const
{
gcc_checking_assert (m_operator);
+#if CHECKING_P
+ if (!lh.undefined_p () && !rh.undefined_p ())
+ gcc_assert (m_operator->operand_check_p (type, lh.type (), rh.type ()));
+#endif
switch (dispatch_kind (r, lh, rh))
{
case RO_III:
relation_trio rel) const
{
gcc_checking_assert (m_operator);
-
if (lhs.undefined_p ())
return false;
+#if CHECKING_P
+ if (!op2.undefined_p ())
+ gcc_assert (m_operator->operand_check_p (lhs.type (), type, op2.type ()));
+#endif
switch (dispatch_kind (r, lhs, op2))
{
case RO_III:
gcc_checking_assert (m_operator);
if (lhs.undefined_p ())
return false;
-
+#if CHECKING_P
+ if (!op1.undefined_p ())
+ gcc_assert (m_operator->operand_check_p (lhs.type (), op1.type (), type));
+#endif
switch (dispatch_kind (r, lhs, op1))
{
case RO_III:
}
}
+bool
+range_op_handler::operand_check_p (tree t1, tree t2, tree t3) const
+{
+ gcc_checking_assert (m_operator);
+ return m_operator->operand_check_p (t1, t2, t3);
+}
+
// Update the known bitmasks in R when applying the operation CODE to
// LH and RH.
{
}
+// Check that operand types are OK. Default to always OK.
+
+bool
+range_operator::operand_check_p (tree, tree, tree) const
+{
+ return true;
+}
+
// Create and return a range from a pair of wide-ints that are known
// to have overflowed (or underflowed).
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override
{ update_known_bitmask (r, LSHIFT_EXPR, lh, rh); }
+ // Check compatibility of LHS and op1.
+ bool operand_check_p (tree t1, tree t2, tree) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
} op_lshift;
class operator_rshift : public cross_product_operator
void update_bitmask (irange &r, const irange &lh,
const irange &rh) const final override
{ update_known_bitmask (r, RSHIFT_EXPR, lh, rh); }
+ // Check compatibility of LHS and op1.
+ bool operand_check_p (tree t1, tree t2, tree) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
} op_rshift;
const irange &lhs,
const irange &op1,
relation_trio rel = TRIO_VARYING) const;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
} op_logical_and;
-
bool
operator_logical_and::fold_range (irange &r, tree type,
const irange &lh,
if (empty_range_varying (r, type, lh, rh))
return true;
+ // Precision of LHS and both operands must match.
+ if (TYPE_PRECISION (lh.type ()) != TYPE_PRECISION (type)
+ || TYPE_PRECISION (type) != TYPE_PRECISION (rh.type ()))
+ return false;
+
// 0 && anything is 0.
if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0))
|| (wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (rh.upper_bound (), 0)))
const irange &lhs,
const irange &op1,
relation_trio rel = TRIO_VARYING) const;
+ // Check compatibility of all operands.
+ bool operand_check_p (tree t1, tree t2, tree t3) const final override
+ { return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t3)); }
} op_logical_or;
bool
const irange &lhs,
const irange &op2,
relation_trio rel = TRIO_VARYING) const;
+ // Check compatibility of LHS and op1.
+ bool operand_check_p (tree t1, tree t2, tree) const final override
+ { return TYPE_PRECISION (t1) == TYPE_PRECISION (t2); }
} op_logical_not;
// Folding a logical NOT, oddly enough, involves doing nothing on the
return fold_range (r, type, lhs, op2);
}
-
bool
operator_bitwise_not::fold_range (irange &r, tree type,
const irange &lh,