+/* Return whether BASE + OFFSET + BITPOS may wrap around the address
+ space. This is used to avoid issuing overflow warnings for
+ expressions like &p->x which can not wrap. */
+
+static bool
+pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
+{
+ tree size;
+ unsigned HOST_WIDE_INT offset_low, total_low;
+ HOST_WIDE_INT offset_high, total_high;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (base)))
+ return true;
+
+ if (bitpos < 0)
+ return true;
+
+ size = size_in_bytes (TREE_TYPE (TREE_TYPE (base)));
+ if (size == NULL_TREE || TREE_CODE (size) != INTEGER_CST)
+ return true;
+
+ /* We can do slightly better for SIZE if we have an ADDR_EXPR of an
+ array. */
+ if (TREE_CODE (base) == ADDR_EXPR)
+ {
+ tree base_size = size_in_bytes (TREE_TYPE (TREE_OPERAND (base, 0)));
+ if (base_size != NULL_TREE
+ && TREE_CODE (base_size) == INTEGER_CST
+ && INT_CST_LT_UNSIGNED (size, base_size))
+ size = base_size;
+ }
+
+ if (offset == NULL_TREE)
+ {
+ offset_low = 0;
+ offset_high = 0;
+ }
+ else if (TREE_CODE (offset) != INTEGER_CST || TREE_OVERFLOW (offset))
+ return true;
+ else
+ {
+ offset_low = TREE_INT_CST_LOW (offset);
+ offset_high = TREE_INT_CST_HIGH (offset);
+ }
+
+ if (add_double_with_sign (offset_low, offset_high,
+ bitpos / BITS_PER_UNIT, 0,
+ &total_low, &total_high,
+ true))
+ return true;
+
+ if ((unsigned HOST_WIDE_INT) total_high
+ < (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (size))
+ return false;
+ if ((unsigned HOST_WIDE_INT) total_high
+ > (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (size))
+ return true;
+ return total_low > TREE_INT_CST_LOW (size);
+}
+