new_size = DECL_SIZE_UNIT (t);
}
- /* ??? If we end up with a constant here do record a MEM_EXPR. */
- else if (CONSTANT_CLASS_P (t))
+ /* ??? If we end up with a constant or a descriptor do not
+ record a MEM_EXPR. */
+ else if (CONSTANT_CLASS_P (t)
+ || TREE_CODE (t) == CONSTRUCTOR)
;
/* If this is a field reference, record it. */
new_size = DECL_SIZE_UNIT (TREE_OPERAND (t, 1));
}
- /* If this is an array reference, look for an outer field reference. */
- else if (TREE_CODE (t) == ARRAY_REF)
- {
- tree off_tree = size_zero_node;
- /* We can't modify t, because we use it at the end of the
- function. */
- tree t2 = t;
-
- do
- {
- tree index = TREE_OPERAND (t2, 1);
- tree low_bound = array_ref_low_bound (t2);
- tree unit_size = array_ref_element_size (t2);
-
- /* We assume all arrays have sizes that are a multiple of a byte.
- First subtract the lower bound, if any, in the type of the
- index, then convert to sizetype and multiply by the size of
- the array element. */
- if (! integer_zerop (low_bound))
- index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
- index, low_bound);
-
- off_tree = size_binop (PLUS_EXPR,
- size_binop (MULT_EXPR,
- fold_convert (sizetype,
- index),
- unit_size),
- off_tree);
- t2 = TREE_OPERAND (t2, 0);
- }
- while (TREE_CODE (t2) == ARRAY_REF);
-
- if (DECL_P (t2)
- || (TREE_CODE (t2) == COMPONENT_REF
- /* For trailing arrays t2 doesn't have a size that
- covers all valid accesses. */
- && ! array_at_struct_end_p (t)))
- {
- attrs.expr = t2;
- attrs.offset_known_p = false;
- if (poly_int_tree_p (off_tree, &attrs.offset))
- {
- attrs.offset_known_p = true;
- apply_bitpos = bitpos;
- }
- }
- /* Else do not record a MEM_EXPR. */
- }
-
- /* If this is an indirect reference, record it. */
- else if (TREE_CODE (t) == MEM_REF
- || TREE_CODE (t) == TARGET_MEM_REF)
+ /* Else record it. */
+ else
{
+ gcc_assert (handled_component_p (t)
+ || TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == TARGET_MEM_REF);
attrs.expr = t;
attrs.offset_known_p = true;
attrs.offset = 0;
--- /dev/null
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+struct verify
+{
+ const bool m_failed = false;
+
+ [[gnu::noinline]] void print_hex(const void* x, int n) const
+ {
+ const auto* bytes = static_cast<const unsigned char*>(x);
+ for (int i = 0; i < n; ++i)
+ __builtin_printf((i && i % 4 == 0) ? "'%02x" : "%02x", bytes[i]);
+ __builtin_printf("\n");
+ }
+
+ template <typename... Ts>
+ verify(bool ok, const Ts&... extra_info) : m_failed(!ok)
+ {
+ if (m_failed)
+ (print_hex(&extra_info, sizeof(extra_info)), ...);
+ }
+
+ ~verify()
+ {
+ if (m_failed)
+ __builtin_abort();
+ }
+};
+
+using K [[gnu::vector_size(16)]] = int;
+
+int
+main()
+{
+ int count = 1;
+ asm("" : "+m"(count));
+ verify(count == 1, 0, "", 0);
+
+ {
+ struct SW
+ {
+ K d;
+ };
+ struct
+ {
+ SW d;
+ } xx;
+ SW& x = xx.d;
+ x = SW(); // [0, 0, 0, 0]
+ for (int i = 3; i >= 2; --i)
+ {
+ x.d[i] = -1; // [0, 0, 0, -1] ...
+ int a = [](K y) {
+ for (int j = 0; j < 4; ++j)
+ if (y[j] != 0)
+ return j;
+ return -1;
+ }(x.d);
+ verify(a == i, 0, 0, 0, 0, i, x);
+ }
+ }
+}