Bootstrapped and regtested (so far just dg.exp and modules.exp) on
x86_64-pc-linux-gnu, OK for trunk if full regtest succeeds?

Rather than updating copy_fndecl_with_name, we could also just fix
modules specifically by overwriting DECL_ABSTRACT_P before calling
build_cdtor_clones in trees_in::decl_value, or by forcing it to 0 for
DECL_MAYBE_IN_CHARGE_CDTOR during tree streaming, if you prefer, since
it'll always be set again by expand_or_defer_fn anyway.

-- >8 --

This patch makes some adjustments required to get a simple modules
testcase working with LTO.  There are two main issues fixed.

Firstly, modules only streams the maybe-in-charge constructor, and any
clones are recreated on stream-in.  These clones are copied from the
existing function decl and then adjusted.  This caused issues because
the clones were getting incorrectly marked as abstract, since after
clones have been created (in the imported file) the maybe-in-charge decl
gets marked as abstract.  So this patch just ensures that clones are
always created as non-abstract.

The second issue is that we need to explicitly tell cgraph that explicit
instantiations need to be emitted, otherwise LTO will elide them (as
they don't necessarily appear to be used directly) and cause link
errors.  Additionally, expand_or_defer_fn doesn't setup comdat groups
for explicit instantiations, so we need to do that here as well.

        PR c++/118961

gcc/cp/ChangeLog:

        * class.cc (copy_fndecl_with_name): Mark clones as non-abstract.
        * module.cc (trees_in::read_var_def): Explicit instantiation
        definitions of variables must be emitted, and are COMDAT.
        (module_state::read_cluster): Likewise for functions.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/lto-1_a.H: New test.
        * g++.dg/modules/lto-1_b.C: New test.
        * g++.dg/modules/lto-2_a.H: New test.
        * g++.dg/modules/lto-2_b.C: New test.
        * g++.dg/modules/lto-3_a.H: New test.
        * g++.dg/modules/lto-3_b.C: New test.

Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
---
 gcc/cp/class.cc                        |  1 +
 gcc/cp/module.cc                       | 17 +++++++++++++++++
 gcc/testsuite/g++.dg/modules/lto-1_a.H |  9 +++++++++
 gcc/testsuite/g++.dg/modules/lto-1_b.C |  9 +++++++++
 gcc/testsuite/g++.dg/modules/lto-2_a.H | 11 +++++++++++
 gcc/testsuite/g++.dg/modules/lto-2_b.C |  9 +++++++++
 gcc/testsuite/g++.dg/modules/lto-3_a.H |  6 ++++++
 gcc/testsuite/g++.dg/modules/lto-3_b.C | 10 ++++++++++
 8 files changed, 72 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/modules/lto-1_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/lto-1_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/lto-2_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/lto-2_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/lto-3_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/lto-3_b.C

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index d5ae69b0fdf..2b694b98e56 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5169,6 +5169,7 @@ copy_fndecl_with_name (tree fn, tree name, tree_code code,
       set_constraints (clone, copy_node (ci));
 
   SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE);
+  DECL_ABSTRACT_P (clone) = false;
   /* There's no pending inline data for this function.  */
   DECL_PENDING_INLINE_INFO (clone) = NULL;
   DECL_PENDING_INLINE_P (clone) = 0;
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 2cded878c64..f9f48bb2421 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12684,6 +12684,13 @@ trees_in::read_var_def (tree decl, tree maybe_template)
          if (maybe_dup && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P 
(maybe_dup))
            DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
          tentative_decl_linkage (decl);
+         if (DECL_EXPLICIT_INSTANTIATION (decl)
+             && !DECL_EXTERNAL (decl))
+           {
+             mark_needed (decl);
+             if (TREE_PUBLIC (decl))
+               maybe_make_one_only (decl);
+           }
          if (DECL_IMPLICIT_INSTANTIATION (decl)
              || (DECL_EXPLICIT_INSTANTIATION (decl)
                  && !DECL_EXTERNAL (decl))
@@ -16604,6 +16611,16 @@ module_state::read_cluster (unsigned snum)
       cfun->language->returns_abnormally = pdata.returns_abnormally;
       cfun->language->infinite_loop = pdata.infinite_loop;
 
+      /* Make sure we emit explicit instantiations.  */
+      if (!abstract
+         && DECL_EXPLICIT_INSTANTIATION (decl)
+         && !DECL_EXTERNAL (decl))
+       {
+         mark_needed (decl);
+         if (TREE_PUBLIC (decl))
+           maybe_make_one_only (decl);
+       }
+
       if (abstract)
        ;
       else if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
diff --git a/gcc/testsuite/g++.dg/modules/lto-1_a.H 
b/gcc/testsuite/g++.dg/modules/lto-1_a.H
new file mode 100644
index 00000000000..f28e1fdce03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lto-1_a.H
@@ -0,0 +1,9 @@
+// PR c++/118961
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+// Test explicit instantiations get emitted with LTO
+
+template <typename> struct S {
+  S() {}
+};
+template struct S<char>;
diff --git a/gcc/testsuite/g++.dg/modules/lto-1_b.C 
b/gcc/testsuite/g++.dg/modules/lto-1_b.C
new file mode 100644
index 00000000000..d63f0ff7fe5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lto-1_b.C
@@ -0,0 +1,9 @@
+// PR c++/118961
+// { dg-module-do link }
+// { dg-require-effective-target lto }
+// { dg-additional-options "-fmodules -flto" }
+
+import "lto-1_a.H";
+
+S<char> s;
+int main() {}
diff --git a/gcc/testsuite/g++.dg/modules/lto-2_a.H 
b/gcc/testsuite/g++.dg/modules/lto-2_a.H
new file mode 100644
index 00000000000..f817329b564
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lto-2_a.H
@@ -0,0 +1,11 @@
+// PR c++/118961
+// { dg-additional-options "-fmodule-header -std=c++20" }
+// { dg-module-cmi {} }
+// Test we correctly emit the bodies of cloned constructors.
+
+template <typename>
+struct S {
+  S() requires true {}
+};
+
+inline S<int> foo() { return {}; }
diff --git a/gcc/testsuite/g++.dg/modules/lto-2_b.C 
b/gcc/testsuite/g++.dg/modules/lto-2_b.C
new file mode 100644
index 00000000000..340ff48141f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lto-2_b.C
@@ -0,0 +1,9 @@
+// PR c++/118961
+// { dg-module-do link }
+// { dg-require-effective-target lto }
+// { dg-additional-options "-fmodules -flto -std=c++20" }
+
+import "lto-2_a.H";
+int main() {
+  foo();
+}
diff --git a/gcc/testsuite/g++.dg/modules/lto-3_a.H 
b/gcc/testsuite/g++.dg/modules/lto-3_a.H
new file mode 100644
index 00000000000..be63699e66f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lto-3_a.H
@@ -0,0 +1,6 @@
+// PR c++/118961
+// { dg-additional-options "-fmodule-header -std=c++20" }
+// { dg-module-cmi {} }
+// We shouldn't ICE when linking against the standard library.
+
+#include <string>
diff --git a/gcc/testsuite/g++.dg/modules/lto-3_b.C 
b/gcc/testsuite/g++.dg/modules/lto-3_b.C
new file mode 100644
index 00000000000..f459596f730
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lto-3_b.C
@@ -0,0 +1,10 @@
+// PR c++/118961
+// { dg-module-do link }
+// { dg-require-effective-target lto }
+// { dg-additional-options "-fmodules -flto -static -std=c++20" }
+
+import "lto-3_a.H";
+
+int main() {
+  std::string m_message;
+}
-- 
2.47.0

Reply via email to