Hello again, This is part one of a patchset to add an optional warning for long distance (cross module) friendship when the friendship has no useful/sensical meaning.
Attached is a patch to error when trying to define a member function of a type owned by a different module. This also fixes an issue where a friend decl lets a user define a function owned by a different module. 2020-08-14 Jeff Chapman II <jchap...@lock3software.com> gcc/cp/ * decl.c (duplicate_decls): Return original decl when attempting to redeclare a function owned by another module instead of clobbering the original decl. (grokfndecl): Error on member declarations of types owned by another module. gcc/testsuite/ * g++.dg/modules/redecl-1_[ab].C: New test. * g++.dg/modules/redecl-2_[ab].C: Ditto. * g++.dg/modules/redecl-3_[ab].C: Ditto. Please let me know if there are any questions, Jeff Chapman II
From fc95c562ec87520f66388a35009649c4b020a843 Mon Sep 17 00:00:00 2001 From: Jeff Chapman II <jchap...@lock3software.com> Date: Thu, 19 Dec 2019 09:43:16 -0500 Subject: [PATCH 1/2] c++: Fix cross module member redecl 2020-08-14 Jeff Chapman II <jchap...@lock3software.com> gcc/cp/ * decl.c (duplicate_decls): Return original decl when attempting to redeclare a function owned by another module instead of clobbering the original decl. (grokfndecl): Error on member declarations of types owned by another module. gcc/testsuite/ * g++.dg/modules/redecl-1_[ab].C: New test. * g++.dg/modules/redecl-2_[ab].C: Ditto. * g++.dg/modules/redecl-3_[ab].C: Ditto. --- gcc/cp/decl.c | 14 ++++++++++++++ gcc/testsuite/g++.dg/modules/redecl-1_a.C | 9 +++++++++ gcc/testsuite/g++.dg/modules/redecl-1_b.C | 8 ++++++++ gcc/testsuite/g++.dg/modules/redecl-2_a.C | 10 ++++++++++ gcc/testsuite/g++.dg/modules/redecl-2_b.C | 7 +++++++ gcc/testsuite/g++.dg/modules/redecl-3_a.C | 6 ++++++ gcc/testsuite/g++.dg/modules/redecl-3_b.C | 13 +++++++++++++ 7 files changed, 67 insertions(+) create mode 100644 gcc/testsuite/g++.dg/modules/redecl-1_a.C create mode 100644 gcc/testsuite/g++.dg/modules/redecl-1_b.C create mode 100644 gcc/testsuite/g++.dg/modules/redecl-2_a.C create mode 100644 gcc/testsuite/g++.dg/modules/redecl-2_b.C create mode 100644 gcc/testsuite/g++.dg/modules/redecl-3_a.C create mode 100644 gcc/testsuite/g++.dg/modules/redecl-3_b.C diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index decd58791ae..e8637dac7eb 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2031,6 +2031,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) } } } + /* FIXME Is there a better place to handle this? Without this, we end up + * potentially merging a decl owned by a separate module with a friend decl + * injected in the current module (see modules/redecl-3). Returning olddecl + * relies on code higher up handling the issue. */ + else if (modules_p () && !module_may_redeclare (olddecl)) + return olddecl; /* We have committed to returning OLDDECL at this point. */ @@ -9517,6 +9523,14 @@ grokfndecl (tree ctype, if (TREE_CODE (type) == METHOD_TYPE) { + if (modules_p() + && !module_may_redeclare (TYPE_NAME (ctype))) + { + error_at (location, "declaration conflicts with import"); + inform (location_of (ctype), "import declared %q#T here", ctype); + return NULL_TREE; + } + tree parm = build_this_parm (decl, type, quals); DECL_CHAIN (parm) = parms; parms = parm; diff --git a/gcc/testsuite/g++.dg/modules/redecl-1_a.C b/gcc/testsuite/g++.dg/modules/redecl-1_a.C new file mode 100644 index 00000000000..2646adf8327 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/redecl-1_a.C @@ -0,0 +1,9 @@ +// { dg-additional-options -fmodules-ts } +export module foo; +// { dg-module-cmi foo } + +export struct Foo +{ + int foo(); +}; + diff --git a/gcc/testsuite/g++.dg/modules/redecl-1_b.C b/gcc/testsuite/g++.dg/modules/redecl-1_b.C new file mode 100644 index 00000000000..b980bfe290c --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/redecl-1_b.C @@ -0,0 +1,8 @@ +// { dg-additional-options -fmodules-ts } +import foo; + +int Foo::foo() // { dg-error "conflicts with import" } +{ + return 1; +} + diff --git a/gcc/testsuite/g++.dg/modules/redecl-2_a.C b/gcc/testsuite/g++.dg/modules/redecl-2_a.C new file mode 100644 index 00000000000..eea99f2024e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/redecl-2_a.C @@ -0,0 +1,10 @@ +// { dg-additional-options -fmodules-ts } +export module foo; +// { dg-module-cmi foo } + +export struct Foo +{ + int foo(); + friend class Bar; +}; + diff --git a/gcc/testsuite/g++.dg/modules/redecl-2_b.C b/gcc/testsuite/g++.dg/modules/redecl-2_b.C new file mode 100644 index 00000000000..9c3b545f6d2 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/redecl-2_b.C @@ -0,0 +1,7 @@ +// { dg-additional-options -fmodules-ts } +import foo; + +struct Bar // { dg-error "cannot declare.*in a different module" } +{ +}; + diff --git a/gcc/testsuite/g++.dg/modules/redecl-3_a.C b/gcc/testsuite/g++.dg/modules/redecl-3_a.C new file mode 100644 index 00000000000..17993d26ef3 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/redecl-3_a.C @@ -0,0 +1,6 @@ +// { dg-additional-options -fmodules-ts } +export module foo; +// { dg-module-cmi foo } + +export int foo(); + diff --git a/gcc/testsuite/g++.dg/modules/redecl-3_b.C b/gcc/testsuite/g++.dg/modules/redecl-3_b.C new file mode 100644 index 00000000000..35efe7b1d37 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/redecl-3_b.C @@ -0,0 +1,13 @@ +// { dg-additional-options "-fmodules-ts" } +import foo; + +struct Bar +{ + friend int foo(); +}; + +int foo() // { dg-error "conflicts with import" } +{ + return 0; +} + -- 2.27.0