#include "tree-pass.h"
#include "langhooks.h"
#include "flags.h"
+#include "diagnostic.h"
#include "expr.h"
#include "cfgloop.h"
#include "optabs.h"
{
/* And finally (T)(P + A) - (T)P. */
tree a = gimple_assign_rhs2 (def_stmt2);
- /* For pointer types, if the conversion of A to the final
- type requires a sign- or zero-extension, then we have
- to punt - it is not defined which one is correct. */
- if (!POINTER_TYPE_P (TREE_TYPE (rhs1))
- || TYPE_PRECISION (TREE_TYPE (rhs1))
- <= TYPE_PRECISION (TREE_TYPE (a))
- || (TREE_CODE (a) == INTEGER_CST
+ if (TYPE_PRECISION (TREE_TYPE (rhs1))
+ <= TYPE_PRECISION (TREE_TYPE (a))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (p))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (p)))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (p))
+ && TREE_CODE (a) == INTEGER_CST
&& tree_int_cst_sign_bit (a) == 0))
{
+ if (issue_strict_overflow_warning
+ (WARN_STRICT_OVERFLOW_MISC)
+ && TYPE_PRECISION (TREE_TYPE (rhs1))
+ > TYPE_PRECISION (TREE_TYPE (a))
+ && INTEGRAL_TYPE_P (TREE_TYPE (p)))
+ warning_at (gimple_location (stmt),
+ OPT_Wstrict_overflow,
+ "assuming signed overflow does not "
+ "occur when assuming that "
+ "(T)(P + A) - (T)P is always (T)A");
if (useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (a)))
code = TREE_CODE (a);