[gcc r16-1759] c++/modules: Ensure type of partial spec VAR_DECL is consistent with its template [PR120644]
Nathaniel Shead
nshead@gcc.gnu.org
Sat Jun 28 14:53:05 GMT 2025
https://gcc.gnu.org/g:98fd493db6216cff11142c9dc477a3ff8e4269fa
commit r16-1759-g98fd493db6216cff11142c9dc477a3ff8e4269fa
Author: Nathaniel Shead <nathanieloshead@gmail.com>
Date: Mon Jun 23 22:24:22 2025 +1000
c++/modules: Ensure type of partial spec VAR_DECL is consistent with its template [PR120644]
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 missed handling partial
specialisations. This patch ensures that the same adjustment is made
there as well.
PR c++/120644
gcc/cp/ChangeLog:
* decl.cc (cp_finish_decl): Also propagate type to partial
templates.
* module.cc (trees_out::decl_value): Add assertion that the
TREE_TYPE of a streamed template decl matches its inner.
(trees_in::is_matching_decl): Clarify function return type
deduction should only occur for non-TEMPLATE_DECL.
* pt.cc (template_for_substitution): Handle partial specs.
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 <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Diff:
---
gcc/cp/decl.cc | 10 ++++++----
gcc/cp/module.cc | 7 ++++++-
gcc/cp/pt.cc | 4 ++++
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 +++++
6 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 4fe97ffbf8f9..83c8e283b56a 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8923,10 +8923,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
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 (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
+ {
+ tree tmpl = template_for_substitution (decl);
+ if (DECL_TEMPLATE_RESULT (tmpl) == decl)
+ TREE_TYPE (tmpl) = 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 42a1b83e1643..846e532c4380 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8213,6 +8213,10 @@ trees_out::decl_value (tree decl, depset *dep)
inner = DECL_TEMPLATE_RESULT (decl);
inner_tag = insert (inner, WK_value);
+ /* On stream-in we assume that a template and its result will
+ have the same type. */
+ gcc_checking_assert (TREE_TYPE (decl) == TREE_TYPE (inner));
+
if (streaming_p ())
{
int code = TREE_CODE (inner);
@@ -12325,7 +12329,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);
}
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c7a0066a11ac..3362a6f8f9ca 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27537,6 +27537,10 @@ tree
template_for_substitution (tree decl)
{
tree tmpl = DECL_TI_TEMPLATE (decl);
+ if (VAR_P (decl))
+ if (tree partial = most_specialized_partial_spec (decl, tf_none))
+ if (partial != error_mark_node)
+ tmpl = TI_TEMPLATE (partial);
/* Set TMPL to the template whose DECL_TEMPLATE_RESULT is the pattern
for the instantiation. This is not always the most general
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 000000000000..324b60cfa0ae
--- /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 000000000000..40cb0f886c08
--- /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 000000000000..c6ad37fd8284
--- /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";
More information about the Gcc-cvs
mailing list