Message ID | Yk2mm7LPfeQim12H@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Handle __builtin_clear_padding on non-trivially-copyable types [PR102586] | expand |
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 >
--- 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);