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