On 3/7/26 8:21 AM, Nathaniel Shead wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
OK.
-- >8 -- In a modules scenario, when we bail out of begin_class_definition due to an error in module_may_redeclare, we return error_mark_node but had already started building the class definition. When we re-enter cp_parser_class_head we then successfully reach xref_basetypes, where we then crash because the binfo slot is non-null. This fixes the issue by moving the module_may_redeclare check earlier, to before we call xref_basetypes, so that we don't start building the definition if we were going to bail anyway. As a side effect this also moves the check to before we update the DECL_SOURCE_LOCATION of the type to the start of the class head, so that when we complain about mismatched attachment we can point to the imported declaration rather than referring to ourselves again. gcc/cp/ChangeLog: * semantics.cc (begin_class_definition): Move module_may_redeclare check to... * parser.cc (cp_parser_class_head): ...here. gcc/testsuite/ChangeLog: * g++.dg/modules/class-13_a.C: New test. * g++.dg/modules/class-13_b.C: New test. Signed-off-by: Nathaniel Shead <[email protected]> --- gcc/cp/parser.cc | 12 ++++++++++++ gcc/cp/semantics.cc | 8 -------- gcc/testsuite/g++.dg/modules/class-13_a.C | 7 +++++++ gcc/testsuite/g++.dg/modules/class-13_b.C | 6 ++++++ 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/class-13_a.C create mode 100644 gcc/testsuite/g++.dg/modules/class-13_b.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 53fbb75b15a..bb17d204734 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -30624,6 +30624,18 @@ cp_parser_class_head (cp_parser* parser, if (type && type != error_mark_node) start_lambda_scope (TYPE_NAME (type));+ /* Check that it's valid to declare this type here. */+ if (modules_p () && type) + { + if (module_may_redeclare (TYPE_NAME (type))) + { + set_instantiating_module (TYPE_NAME (type)); + set_defining_module (TYPE_NAME (type)); + } + else + type = NULL_TREE; + } + /* We will have entered the scope containing the class; the names of base classes should be looked up in that context. For example:diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.ccindex 4aa2f14b468..ac08b598f3d 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -4207,14 +4207,6 @@ begin_class_definition (tree t) pushtag (TYPE_IDENTIFIER (t), t); }- if (modules_p ())- { - if (!module_may_redeclare (TYPE_NAME (t))) - return error_mark_node; - set_instantiating_module (TYPE_NAME (t)); - set_defining_module (TYPE_NAME (t)); - } - maybe_process_partial_specialization (t); pushclass (t); TYPE_BEING_DEFINED (t) = 1; diff --git a/gcc/testsuite/g++.dg/modules/class-13_a.C b/gcc/testsuite/g++.dg/modules/class-13_a.C new file mode 100644 index 00000000000..f60906bcd34 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/class-13_a.C @@ -0,0 +1,7 @@ +// { dg-additional-options "-fmodules" } +// { dg-module-cmi M } + +export module M; +export struct S { + struct X; +}; diff --git a/gcc/testsuite/g++.dg/modules/class-13_b.C b/gcc/testsuite/g++.dg/modules/class-13_b.C new file mode 100644 index 00000000000..b4417247b51 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/class-13_b.C @@ -0,0 +1,6 @@ +// { dg-additional-options "-fmodules" } + +import M; +struct S::X {}; // { dg-error "in global module conflicts with import" } +struct S::X {}; // { dg-error "in global module conflicts with import" } +// { dg-regexp {[^\n]*class-13_a.C:6:10: note: import declared attached to module 'M'\n} }
