]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple-fold: Fix up type_has_padding_at_level_p [PR117065]
authorJakub Jelinek <jakub@redhat.com>
Fri, 29 Nov 2024 09:19:08 +0000 (10:19 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 29 Nov 2024 09:19:08 +0000 (10:19 +0100)
The following testcase used to ICE on the trunk since the clear small
object if it has padding optimization before my r15-5746 change,
now it doesn't just because type_has_padding_at_level_p isn't called
on the testcase.

Though, as the testcase shows, structures/unions which contain erroneous
types of one or more of its members can have TREE_TYPE of the FIELD_DECL
error_mark_node, on which we can crash.

E.g. the __builtin_clear_padding lowering just ignores those:
            if (TREE_TYPE (field) == error_mark_node)
              continue;
and
                if (ftype == error_mark_node)
                  continue;
It doesn't matter much what exactly we do for those cases, as we are going
to fail the compilation anyway, but we shouldn't crash.

So, the following patch ignores those in type_has_padding_at_level_p.
For RECORD_TYPE, we already return if !DECL_SIZE (f) which I think should
cover already the erroneous fields (and we don't use TYPE_SIZE on those).

2024-11-29  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/117065
* gimple-fold.cc (type_has_padding_at_level_p) <case UNION_TYPE>:
Also continue if f has error_mark_node type.

* gcc.dg/pr117065.c: New test.

gcc/gimple-fold.cc
gcc/testsuite/gcc.dg/pr117065.c [new file with mode: 0644]

index e85744651d089d1be6f87c02dfa657338d2f8822..ba2c94794de095dbc44db0eaa0c2196b8232f97e 100644 (file)
@@ -4863,7 +4863,7 @@ type_has_padding_at_level_p (tree type)
       any_fields = false;
       /* If any of the fields is smaller than the whole, there is padding.  */
       for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
-       if (TREE_CODE (f) != FIELD_DECL)
+       if (TREE_CODE (f) != FIELD_DECL || TREE_TYPE (f) == error_mark_node)
          continue;
        else if (simple_cst_equal (TYPE_SIZE (TREE_TYPE (f)),
                                   TYPE_SIZE (type)) != 1)
diff --git a/gcc/testsuite/gcc.dg/pr117065.c b/gcc/testsuite/gcc.dg/pr117065.c
new file mode 100644 (file)
index 0000000..322cf4d
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR middle-end/117065 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+union U { struct A a; unsigned long long b; }; /* { dg-error "field 'a' has incomplete type" } */
+
+union U
+foo (void)
+{
+  union U u = { .b = 1 };
+  return u;
+}