While working on the GCC 11 patch, it occurred to me that we could move the errors about invalid members from finish_struct_anon_r to here, so we properly get a diagnostic in g++.law/union4.C.
Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/97974 * class.c (finish_struct_anon_r): Drop complain parm. Remove non-field diagnostic. (finish_struct_anon): Adjust. * decl.c (fixup_anonymous_aggr): Move non-field diagnostic here. gcc/testsuite/ChangeLog: PR c++/97974 * g++.old-deja/g++.law/union4.C: Add expected diagnostic. --- gcc/cp/class.c | 34 ++-------------- gcc/cp/decl.c | 45 ++++++++++++++++++--- gcc/testsuite/g++.old-deja/g++.law/union4.C | 2 +- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 2cf527e4a84..d693b438668 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3023,7 +3023,7 @@ warn_hidden (tree t) /* Recursive helper for finish_struct_anon. */ static void -finish_struct_anon_r (tree field, bool complain) +finish_struct_anon_r (tree field) { for (tree elt = TYPE_FIELDS (TREE_TYPE (field)); elt; elt = DECL_CHAIN (elt)) { @@ -3039,34 +3039,6 @@ finish_struct_anon_r (tree field, bool complain) || TYPE_UNNAMED_P (TREE_TYPE (elt)))) continue; - if (complain - && (TREE_CODE (elt) != FIELD_DECL - || (TREE_PRIVATE (elt) || TREE_PROTECTED (elt)))) - { - /* We already complained about static data members in - finish_static_data_member_decl. */ - if (!VAR_P (elt)) - { - auto_diagnostic_group d; - if (permerror (DECL_SOURCE_LOCATION (elt), - TREE_CODE (TREE_TYPE (field)) == UNION_TYPE - ? "%q#D invalid; an anonymous union may " - "only have public non-static data members" - : "%q#D invalid; an anonymous struct may " - "only have public non-static data members", elt)) - { - static bool hint; - if (flag_permissive && !hint) - { - hint = true; - inform (DECL_SOURCE_LOCATION (elt), - "this flexibility is deprecated and will be " - "removed"); - } - } - } - } - TREE_PRIVATE (elt) = TREE_PRIVATE (field); TREE_PROTECTED (elt) = TREE_PROTECTED (field); @@ -3084,7 +3056,7 @@ finish_struct_anon_r (tree field, bool complain) int j=A().i; */ if (DECL_NAME (elt) == NULL_TREE && ANON_AGGR_TYPE_P (TREE_TYPE (elt))) - finish_struct_anon_r (elt, /*complain=*/false); + finish_struct_anon_r (elt); } } @@ -3103,7 +3075,7 @@ finish_struct_anon (tree t) if (DECL_NAME (field) == NULL_TREE && ANON_AGGR_TYPE_P (TREE_TYPE (field))) - finish_struct_anon_r (field, /*complain=*/true); + finish_struct_anon_r (field); } } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 60dc2bf182d..e51c1b09652 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5005,12 +5005,47 @@ fixup_anonymous_aggr (tree t) TYPE_HAS_COPY_ASSIGN (t) = 0; TYPE_HAS_CONST_COPY_ASSIGN (t) = 0; - /* Splice the implicitly generated functions out of TYPE_FIELDS. */ + /* Splice the implicitly generated functions out of TYPE_FIELDS and diagnose + invalid members. */ for (tree probe, *prev_p = &TYPE_FIELDS (t); (probe = *prev_p);) - if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe)) - *prev_p = DECL_CHAIN (probe); - else - prev_p = &DECL_CHAIN (probe); + { + if (TREE_CODE (probe) == FUNCTION_DECL && DECL_ARTIFICIAL (probe)) + *prev_p = DECL_CHAIN (probe); + else + prev_p = &DECL_CHAIN (probe); + + if (DECL_ARTIFICIAL (probe) + && (!DECL_IMPLICIT_TYPEDEF_P (probe) + || TYPE_ANON_P (TREE_TYPE (probe)))) + continue; + + if (TREE_CODE (probe) != FIELD_DECL + || (TREE_PRIVATE (probe) || TREE_PROTECTED (probe))) + { + /* We already complained about static data members in + finish_static_data_member_decl. */ + if (!VAR_P (probe)) + { + auto_diagnostic_group d; + if (permerror (DECL_SOURCE_LOCATION (probe), + TREE_CODE (t) == UNION_TYPE + ? "%q#D invalid; an anonymous union may " + "only have public non-static data members" + : "%q#D invalid; an anonymous struct may " + "only have public non-static data members", probe)) + { + static bool hint; + if (flag_permissive && !hint) + { + hint = true; + inform (DECL_SOURCE_LOCATION (probe), + "this flexibility is deprecated and will be " + "removed"); + } + } + } + } + } /* Splice all functions out of CLASSTYPE_MEMBER_VEC. */ vec<tree,va_gc>* vec = CLASSTYPE_MEMBER_VEC (t); diff --git a/gcc/testsuite/g++.old-deja/g++.law/union4.C b/gcc/testsuite/g++.old-deja/g++.law/union4.C index 958ff0afe5b..ec30d1e3a13 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/union4.C +++ b/gcc/testsuite/g++.old-deja/g++.law/union4.C @@ -7,7 +7,7 @@ // Message-ID: <m0pa49a-0000...@piano.veritas.com> static union { - struct SS { + struct SS { // { dg-error "anonymous union" } int ss; }; };// { dg-error "no members" } base-commit: 449d7b40f6f6be8d7f9aa7232c73b0371f0963bf prerequisite-patch-id: 39f358d55a4ba496b673d13e00215152266caa54 prerequisite-patch-id: f0d6c56fe2c9e16572f0760fb223f6d4df3e859e -- 2.27.0