On 6/23/25 5:41 PM, Nathaniel Shead wrote:
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.

Hmm, if we aren't going to try to keep the type of the TEMPLATE_DECL correct, maybe we should always set it to NULL_TREE to make sure we only look at the inner type.

The rest of the patch is OK.

        * 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";

Reply via email to