Hi! The following patches (included or attached) fix a regression on WebKit compilation. The first hunk basically reverts Honza's patch from December/January, because layout_type when the variants are already linked in doesn't layout just the current type, but also forcefully overwrites all the other variants, which is clearly highly undesirable. The attached patch has an alternate hunk for that, where it doesn't call layout_type at all and just copies over the needed fields from the main variant. The second hunk (the same in between both patches) fixes a problem that alignof (const T) is incorrect, but it has been that way already in 4.8 at least. I've been wondering if it would be possible that build_cplus_array_type would see incomplete element type on the main variant and complete qualified element type, but have not succeeded with e.g. struct S { typedef S T[4][4] __attribute__((aligned (16))); static T t; static volatile T v; }; void foo (const S::T); volatile const S::T w; S::T S::t; volatile S::T S::v; The included (first) patch has been successfully bootstrapped/regtested on x86_64-linux and i686-linux, the attached patch not, but I can bootstrap/regtest it if you prefer it. 2015-04-08 Jakub Jelinek Jan Hubicka PR c++/65690 * tree.c (build_cplus_array_type): Layout type before variants are set, but copy over TYPE_SIZE and TYPE_SIZE_UNIT from the main variant. (cp_build_qualified_type_real): Use check_base_type. Build a variant and copy over even TYPE_CONTEXT and TYPE_ALIGN/TYPE_USER_ALIGN if any of those are different. * c-c++-common/attr-aligned-1.c: New test. --- gcc/cp/tree.c.jj 2015-04-01 15:29:33.000000000 +0200 +++ gcc/cp/tree.c 2015-04-08 09:09:45.326939354 +0200 @@ -880,12 +880,19 @@ build_cplus_array_type (tree elt_type, t { t = build_min_array_type (elt_type, index_type); set_array_type_canon (t, elt_type, index_type); + if (!dependent) + { + layout_type (t); + /* Make sure sizes are shared with the main variant. + layout_type can't be called after setting TYPE_NEXT_VARIANT, + as it will overwrite alignment etc. of all variants. */ + TYPE_SIZE (t) = TYPE_SIZE (m); + TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (m); + } TYPE_MAIN_VARIANT (t) = m; TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); TYPE_NEXT_VARIANT (m) = t; - if (!dependent) - layout_type (t); } } @@ -1057,21 +1064,23 @@ cp_build_qualified_type_real (tree type, should be equivalent to those in check_qualified_type. */ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) if (TREE_TYPE (t) == element_type - && TYPE_NAME (t) == TYPE_NAME (type) - && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) - && attribute_list_equal (TYPE_ATTRIBUTES (t), - TYPE_ATTRIBUTES (type))) + && check_base_type (t, type)) break; if (!t) { t = build_cplus_array_type (element_type, TYPE_DOMAIN (type)); - /* Keep the typedef name. */ - if (TYPE_NAME (t) != TYPE_NAME (type)) + /* Keep the typedef name, context and alignment. */ + if (TYPE_NAME (t) != TYPE_NAME (type) + || TYPE_CONTEXT (t) != TYPE_CONTEXT (type) + || TYPE_ALIGN (t) != TYPE_ALIGN (type)) { t = build_variant_type_copy (t); TYPE_NAME (t) = TYPE_NAME (type); + TYPE_CONTEXT (t) = TYPE_CONTEXT (type); + TYPE_ALIGN (t) = TYPE_ALIGN (type); + TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type); } } --- gcc/testsuite/c-c++-common/attr-aligned-1.c.jj 2015-04-08 09:22:46.181427189 +0200 +++ gcc/testsuite/c-c++-common/attr-aligned-1.c 2015-04-08 09:26:41.315627195 +0200 @@ -0,0 +1,24 @@ +/* PR c++/65690 */ +/* { dg-do run } */ + +typedef double T[4][4] __attribute__((aligned (2 * __alignof__ (double)))); +void foo (const T); +struct S { T s; }; + +int +main () +{ + if (__alignof__ (struct S) != 2 * __alignof__ (double) + || __alignof__ (T) != 2 * __alignof__ (double) + || __alignof__ (const struct S) != 2 * __alignof__ (double) + || __alignof__ (const T) != 2 * __alignof__ (double)) + __builtin_abort (); + return 0; +} + +#if defined(__cplusplus) && __cplusplus >= 201103L +static_assert (alignof (S) == 2 * alignof (double), "alignment of S"); +static_assert (alignof (T) == 2 * alignof (double), "alignment of T"); +static_assert (alignof (const S) == 2 * alignof (double), "alignment of const S"); +static_assert (alignof (const T) == 2 * alignof (double), "alignment of const T"); +#endif Jakub