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