From: Martin Uecker Date: Sat, 28 Feb 2026 16:12:43 +0000 (+0100) Subject: c: Fix recursive structure / union redeclaration with qualifiers [PR124303] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7c3e6df8ae01a473fba63e12efe2c82bd50ad502;p=thirdparty%2Fgcc.git c: Fix recursive structure / union redeclaration with qualifiers [PR124303] We reject correct recursive redeclarations when qualifiers are involved. The reason is that the check is done before the variants are completed. PR c/124303 gcc/c/ChangeLog: * c-decl.cc (finish_struct): Check for consistency of declarations after completing variants. gcc/testsuite/ChangeLog: * gcc.dg/pr124303.c: New test. --- diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 8a894de3a1b..37bd01ab7b0 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9970,6 +9970,23 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, warning_at (loc, 0, "union cannot be made transparent"); } + tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)); + for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) + { + TYPE_FIELDS (x) = TYPE_FIELDS (t); + TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t); + TYPE_TRANSPARENT_AGGR (x) = TYPE_TRANSPARENT_AGGR (t); + TYPE_TYPELESS_STORAGE (x) = TYPE_TYPELESS_STORAGE (t); + C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t); + C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t); + C_TYPE_FIELDS_NON_CONSTEXPR (x) = C_TYPE_FIELDS_NON_CONSTEXPR (t); + C_TYPE_FIELDS_HAS_COUNTED_BY (x) = C_TYPE_FIELDS_HAS_COUNTED_BY (t); + C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t); + C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t); + C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE; + TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t); + } + /* Check for consistency with previous definition. */ if (flag_isoc23 && NULL != enclosing_struct_parse_info) { @@ -10024,23 +10041,6 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, c_update_type_canonical (t); } - tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)); - for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) - { - TYPE_FIELDS (x) = TYPE_FIELDS (t); - TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t); - TYPE_TRANSPARENT_AGGR (x) = TYPE_TRANSPARENT_AGGR (t); - TYPE_TYPELESS_STORAGE (x) = TYPE_TYPELESS_STORAGE (t); - C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t); - C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t); - C_TYPE_FIELDS_NON_CONSTEXPR (x) = C_TYPE_FIELDS_NON_CONSTEXPR (t); - C_TYPE_FIELDS_HAS_COUNTED_BY (x) = C_TYPE_FIELDS_HAS_COUNTED_BY (t); - C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t); - C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t); - C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE; - TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t); - } - /* Update type location to the one of the definition, instead of e.g. a forward declaration. */ if (TYPE_STUB_DECL (t)) diff --git a/gcc/testsuite/gcc.dg/pr124303.c b/gcc/testsuite/gcc.dg/pr124303.c new file mode 100644 index 00000000000..e7075875108 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr124303.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c23" } */ + +struct s { void (*p)(const struct s*); }; +struct s { void (*p)(const struct s*); }; + +