While testing the fix for PR124311 I noticed that we are missing a
diagnostic for this case.

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

-- >8 --

We had missed checking whether we were doing an (outside class)
declaration of a member attached to the wrong module.  This patch adds
those checks.

Within duplicate_decls/maybe_module_redeclare there's not a nice way to
do this because the attachment of a member is always calculated based on
the attachment of its owning type, which defeats the purpose here.
Instead I added the checks to start_decl where we do other various
checks for if a redeclaration of a class member is legal.

gcc/cp/ChangeLog:

        * decl.cc (start_decl): Check for module_may_redeclare for class
        members.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/class-12_a.C: New test.
        * g++.dg/modules/class-12_b.C: New test.
        * g++.dg/modules/class-12_c.C: New test.

Signed-off-by: Nathaniel Shead <[email protected]>
---
 gcc/cp/decl.cc                            | 14 ++++++++++---
 gcc/testsuite/g++.dg/modules/class-12_a.C | 25 +++++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/class-12_b.C | 23 +++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/class-12_c.C | 22 ++++++++++++++++++++
 4 files changed, 81 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/class-12_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/class-12_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/class-12_c.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 6b210a30b6a..945584cd7ce 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6693,6 +6693,10 @@ start_decl (const cp_declarator *declarator,
                               context, DECL_NAME (decl));
                  DECL_CONTEXT (decl) = DECL_CONTEXT (field);
                }
+
+             if (modules_p () && !module_may_redeclare (field))
+               return error_mark_node;
+
              /* Static data member are tricky; an in-class initialization
                 still doesn't provide a definition, so the in-class
                 declaration will have DECL_EXTERNAL set, but will have an
@@ -6713,9 +6717,13 @@ start_decl (const cp_declarator *declarator,
                                      this_tmpl
                                      ? current_template_parms
                                      : NULL_TREE);
-         if (field && field != error_mark_node
-             && duplicate_decls (decl, field))
-           decl = field;
+         if (field && field != error_mark_node)
+           {
+             if (modules_p () && !module_may_redeclare (field))
+               return error_mark_node;
+             if (duplicate_decls (decl, field))
+               decl = field;
+           }
        }
 
       /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set.  */
diff --git a/gcc/testsuite/g++.dg/modules/class-12_a.C 
b/gcc/testsuite/g++.dg/modules/class-12_a.C
new file mode 100644
index 00000000000..cc0f7a6ecc6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-12_a.C
@@ -0,0 +1,25 @@
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+
+export extern "C++" struct Global {
+  Global();
+  Global(const Global&);
+  Global(int);
+  Global(double);
+  void foo();
+  void bar();
+  static int x;
+  static int y;
+};
+export struct Module {
+  Module();
+  Module(const Module&);
+  Module(int);
+  Module(double);
+  void foo();
+  void bar();
+  static int x;
+  static int y;
+};
diff --git a/gcc/testsuite/g++.dg/modules/class-12_b.C 
b/gcc/testsuite/g++.dg/modules/class-12_b.C
new file mode 100644
index 00000000000..7fb73c34135
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-12_b.C
@@ -0,0 +1,23 @@
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi !X }
+
+export module X;
+import M;
+
+             Global::Global() = default;               // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" Global::Global(const Global&) = default;
+             Global::Global(int) {}                    // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" Global::Global(double) {}
+             void Global::foo() {}                     // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" void Global::bar() {}
+             int Global::x = 123;                      // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" int Global::y = 123;
+
+             Module::Module() = default;               // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" Module::Module(const Module&) = default;  // { dg-error "in 
global module conflicts with import" }
+             Module::Module(int) {}                    // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" Module::Module(double) {}                 // { dg-error "in 
global module conflicts with import" }
+             void Module::foo() {}                     // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" void Module::bar() {}                     // { dg-error "in 
global module conflicts with import" }
+             int Module::x = 123;                      // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" int Module::y = 123;                      // { dg-error "in 
global module conflicts with import" }
diff --git a/gcc/testsuite/g++.dg/modules/class-12_c.C 
b/gcc/testsuite/g++.dg/modules/class-12_c.C
new file mode 100644
index 00000000000..c6bfc760e5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/class-12_c.C
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fmodules" }
+
+module M:part;
+import M;
+
+             Global::Global() = default;               // { dg-error "in 
module .M. conflicts with import" }
+extern "C++" Global::Global(const Global&) = default;
+             Global::Global(int) {}                    // { dg-error "in 
module .M. conflicts with import" }
+extern "C++" Global::Global(double) {}
+             void Global::foo() {}                     // { dg-error "in 
module .M. conflicts with import" }
+extern "C++" void Global::bar() {}
+             int Global::x = 123;                      // { dg-error "in 
module .X. conflicts with import" }
+extern "C++" int Global::y = 123;
+
+             Module::Module() = default;
+extern "C++" Module::Module(const Module&) = default;  // { dg-error "in 
global module conflicts with import" }
+             Module::Module(int) {}
+extern "C++" Module::Module(double) {}                 // { dg-error "in 
global module conflicts with import" }
+             void Module::foo() {}
+extern "C++" void Module::bar() {}                     // { dg-error "in 
global module conflicts with import" }
+             int Module::x = 123;
+extern "C++" int Module::y = 123;                      // { dg-error "in 
global module conflicts with import" }
-- 
2.51.0

Reply via email to