summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-05-17 10:15:50 +0200
committerJakub Jelinek <jakub@redhat.com>2023-05-17 10:15:50 +0200
commit78327cf06e6b65fc9c614622c98f6a3f3bfb7784 (patch)
tree9cb38eda5fe19858a0a975f5031dafdedce2def7
parenta04bf39f61ce7814d197d712760f08c206daf4f1 (diff)
downloadgcc-78327cf06e6b65fc9c614622c98f6a3f3bfb7784.tar.gz
c++: Don't try to initialize zero width bitfields in zero initialization [PR109868]
My GCC 12 change to avoid removing zero-sized bitfields as they are important for ABI and are needed for layout compatibility traits apparently causes zero sized bitfields to be initialized in the IL, which at least in 13+ results in ICEs in the ranger which is upset about zero precision types. I think we could even avoid initializing other unnamed bitfields, but unfortunately !CONSTRUCTOR_NO_CLEARING doesn't mean in the middle-end clearing of padding bits and until we have some new flag that represents the request to clear padding bits, I think it is better to keep zeroing non-zero sized unnamed bitfields. In addition to skipping those fields, I have changed the logic how UNION_TYPEs are handled, the current code was a little bit weird in that e.g. if first non-static data member had error_mark_node type, we'd happily zero initialize the second non-static data member, etc. 2023-05-17 Jakub Jelinek <jakub@redhat.com> PR c++/109868 * init.cc (build_zero_init_1): Don't initialize zero-width bitfields. For unions only initialize the first FIELD_DECL. * g++.dg/init/pr109868.C: New test.
-rw-r--r--gcc/cp/init.cc19
-rw-r--r--gcc/testsuite/g++.dg/init/pr109868.C13
2 files changed, 26 insertions, 6 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 0b35e1092e9..6ccda365b04 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -189,15 +189,21 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
init = build_zero_cst (type);
else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
{
- tree field;
+ tree field, next;
vec<constructor_elt, va_gc> *v = NULL;
/* Iterate over the fields, building initializations. */
- for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = next)
{
+ next = DECL_CHAIN (field);
+
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ /* For unions, only the first field is initialized. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ next = NULL_TREE;
+
if (TREE_TYPE (field) == error_mark_node)
continue;
@@ -212,6 +218,11 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
continue;
}
+ /* Don't add zero width bitfields. */
+ if (DECL_C_BIT_FIELD (field)
+ && integer_zerop (DECL_SIZE (field)))
+ continue;
+
/* Note that for class types there will be FIELD_DECLs
corresponding to base classes as well. Thus, iterating
over TYPE_FIELDs will result in correct initialization of
@@ -230,10 +241,6 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
if (value)
CONSTRUCTOR_APPEND_ELT(v, field, value);
}
-
- /* For unions, only the first field is initialized. */
- if (TREE_CODE (type) == UNION_TYPE)
- break;
}
/* Build a constructor to contain the initializations. */
diff --git a/gcc/testsuite/g++.dg/init/pr109868.C b/gcc/testsuite/g++.dg/init/pr109868.C
new file mode 100644
index 00000000000..0926f406e4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr109868.C
@@ -0,0 +1,13 @@
+// PR c++/109868
+// { dg-do compile }
+// { dg-options "-O2" }
+
+struct A { virtual void foo (); };
+struct B { long b; int : 0; };
+struct C : A { B c; };
+
+void
+bar (C *p)
+{
+ *p = C ();
+}