https://gcc.gnu.org/g:f20f6c796499d097d301104fb2abe49fb77ce492
commit r16-1760-gf20f6c796499d097d301104fb2abe49fb77ce492 Author: Nathaniel Shead <nathanielosh...@gmail.com> Date: Fri Jun 27 18:56:25 2025 +1000 c++/modules: Make bitfield storage unit detection more robust Modules streaming needs to handle these differently from other unnamed FIELD_DECLs that are streamed for internal RECORD_DECLs, and there doesn't seem to be a good way to detect this case otherwise. This matters only to allow for compiler-generated type definitions that build FIELD_DECLs with no name, as otherwise they get confused. Currently the only such types left I hadn't earlier fixed by giving names to are contextless, for which we have an early check to mark their fields as MK_unique anyway, but there may be other cases in the future. gcc/cp/ChangeLog: * module.cc (trees_out::walking_bit_field_unit): New flag. (trees_out::trees_out): Initialize it. (trees_out::core_vals): Set it. (trees_out::get_merge_kind): Use it, move previous ad-hoc check into assertion. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> Diff: --- gcc/cp/module.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 846e532c4380..c8e79f33af41 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -3097,6 +3097,9 @@ private: unsigned section; bool writing_local_entities; /* Whether we might walk into a TU-local entity we need to emit placeholders for. */ + bool walking_bit_field_unit; /* Whether we're walking the underlying + storage for a bit field. There's no other + great way to detect this. */ #if CHECKING_P int importedness; /* Checker that imports not occurring inappropriately. +ve imports ok, @@ -3263,7 +3266,7 @@ trees_out::trees_out (allocator *mem, module_state *state, depset::hash &deps, unsigned section) :parent (mem), state (state), tree_map (500), dep_hash (&deps), ref_num (0), section (section), - writing_local_entities (false) + writing_local_entities (false), walking_bit_field_unit (false) { #if CHECKING_P importedness = 0; @@ -6512,7 +6515,10 @@ trees_out::core_vals (tree t) case FIELD_DECL: WT (t->field_decl.offset); WT (t->field_decl.bit_field_type); - WT (t->field_decl.qualifier); /* bitfield unit. */ + { + auto ovr = make_temp_override (walking_bit_field_unit, true); + WT (t->field_decl.qualifier); /* bitfield unit. */ + } WT (t->field_decl.bit_offset); WT (t->field_decl.fcontext); WT (t->decl_common.initial); @@ -11272,15 +11278,16 @@ trees_out::get_merge_kind (tree decl, depset *dep) return MK_named; } - if (!DECL_NAME (decl) - && !RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)) - && !DECL_BIT_FIELD_REPRESENTATIVE (decl)) + if (walking_bit_field_unit) { /* The underlying storage unit for a bitfield. We do not need to dedup it, because it's only reachable through the bitfields it represents. And those are deduped. */ // FIXME: Is that assertion correct -- do we ever fish it // out and put it in an expr? + gcc_checking_assert (!DECL_NAME (decl) + && !RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)) + && !DECL_BIT_FIELD_REPRESENTATIVE (decl)); gcc_checking_assert ((TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE ? TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) : TREE_CODE (TREE_TYPE (decl)))