https://gcc.gnu.org/g:f93059c82e61d67bc550ba0e3bf915ab763b02c7
commit r15-5772-gf93059c82e61d67bc550ba0e3bf915ab763b02c7 Author: Jakub Jelinek <ja...@redhat.com> Date: Fri Nov 29 10:19:08 2024 +0100 gimple-fold: Fix up type_has_padding_at_level_p [PR117065] 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 <ja...@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. Diff: --- gcc/gimple-fold.cc | 2 +- gcc/testsuite/gcc.dg/pr117065.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index e85744651d08..ba2c94794de0 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -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 index 000000000000..322cf4de1ae7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr117065.c @@ -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; +}