RFA (layout): PATCH for c++/48029 (ICE-on-valid with templates and arrays)

Richard Guenther richard.guenther@gmail.com
Thu Mar 10 09:56:00 GMT 2011


On Thu, Mar 10, 2011 at 3:59 AM, Jason Merrill <jason@redhat.com> wrote:
> In this testcase, when we first declare the myvectypes and mytype3,
> vector<string> has not been instantiated, so we mark the array, and the
> pointer to the array, for structural equality comparison.  When we actually
> go to instantiate mytype3, we complete vector<string> and rebuild the array
> and pointer types, and use those to look up the template specialization.
>  Which fails to find the one we already had because the new pointer type has
> TYPE_CANONICAL and therefore hashes
> differently from the one that didn't.
>
> We deal with ARRAY_TYPE specially in iterative_hash_template_arg, but that
> doesn't cover a compound type which uses an ARRAY_TYPE, such as the pointer
> in this case.
>
> The business of having an array with the same element type and domain have
> different TYPE_CANONICAL dependending on whether or not the element type is
> complete has always seemed strange and fragile to me, so I tried removing
> the relevant code from layout_type; this produced only a single test
> failure, which was fixed by changing type_hash_eq to not trust TYPE_ALIGN if
> the type isn't complete yet.  I imagine that's what Doug was talking about
> in his comment about alignment.

Ugh.  Why do we call layout_type on arrays with incomplete element type
at all?  I suppose the array type is still considered un-layouted after
that finished (NULL TYPE_SIZE)?  So, what does layout_type provide
that the C++ FE relies on when layouting this kind of type?

Other than the above questions the patch looks ok if indeed layout_type
returns with a NULL TYPE_SIZE.

Thanks,
Richard.

> Tested (c,c++,fortran,java,lto,objc) x86_64-pc-linux-gnu.  OK for 4.5 and
> 4.6?
>
> commit 45deb1cd5953c5730e14e00c5a8f800dadea66bd
> Author: Jason Merrill <jason@redhat.com>
> Date:   Wed Mar 9 16:47:10 2011 -0500
>
>        PR c++/48029
>        * stor-layout.c (layout_type): Don't set structural equality
>        on arrays of incomplete type.
>        * tree.c (type_hash_eq): Handle comparing them properly.
>        * cp/pt.c (iterative_hash_template_arg): Remove special case for
>        ARRAY_TYPE.
>
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index ac91698..ab2aea3 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -1569,13 +1569,6 @@ iterative_hash_template_arg (tree arg, hashval_t val)
>       val = iterative_hash_object (code, val);
>       return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val);
>
> -    case ARRAY_TYPE:
> -      /* layout_type sets structural equality for arrays of
> -        incomplete type, so we can't rely on the canonical type
> -        for hashing.  */
> -      val = iterative_hash_template_arg (TREE_TYPE (arg), val);
> -      return iterative_hash_template_arg (TYPE_DOMAIN (arg), val);
> -
>     case LAMBDA_EXPR:
>       /* A lambda can't appear in a template arg, but don't crash on
>         erroneous input.  */
> diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
> index 9056d7e..ed36c5b 100644
> --- a/gcc/stor-layout.c
> +++ b/gcc/stor-layout.c
> @@ -2028,11 +2028,6 @@ layout_type (tree type)
>  #else
>        TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);
>  #endif
> -       if (!TYPE_SIZE (element))
> -         /* We don't know the size of the underlying element type, so
> -            our alignment calculations will be wrong, forcing us to
> -            fall back on structural equality. */
> -         SET_TYPE_STRUCTURAL_EQUALITY (type);
>        TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
>        SET_TYPE_MODE (type, BLKmode);
>        if (TYPE_SIZE (type) != 0
> diff --git a/gcc/tree.c b/gcc/tree.c
> index c947072..61532db 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -5981,12 +5981,18 @@ type_hash_eq (const void *va, const void *vb)
>       || TREE_TYPE (a->type) != TREE_TYPE (b->type)
>       || !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
>                                 TYPE_ATTRIBUTES (b->type))
> -      || TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
> -      || TYPE_MODE (a->type) != TYPE_MODE (b->type)
>       || (TREE_CODE (a->type) != COMPLEX_TYPE
>           && TYPE_NAME (a->type) != TYPE_NAME (b->type)))
>     return 0;
>
> +  /* Be careful about comparing arrays before and after the element type
> +     has been completed; don't compare TYPE_ALIGN unless both types are
> +     complete.  */
> +  if (TYPE_SIZE (a->type) && TYPE_SIZE (b->type)
> +      && (TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
> +         || TYPE_MODE (a->type) != TYPE_MODE (b->type)))
> +    return 0;
> +
>   switch (TREE_CODE (a->type))
>     {
>     case VOID_TYPE:
>
>



More information about the Gcc-patches mailing list