aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-04-07 09:14:07 +0200
committerJakub Jelinek <jakub@redhat.com>2022-04-07 09:14:07 +0200
commit46c739d40c6c1028295931c53cf414d581519072 (patch)
tree70ecb58f0520543a4b071225b890f17fc21c9da6 /gcc
parent973a2ce71f8dab559fbbfc34b59e39e047df74a6 (diff)
downloadgcc-46c739d40c6c1028295931c53cf414d581519072.zip
gcc-46c739d40c6c1028295931c53cf414d581519072.tar.gz
gcc-46c739d40c6c1028295931c53cf414d581519072.tar.bz2
c++: Handle __builtin_clear_padding on non-trivially-copyable types [PR102586]
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. 2022-04-07 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-objcp-common.cc16
-rw-r--r--gcc/cp/cp-objcp-common.h3
-rw-r--r--gcc/gimple-fold.cc7
-rw-r--r--gcc/langhooks-def.h4
-rw-r--r--gcc/langhooks.h5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C44
7 files changed, 76 insertions, 5 deletions
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 8f74802..0b70d55 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -280,6 +280,22 @@ cp_unit_size_without_reusable_padding (tree type)
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)
+{
+ if (DECL_FIELD_IS_BASE (field))
+ {
+ tree type = TREE_TYPE (field);
+ if (TYPE_LANG_SPECIFIC (type))
+ return CLASSTYPE_AS_BASE (type);
+ }
+ return NULL_TREE;
+}
+
/* Stubs to keep c-opts.cc happy. */
void
push_file_scope (void)
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 4c13731..3c04e5c 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -31,6 +31,7 @@ extern int cp_decl_dwarf_attribute (const_tree, int);
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 (location_t, const char *,
#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
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 97880a5..ac22adf 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -4747,7 +4747,7 @@ clear_padding_type (clear_padding_struct *buf, tree type,
"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 *buf, tree type,
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;
}
}
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 49c8f58..e226395 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -216,6 +216,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
#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_reusable_padding (tree);
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. */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 0eec1b0..4731f08 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -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. */
diff --git a/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C b/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C
index 7b1282e..ed74ebf 100644
--- a/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C
@@ -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);
diff --git a/gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C
new file mode 100644
index 0000000..b5f0191
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-5.C
@@ -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 ();
+}