Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >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.cc
index 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} }
-- 
2.51.0

Reply via email to