public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Fix alignment handling in build_cplus_array_type/cp_build_qualified_type_real (PR c++/65690)
@ 2015-04-08 10:02 Jakub Jelinek
  2015-04-08 14:47 ` Jason Merrill
  2015-04-09  9:39 ` Jakub Jelinek
  0 siblings, 2 replies; 14+ messages in thread
From: Jakub Jelinek @ 2015-04-08 10:02 UTC (permalink / raw)
  To: Jason Merrill, Jan Hubicka; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4563 bytes --]

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  <jakub@redhat.com>
	    Jan Hubicka  <hubicka@ucw.cz>

	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

[-- Attachment #2: V554a --]
[-- Type: text/plain, Size: 3282 bytes --]

2015-04-08  Jakub Jelinek  <jakub@redhat.com>
	    Jan Hubicka  <hubicka@ucw.cz>

	PR c++/65690
	* tree.c (build_cplus_array_type): Don't layout the type,
	instead copy everything over 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)
+	    {
+	      TYPE_SIZE (t) = TYPE_SIZE (m);
+	      TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (m);
+	      TYPE_ALIGN (t) = TYPE_ALIGN (m);
+	      TYPE_PRECISION (t) = TYPE_PRECISION (m);
+	      TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (m);
+	      SET_TYPE_MODE (t, TYPE_MODE (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

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-04-10 14:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-08 10:02 [C++ PATCH] Fix alignment handling in build_cplus_array_type/cp_build_qualified_type_real (PR c++/65690) Jakub Jelinek
2015-04-08 14:47 ` Jason Merrill
2015-04-08 15:08   ` Jakub Jelinek
2015-04-09 14:48     ` Jason Merrill
2015-04-09 15:19       ` Jakub Jelinek
2015-04-08 16:22   ` Jan Hubicka
2015-04-08 16:28     ` Jakub Jelinek
2015-04-08 16:32       ` Jan Hubicka
2015-04-08 17:00         ` Jakub Jelinek
2015-04-09  9:39 ` Jakub Jelinek
2015-04-09 14:51   ` Jason Merrill
2015-04-09 18:12     ` [C++ PATCH] Fix alignment handling in build_cplus_array_type/cp_build_qualified_type_real (PR c++/65715) Jakub Jelinek
2015-04-10 14:28       ` Jason Merrill
2015-04-10 14:31         ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).