On 3/6/20 8:12 PM, Marek Polacek wrote:
On Fri, Mar 06, 2020 at 05:49:07PM -0500, Jason Merrill wrote:
On 3/5/20 2:40 PM, Marek Polacek wrote:
The static_assert in the following test was failing on armv7hl because
we were disregarding the alignas specifier on Cell.  BaseShape's data
takes up 20B on 32-bit architectures, but we failed to round up its
TYPE_SIZE.  This happens since the
<https://gcc.gnu.org/ml/gcc-patches/2019-06/msg01189.html>
patch: here, in layout_class_type for TenuredCell, we see that the size
of TenuredCell and its CLASSTYPE_AS_BASE match, so we set

    CLASSTYPE_AS_BASE (t) = t;

But while TYPE_USER_ALIGN of TenuredCell was 0, TYPE_USER_ALIGN of its
CLASSTYPE_AS_BASE was 1.

Surely the bug is that TYPE_USER_ALIGN isn't set for TenuredCell?

That's my understanding.

So why is that? Where is setting TYPE_USER_ALIGN on as-base TenuredCell, and why isn't it setting it on the main type as well? Or is it getting cleared on the main type for some reason?

I think it's clear that we're losing the alignas
specifier and so the TYPE_SIZE of BaseShape is wrong.  Before the patch from
June patch we'd set it...

   After we replace it, it's no longer 1.  Then
we perform layout_empty_base_or_field for TenuredCell and since
TYPE_USER_ALIGN of its CLASSTYPE_AS_BASE is now 0, we don't do this
adjustment:

    if (CLASSTYPE_USER_ALIGN (type))
      {
        rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (type));
        if (warn_packed)
          rli->unpacked_align = MAX (rli->unpacked_align, CLASSTYPE_ALIGN 
(type));
        TYPE_USER_ALIGN (rli->t) = 1;
      }

I would expect it to be set here on TenuredCell prime, and then copied to the as-base type with

      TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);

...here, but we no longer do.  Is there any other direction I could pursue?
Well, perhaps...

--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6705,6 +6705,10 @@ layout_class_type (tree t, tree *virtuals_p)
     /* If we didn't end up needing an as-base type, don't use it.  */
     if (CLASSTYPE_AS_BASE (t) != t
+      /* If T's CLASSTYPE_AS_BASE is TYPE_USER_ALIGN, but T is not,
+        replacing the as-base type would change CLASSTYPE_USER_ALIGN,
+        causing us to lose the user-specified alignment as in PR94050.  */
+      && !CLASSTYPE_USER_ALIGN (t)
         && tree_int_cst_equal (TYPE_SIZE (t),
                             TYPE_SIZE (CLASSTYPE_AS_BASE (t))))
       CLASSTYPE_AS_BASE (t) = t;

...we could copy the TYPE_USER_ALIGN flag to t if its old CLASSTYPE_AS_BASE
had it.  But my fix seems to be safer.

The flag should be set properly regardless of whether we do this optimization.

Jason

Reply via email to