diff mbox series

c++: Handle __builtin_clear_padding on non-trivially-copyable types [PR102586]

Message ID Yk2mm7LPfeQim12H@tucnak
State New
Headers show
Series c++: Handle __builtin_clear_padding on non-trivially-copyable types [PR102586] | expand

Commit Message

Jakub Jelinek April 6, 2022, 2:41 p.m. UTC
On Fri, Feb 11, 2022 at 07:55:50PM +0100, Jakub Jelinek via Gcc-patches wrote:
> Something like the https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c16
> will still be needed with adjusted testcase from
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c15 such that
> __builtin_clear_padding is called directly on var addresses rather than
> in separate functions.

Here is an updated version of the
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c15
patch which uses FIELD_DECL in the langhook instead of its TREE_TYPE,
and the testcases have been adjusted for the builtin accepting
pointers to non-trivially-copyable types only if it is address of a
declaration.

Bootstrapped/regtested on powerpc64le-linux, ok for trunk?

2022-04-06  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/102586
gcc/
	* langhooks.h (struct lang_hooks_for_types): Add classtype_as_base
	langhook.
	* langhooks-def.h (LANG_HOOKS_CLASSTYPE_AS_BASE): Define.
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add it.
	* gimple-fold.cc (clear_padding_type): Use ftype instead of
	TREE_TYPE (field) some more.  For artificial FIELD_DECLs without
	name try the lang_hooks.types.classtype_as_base langhook and
	if it returns non-NULL, use that instead of ftype for recursive call.
gcc/cp/
	* cp-objcp-common.h (cp_classtype_as_base): Declare.
	(LANG_HOOKS_CLASSTYPE_AS_BASE): Redefine.
	* cp-objcp-common.cc (cp_classtype_as_base): New function.
gcc/testsuite/
	* g++.dg/torture/builtin-clear-padding-5.C: New test.
	* g++.dg/cpp2a/builtin-clear-padding1.C (bar): Uncomment one
	call that is now accepted.



	Jakub

Comments

Jason Merrill April 6, 2022, 3:11 p.m. UTC | #1
On 4/6/22 10:41, Jakub Jelinek wrote:
> On Fri, Feb 11, 2022 at 07:55:50PM +0100, Jakub Jelinek via Gcc-patches wrote:
>> Something like the https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c16
>> will still be needed with adjusted testcase from
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c15 such that
>> __builtin_clear_padding is called directly on var addresses rather than
>> in separate functions.
> 
> Here is an updated version of the
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c15
> patch which uses FIELD_DECL in the langhook instead of its TREE_TYPE,
> and the testcases have been adjusted for the builtin accepting
> pointers to non-trivially-copyable types only if it is address of a
> declaration.
> 
> Bootstrapped/regtested on powerpc64le-linux, ok for trunk?
> 
> 2022-04-06  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/102586
> gcc/
> 	* langhooks.h (struct lang_hooks_for_types): Add classtype_as_base
> 	langhook.
> 	* langhooks-def.h (LANG_HOOKS_CLASSTYPE_AS_BASE): Define.
> 	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add it.
> 	* gimple-fold.cc (clear_padding_type): Use ftype instead of
> 	TREE_TYPE (field) some more.  For artificial FIELD_DECLs without
> 	name try the lang_hooks.types.classtype_as_base langhook and
> 	if it returns non-NULL, use that instead of ftype for recursive call.
> gcc/cp/
> 	* cp-objcp-common.h (cp_classtype_as_base): Declare.
> 	(LANG_HOOKS_CLASSTYPE_AS_BASE): Redefine.
> 	* cp-objcp-common.cc (cp_classtype_as_base): New function.
> gcc/testsuite/
> 	* g++.dg/torture/builtin-clear-padding-5.C: New test.
> 	* g++.dg/cpp2a/builtin-clear-padding1.C (bar): Uncomment one
> 	call that is now accepted.
> 
> --- gcc/langhooks.h.jj	2022-02-11 00:18:54.909437559 +0100
> +++ gcc/langhooks.h	2022-04-06 12:34:43.312087323 +0200
> @@ -188,6 +188,11 @@ struct lang_hooks_for_types
>     /* Returns a tree for the unit size of T excluding tail padding that
>        might be used by objects inheriting from T.  */
>     tree (*unit_size_without_reusable_padding) (tree);
> +
> +  /* Returns type corresponding to FIELD's type when FIELD is a C++ base class
> +     i.e., type without virtual base classes or tail padding.  Returns
> +     NULL_TREE otherwise.  */
> +  tree (*classtype_as_base) (const_tree);
>   };
>   
>   /* Language hooks related to decls and the symbol table.  */
> --- gcc/langhooks-def.h.jj	2022-02-11 00:18:54.887437859 +0100
> +++ gcc/langhooks-def.h	2022-04-06 12:31:39.149670170 +0200
> @@ -216,6 +216,7 @@ extern tree lhd_unit_size_without_reusab
>   #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
>   #define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE	lhd_type_dwarf_attribute
>   #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING lhd_unit_size_without_reusable_padding
> +#define LANG_HOOKS_CLASSTYPE_AS_BASE	hook_tree_const_tree_null
>   
>   #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
>     LANG_HOOKS_MAKE_TYPE, \
> @@ -243,7 +244,8 @@ extern tree lhd_unit_size_without_reusab
>     LANG_HOOKS_GET_DEBUG_TYPE, \
>     LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
>     LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, \
> -  LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING \
> +  LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING, \
> +  LANG_HOOKS_CLASSTYPE_AS_BASE \
>   }
>   
>   /* Declaration hooks.  */
> --- gcc/gimple-fold.cc.jj	2022-04-06 09:59:32.744654454 +0200
> +++ gcc/gimple-fold.cc	2022-04-06 12:35:29.413440758 +0200
> @@ -4747,7 +4747,7 @@ clear_padding_type (clear_padding_struct
>   				      "have well defined padding bits for %qs",
>   			    field, "__builtin_clear_padding");
>   	      }
> -	    else if (is_empty_type (TREE_TYPE (field)))
> +	    else if (is_empty_type (ftype))
>   	      continue;
>   	    else
>   	      {
> @@ -4758,8 +4758,9 @@ clear_padding_type (clear_padding_struct
>   		gcc_assert (pos >= 0 && fldsz >= 0 && pos >= cur_pos);
>   		clear_padding_add_padding (buf, pos - cur_pos);
>   		cur_pos = pos;
> -		clear_padding_type (buf, TREE_TYPE (field),
> -				    fldsz, for_auto_init);
> +		if (tree asbase = lang_hooks.types.classtype_as_base (field))
> +		  ftype = asbase;
> +		clear_padding_type (buf, ftype, fldsz, for_auto_init);
>   		cur_pos += fldsz;
>   	      }
>   	  }
> --- gcc/cp/cp-objcp-common.h.jj	2022-02-11 00:18:54.730439994 +0100
> +++ gcc/cp/cp-objcp-common.h	2022-04-06 12:31:39.151670141 +0200
> @@ -31,6 +31,7 @@ extern int cp_decl_dwarf_attribute (cons
>   extern int cp_type_dwarf_attribute (const_tree, int);
>   extern void cp_common_init_ts (void);
>   extern tree cp_unit_size_without_reusable_padding (tree);
> +extern tree cp_classtype_as_base (const_tree);
>   extern tree cp_get_global_decls ();
>   extern tree cp_pushdecl (tree);
>   extern void cp_register_dumps (gcc::dump_manager *);
> @@ -167,6 +168,8 @@ extern tree cxx_simulate_record_decl (lo
>   #define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
>   #undef LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING
>   #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING cp_unit_size_without_reusable_padding
> +#undef LANG_HOOKS_CLASSTYPE_AS_BASE
> +#define LANG_HOOKS_CLASSTYPE_AS_BASE cp_classtype_as_base
>   
>   #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
>   #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
> --- gcc/cp/cp-objcp-common.cc.jj	2022-02-11 00:18:54.720440130 +0100
> +++ gcc/cp/cp-objcp-common.cc	2022-04-06 13:24:43.543051969 +0200
> @@ -280,6 +280,23 @@ cp_unit_size_without_reusable_padding (t
>     return TYPE_SIZE_UNIT (type);
>   }
>   
> +/* Returns type corresponding to FIELD's type when FIELD is a C++ base class
> +   i.e., type without virtual base classes or tail padding.  Returns
> +   NULL_TREE otherwise.  */
> +
> +tree
> +cp_classtype_as_base (const_tree field)
> +{
> +  tree type = TREE_TYPE (field);
> +  if (!DECL_ARTIFICIAL (field)
> +      || DECL_NAME (field) != NULL_TREE
> +      || TREE_CODE (type) != RECORD_TYPE)
> +    return NULL_TREE;
> +  if (!TYPE_LANG_SPECIFIC (type))
> +    return NULL_TREE;

Now that this is in the front-end, we can replace the above checks with 
DECL_FIELD_IS_BASE.  OK with that change.

> +  return CLASSTYPE_AS_BASE (type);
> +}
> +
>   /* Stubs to keep c-opts.cc happy.  */
>   void
>   push_file_scope (void)
> --- gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C.jj	2022-04-06 12:31:39.151670141 +0200
> +++ gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C	2022-04-06 13:15:36.674717019 +0200
> @@ -0,0 +1,44 @@
> +// PR tree-optimization/102586
> +// { dg-options "-Wno-inaccessible-base" }
> +
> +struct C0 {};
> +struct C1 {};
> +struct C2 : C1, virtual C0 {};
> +struct C3 : virtual C2, C1 { virtual int foo () { return 1; } };
> +struct C4 : virtual C3, C1 { virtual int foo () { return 2; } };
> +struct C5 : C4 { virtual int foo () { return 3; } };
> +struct C6 { char c; };
> +struct C7 : virtual C6, virtual C3, C1 { virtual int foo () { return 4; } };
> +struct C8 : C7 { virtual int foo () { return 5; } };
> +
> +__attribute__((noipa)) int
> +bar (C5 *p)
> +{
> +  return p->foo ();
> +}
> +
> +__attribute__((noipa)) int
> +baz (C3 *p)
> +{
> +  return p->foo ();
> +}
> +
> +__attribute__((noipa)) int
> +qux (C8 *p)
> +{
> +  return p->foo ();
> +}
> +
> +int
> +main ()
> +{
> +  C5 c5;
> +  C8 c8;
> +  c8.c = 42;
> +  __builtin_clear_padding (&c5);
> +  __builtin_clear_padding (&c8);
> +  if (bar (&c5) != 3 || baz (&c5) != 3)
> +    __builtin_abort ();
> +  if (qux (&c8) != 5 || baz (&c8) != 5 || c8.c != 42)
> +    __builtin_abort ();
> +}
> --- gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C.jj	2022-03-14 10:46:42.021766309 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C	2022-04-06 13:14:31.614628521 +0200
> @@ -43,7 +43,7 @@ bar ()
>     __builtin_clear_padding (&c2);
>     __builtin_clear_padding (&c3);
>     __builtin_clear_padding (&c4);
> -//  __builtin_clear_padding (&c5);
> +  __builtin_clear_padding (&c5);
>     __builtin_clear_padding (&c6);
>     __builtin_clear_padding (&c7);
>     __builtin_clear_padding (&c8);
> 
> 
> 	Jakub
>
diff mbox series

Patch

--- gcc/langhooks.h.jj	2022-02-11 00:18:54.909437559 +0100
+++ gcc/langhooks.h	2022-04-06 12:34:43.312087323 +0200
@@ -188,6 +188,11 @@  struct lang_hooks_for_types
   /* Returns a tree for the unit size of T excluding tail padding that
      might be used by objects inheriting from T.  */
   tree (*unit_size_without_reusable_padding) (tree);
+
+  /* Returns type corresponding to FIELD's type when FIELD is a C++ base class
+     i.e., type without virtual base classes or tail padding.  Returns
+     NULL_TREE otherwise.  */
+  tree (*classtype_as_base) (const_tree);
 };
 
 /* Language hooks related to decls and the symbol table.  */
--- gcc/langhooks-def.h.jj	2022-02-11 00:18:54.887437859 +0100
+++ gcc/langhooks-def.h	2022-04-06 12:31:39.149670170 +0200
@@ -216,6 +216,7 @@  extern tree lhd_unit_size_without_reusab
 #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
 #define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE	lhd_type_dwarf_attribute
 #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING lhd_unit_size_without_reusable_padding
+#define LANG_HOOKS_CLASSTYPE_AS_BASE	hook_tree_const_tree_null
 
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
   LANG_HOOKS_MAKE_TYPE, \
@@ -243,7 +244,8 @@  extern tree lhd_unit_size_without_reusab
   LANG_HOOKS_GET_DEBUG_TYPE, \
   LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
   LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, \
-  LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING \
+  LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING, \
+  LANG_HOOKS_CLASSTYPE_AS_BASE \
 }
 
 /* Declaration hooks.  */
--- gcc/gimple-fold.cc.jj	2022-04-06 09:59:32.744654454 +0200
+++ gcc/gimple-fold.cc	2022-04-06 12:35:29.413440758 +0200
@@ -4747,7 +4747,7 @@  clear_padding_type (clear_padding_struct
 				      "have well defined padding bits for %qs",
 			    field, "__builtin_clear_padding");
 	      }
-	    else if (is_empty_type (TREE_TYPE (field)))
+	    else if (is_empty_type (ftype))
 	      continue;
 	    else
 	      {
@@ -4758,8 +4758,9 @@  clear_padding_type (clear_padding_struct
 		gcc_assert (pos >= 0 && fldsz >= 0 && pos >= cur_pos);
 		clear_padding_add_padding (buf, pos - cur_pos);
 		cur_pos = pos;
-		clear_padding_type (buf, TREE_TYPE (field),
-				    fldsz, for_auto_init);
+		if (tree asbase = lang_hooks.types.classtype_as_base (field))
+		  ftype = asbase;
+		clear_padding_type (buf, ftype, fldsz, for_auto_init);
 		cur_pos += fldsz;
 	      }
 	  }
--- gcc/cp/cp-objcp-common.h.jj	2022-02-11 00:18:54.730439994 +0100
+++ gcc/cp/cp-objcp-common.h	2022-04-06 12:31:39.151670141 +0200
@@ -31,6 +31,7 @@  extern int cp_decl_dwarf_attribute (cons
 extern int cp_type_dwarf_attribute (const_tree, int);
 extern void cp_common_init_ts (void);
 extern tree cp_unit_size_without_reusable_padding (tree);
+extern tree cp_classtype_as_base (const_tree);
 extern tree cp_get_global_decls ();
 extern tree cp_pushdecl (tree);
 extern void cp_register_dumps (gcc::dump_manager *);
@@ -167,6 +168,8 @@  extern tree cxx_simulate_record_decl (lo
 #define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
 #undef LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING
 #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING cp_unit_size_without_reusable_padding
+#undef LANG_HOOKS_CLASSTYPE_AS_BASE
+#define LANG_HOOKS_CLASSTYPE_AS_BASE cp_classtype_as_base
 
 #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
--- gcc/cp/cp-objcp-common.cc.jj	2022-02-11 00:18:54.720440130 +0100
+++ gcc/cp/cp-objcp-common.cc	2022-04-06 13:24:43.543051969 +0200
@@ -280,6 +280,23 @@  cp_unit_size_without_reusable_padding (t
   return TYPE_SIZE_UNIT (type);
 }
 
+/* Returns type corresponding to FIELD's type when FIELD is a C++ base class
+   i.e., type without virtual base classes or tail padding.  Returns
+   NULL_TREE otherwise.  */
+
+tree
+cp_classtype_as_base (const_tree field)
+{
+  tree type = TREE_TYPE (field);
+  if (!DECL_ARTIFICIAL (field)
+      || DECL_NAME (field) != NULL_TREE
+      || TREE_CODE (type) != RECORD_TYPE)
+    return NULL_TREE;
+  if (!TYPE_LANG_SPECIFIC (type))
+    return NULL_TREE;
+  return CLASSTYPE_AS_BASE (type);
+}
+
 /* Stubs to keep c-opts.cc happy.  */
 void
 push_file_scope (void)
--- gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C.jj	2022-04-06 12:31:39.151670141 +0200
+++ gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C	2022-04-06 13:15:36.674717019 +0200
@@ -0,0 +1,44 @@ 
+// PR tree-optimization/102586
+// { dg-options "-Wno-inaccessible-base" }
+
+struct C0 {};
+struct C1 {};
+struct C2 : C1, virtual C0 {};
+struct C3 : virtual C2, C1 { virtual int foo () { return 1; } };
+struct C4 : virtual C3, C1 { virtual int foo () { return 2; } };
+struct C5 : C4 { virtual int foo () { return 3; } };
+struct C6 { char c; };
+struct C7 : virtual C6, virtual C3, C1 { virtual int foo () { return 4; } };
+struct C8 : C7 { virtual int foo () { return 5; } };
+
+__attribute__((noipa)) int
+bar (C5 *p)
+{
+  return p->foo ();
+}
+
+__attribute__((noipa)) int
+baz (C3 *p)
+{
+  return p->foo ();
+}
+
+__attribute__((noipa)) int
+qux (C8 *p)
+{
+  return p->foo ();
+}
+
+int
+main ()
+{
+  C5 c5;
+  C8 c8;
+  c8.c = 42;
+  __builtin_clear_padding (&c5);
+  __builtin_clear_padding (&c8);
+  if (bar (&c5) != 3 || baz (&c5) != 3)
+    __builtin_abort ();
+  if (qux (&c8) != 5 || baz (&c8) != 5 || c8.c != 42)
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C.jj	2022-03-14 10:46:42.021766309 +0100
+++ gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C	2022-04-06 13:14:31.614628521 +0200
@@ -43,7 +43,7 @@  bar ()
   __builtin_clear_padding (&c2);
   __builtin_clear_padding (&c3);
   __builtin_clear_padding (&c4);
-//  __builtin_clear_padding (&c5);
+  __builtin_clear_padding (&c5);
   __builtin_clear_padding (&c6);
   __builtin_clear_padding (&c7);
   __builtin_clear_padding (&c8);