-
- if (off)
- mem = adjust_automodify_address_nv (mem, BLKmode, NULL, off);
-
- /* Allow the string and memory builtins to overflow from one
- field into another, see http://gcc.gnu.org/PR23561.
- Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
- memory accessed by the string or memory builtin will fit
- within the field. */
- if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
- {
- tree mem_expr = MEM_EXPR (mem);
- HOST_WIDE_INT offset = -1, length = -1;
- tree inner = exp;
-
- while (TREE_CODE (inner) == ARRAY_REF
- || CONVERT_EXPR_P (inner)
- || TREE_CODE (inner) == VIEW_CONVERT_EXPR
- || TREE_CODE (inner) == SAVE_EXPR)
- inner = TREE_OPERAND (inner, 0);
-
- gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
-
- if (MEM_OFFSET_KNOWN_P (mem))
- offset = MEM_OFFSET (mem);
-
- if (offset >= 0 && len && host_integerp (len, 0))
- length = tree_low_cst (len, 0);
-
- while (TREE_CODE (inner) == COMPONENT_REF)
- {
- tree field = TREE_OPERAND (inner, 1);
- gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
- gcc_assert (field == TREE_OPERAND (mem_expr, 1));
-
- /* Bitfields are generally not byte-addressable. */
- gcc_assert (!DECL_BIT_FIELD (field)
- || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
- % BITS_PER_UNIT) == 0
- && host_integerp (DECL_SIZE (field), 0)
- && (TREE_INT_CST_LOW (DECL_SIZE (field))
- % BITS_PER_UNIT) == 0));
-
- /* If we can prove that the memory starting at XEXP (mem, 0) and
- ending at XEXP (mem, 0) + LENGTH will fit into this field, we
- can keep the COMPONENT_REF in MEM_EXPR. But be careful with
- fields without DECL_SIZE_UNIT like flexible array members. */
- if (length >= 0
- && DECL_SIZE_UNIT (field)
- && host_integerp (DECL_SIZE_UNIT (field), 0))
- {
- HOST_WIDE_INT size
- = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
- if (offset <= size
- && length <= size
- && offset + length <= size)
- break;
- }
-
- if (offset >= 0
- && host_integerp (DECL_FIELD_OFFSET (field), 0))
- offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
- / BITS_PER_UNIT;
- else
- {
- offset = -1;
- length = -1;
- }
-
- mem_expr = TREE_OPERAND (mem_expr, 0);
- inner = TREE_OPERAND (inner, 0);
- }
-
- if (mem_expr == NULL)
- offset = -1;
- if (mem_expr != MEM_EXPR (mem))
- {
- set_mem_expr (mem, mem_expr);
- if (offset >= 0)
- set_mem_offset (mem, offset);
- else
- clear_mem_offset (mem);
- }
- }
- set_mem_alias_set (mem, 0);
- clear_mem_size (mem);