Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk/15? -- >8 --
We were erroring because the TEMPLATE_DECL of the existing partial specialisation has an undeduced return type, but the imported declaration did not. The root cause is similar to what was fixed in r13-2744-g4fac53d6522189, where modules streaming code assumes that a TEMPLATE_DECL and its DECL_TEMPLATE_RESULT will always have the same TREE_TYPE. That commit fixed the issue by ensuring that when the type of a variable is deduced the TEMPLATE_DECL is updated as well, but this missed handling partial specialisations. However, I don't think we actually care about that, since it seems that only the type of the inner decl actually matters in practice. Instead, this patch handles the issue on the modules side when deduping a streamed decl, by only comparing the inner type. PR c++/120644 gcc/cp/ChangeLog: * decl.cc (cp_finish_decl): Remove workaround. * module.cc (trees_in::is_matching_decl): Only compare types of inner decls. Clarify function return type deduction should only occur for non-TEMPLATE_DECL. gcc/testsuite/ChangeLog: * g++.dg/modules/auto-7.h: New test. * g++.dg/modules/auto-7_a.H: New test. * g++.dg/modules/auto-7_b.C: New test. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> --- gcc/cp/decl.cc | 6 ------ gcc/cp/module.cc | 5 +++-- gcc/testsuite/g++.dg/modules/auto-7.h | 12 ++++++++++++ gcc/testsuite/g++.dg/modules/auto-7_a.H | 5 +++++ gcc/testsuite/g++.dg/modules/auto-7_b.C | 5 +++++ 5 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/auto-7.h create mode 100644 gcc/testsuite/g++.dg/modules/auto-7_a.H create mode 100644 gcc/testsuite/g++.dg/modules/auto-7_b.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index febdc89f89d..150d26079a8 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8921,12 +8921,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* Now that we have a type, try these again. */ layout_decl (decl, 0); cp_apply_type_quals_to_decl (cp_type_quals (type), decl); - - /* Update the type of the corresponding TEMPLATE_DECL to match. */ - if (DECL_LANG_SPECIFIC (decl) - && DECL_TEMPLATE_INFO (decl) - && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) == decl) - TREE_TYPE (DECL_TI_TEMPLATE (decl)) = type; } if (ensure_literal_type_for_constexpr_object (decl) == error_mark_node) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index c99988da05b..606eac77db9 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -12193,7 +12193,8 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) { dump (dumper::MERGE) && dump ("Propagating deduced return type to %N", existing); - FNDECL_USED_AUTO (e_inner) = true; + gcc_checking_assert (existing == e_inner); + FNDECL_USED_AUTO (existing) = true; DECL_SAVED_AUTO_RETURN_TYPE (existing) = TREE_TYPE (e_type); TREE_TYPE (existing) = change_return_type (TREE_TYPE (d_type), e_type); } @@ -12248,7 +12249,7 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) /* Using cp_tree_equal because we can meet TYPE_ARGUMENT_PACKs here. I suspect the entities that directly do that are things that shouldn't go to duplicate_decls (FIELD_DECLs etc). */ - else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing))) + else if (!cp_tree_equal (TREE_TYPE (d_inner), TREE_TYPE (e_inner))) { mismatch_msg = G_("conflicting type for imported declaration %#qD"); mismatch: diff --git a/gcc/testsuite/g++.dg/modules/auto-7.h b/gcc/testsuite/g++.dg/modules/auto-7.h new file mode 100644 index 00000000000..324b60cfa0a --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-7.h @@ -0,0 +1,12 @@ +// PR c++/120644 + +enum class E { E0, E1 }; + +template <typename T> +constexpr auto fmt_kind = E::E0; + +template <typename T> +class opt{}; + +template <typename T> +constexpr auto fmt_kind<opt<T>> = E::E1; diff --git a/gcc/testsuite/g++.dg/modules/auto-7_a.H b/gcc/testsuite/g++.dg/modules/auto-7_a.H new file mode 100644 index 00000000000..40cb0f886c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-7_a.H @@ -0,0 +1,5 @@ +// PR c++/120644 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +#include "auto-7.h" diff --git a/gcc/testsuite/g++.dg/modules/auto-7_b.C b/gcc/testsuite/g++.dg/modules/auto-7_b.C new file mode 100644 index 00000000000..c6ad37fd828 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-7_b.C @@ -0,0 +1,5 @@ +// PR c++/120644 +// { dg-additional-options "-fmodules -fno-module-lazy" } + +#include "auto-7.h" +import "auto-7_a.H"; -- 2.47.0