diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2023-11-28 09:39:30 -0500 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2023-11-29 11:43:53 -0500 |
commit | ea19de921b01a6ab470929f8da4dde526edb08f1 (patch) | |
tree | 5088e0a596202dc03e252f4956c009488989a119 /gcc | |
parent | 302461ad9a04d82fee904bddac69811d13d5bb6a (diff) | |
download | gcc-ea19de921b01a6ab470929f8da4dde526edb08f1.zip gcc-ea19de921b01a6ab470929f8da4dde526edb08f1.tar.gz gcc-ea19de921b01a6ab470929f8da4dde526edb08f1.tar.bz2 |
Add operand_check_p to range-ops.
Add an optional method to verify operands are compatible, and check
the operands before all range operations.
* range-op-mixed.h (operator_equal::operand_check_p): New.
(operator_not_equal::operand_check_p): New.
(operator_lt::operand_check_p): New.
(operator_le::operand_check_p): New.
(operator_gt::operand_check_p): New.
(operator_ge::operand_check_p): New.
(operator_plus::operand_check_p): New.
(operator_abs::operand_check_p): New.
(operator_minus::operand_check_p): New.
(operator_negate::operand_check_p): New.
(operator_mult::operand_check_p): New.
(operator_bitwise_not::operand_check_p): New.
(operator_bitwise_xor::operand_check_p): New.
(operator_bitwise_and::operand_check_p): New.
(operator_bitwise_or::operand_check_p): New.
(operator_min::operand_check_p): New.
(operator_max::operand_check_p): New.
* range-op.cc (range_op_handler::fold_range): Check operand
parameter types.
(range_op_handler::op1_range): Ditto.
(range_op_handler::op2_range): Ditto.
(range_op_handler::operand_check_p): New.
(range_operator::operand_check_p): New.
(operator_lshift::operand_check_p): New.
(operator_rshift::operand_check_p): New.
(operator_logical_and::operand_check_p): New.
(operator_logical_or::operand_check_p): New.
(operator_logical_not::operand_check_p): New.
* range-op.h (range_operator::operand_check_p): New.
(range_op_handler::operand_check_p): New.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/range-op-mixed.h | 63 | ||||
-rw-r--r-- | gcc/range-op.cc | 53 | ||||
-rw-r--r-- | gcc/range-op.h | 5 |
3 files changed, 114 insertions, 7 deletions
diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h index 45e11df..4386a68 100644 --- a/gcc/range-op-mixed.h +++ b/gcc/range-op-mixed.h @@ -138,6 +138,9 @@ public: 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 @@ -174,6 +177,9 @@ public: 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 @@ -207,6 +213,9 @@ public: 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 @@ -243,6 +252,9 @@ public: 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 @@ -278,6 +290,9 @@ public: 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 @@ -314,6 +329,9 @@ public: 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 @@ -409,7 +427,10 @@ public: 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, @@ -436,6 +457,9 @@ class operator_abs : 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 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, @@ -477,7 +501,10 @@ public: 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, @@ -506,6 +533,9 @@ class operator_negate : public range_operator 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); } }; @@ -557,7 +587,10 @@ public: 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 @@ -586,6 +619,10 @@ public: 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 @@ -606,6 +643,10 @@ public: 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, @@ -629,6 +670,10 @@ public: 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, @@ -651,6 +696,10 @@ public: 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, @@ -662,6 +711,10 @@ class operator_min : public range_operator 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, @@ -673,6 +726,10 @@ class operator_max : public range_operator 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, diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 6137f2a..a091815 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -201,6 +201,10 @@ range_op_handler::fold_range (vrange &r, tree type, 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: @@ -237,9 +241,12 @@ range_op_handler::op1_range (vrange &r, tree type, 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: @@ -270,7 +277,10 @@ range_op_handler::op2_range (vrange &r, tree type, 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: @@ -394,6 +404,13 @@ range_op_handler::overflow_free_p (const vrange &lh, } } +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. @@ -737,6 +754,14 @@ range_operator::update_bitmask (irange &, const irange &, { } +// 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). @@ -2466,6 +2491,9 @@ public: 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 @@ -2495,6 +2523,9 @@ public: 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; @@ -3070,9 +3101,12 @@ public: 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, @@ -3082,6 +3116,11 @@ operator_logical_and::fold_range (irange &r, tree type, 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))) @@ -3567,6 +3606,10 @@ public: 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 @@ -3993,6 +4036,9 @@ public: 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 @@ -4036,7 +4082,6 @@ operator_logical_not::op1_range (irange &r, return fold_range (r, type, lhs, op2); } - bool operator_bitwise_not::fold_range (irange &r, tree type, const irange &lh, diff --git a/gcc/range-op.h b/gcc/range-op.h index 282ce38..ab8f8a3 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -157,6 +157,10 @@ public: virtual bool overflow_free_p (const irange &lh, const irange &rh, relation_trio = TRIO_VARYING) const; + + // Compatability check for operands. + virtual bool operand_check_p (tree, tree, tree) const; + protected: // Perform an integral operation between 2 sub-ranges and return it. virtual void wi_fold (irange &r, tree type, @@ -226,6 +230,7 @@ public: const vrange &op2) const; bool overflow_free_p (const vrange &lh, const vrange &rh, relation_trio = TRIO_VARYING) const; + bool operand_check_p (tree, tree, tree) const; protected: unsigned dispatch_kind (const vrange &lhs, const vrange &op1, const vrange& op2) const; |