Regtested and bootstrapped on x86_64-pc-linux-gnu.
Should the test case be split up?
Also, for some reason we only get diagnostics correctly after c++20. I'd
expect that it should work for c++98 onward, but no error is reported so
i kept the test in c++20.
-- >8 --
When a partial specialization was redeclared with different template
parameters, maybe_new_partial_specialization was incorrectly treating it
as the same specialization by only comparing template argument lists
without comparing template-heads. This caused an ICE when the
redeclaration had different template parameters.
Per [temp.spec.partial.general]/2, two partial specializations declare
the same entity only if they have equivalent template-heads and
template argument lists.
Fix by comparing template parameter lists (template-heads) in addition
to template argument lists when checking for existing specializations.
PR c++/122958
gcc/cp/ChangeLog:
* pt.cc (maybe_new_partial_specialization): Compare template
parameter lists when checking for existing specializations.
gcc/testsuite/ChangeLog:
* g++.dg/template/partial-spec-redecl.C: New test.
Signed-off-by: Egas Ribeiro <[email protected]>
---
gcc/cp/pt.cc | 7 ++++++-
.../g++.dg/cpp2a/partial-spec-redecl.C | 19 +++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/partial-spec-redecl.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ae7429b449c..9277c377c37 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -979,7 +979,12 @@ maybe_new_partial_specialization (tree& type)
tree spec_tmpl = TREE_VALUE (specs);
tree spec_args = TREE_PURPOSE (specs);
tree spec_constr = get_constraints (spec_tmpl);
- if (comp_template_args (args, spec_args)
+ tree spec_parms = DECL_TEMPLATE_PARMS (spec_tmpl);
+ /* Per [temp.spec.partial.general]/2, two partial specializations
+ declare the same entity if they have equivalent template-heads
+ and template argument lists. */
+ if (comp_template_args (args, spec_args)
+ && comp_template_parms (spec_parms, current_template_parms)
&& equivalent_constraints (type_constr, spec_constr))
{
type = TREE_TYPE (spec_tmpl);
diff --git a/gcc/testsuite/g++.dg/cpp2a/partial-spec-redecl.C
b/gcc/testsuite/g++.dg/cpp2a/partial-spec-redecl.C
new file mode 100644
index 00000000000..3d2805e478e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/partial-spec-redecl.C
@@ -0,0 +1,19 @@
+// PR c++/122958
+// { dg-do compile { target c++20 } }
+template <class>
+class C;
+
+template <class R, class... S>
+class C<R(S...)>;
+
+template <class R, class... S, class RC = void>
+class C<R(S...)> {}; // { dg-error "default template arguments may not be
used | template parameters not deducible" }
+
+template <class>
+class D;
+
+template <class R, class S>
+class D<R(S)>;
+
+template <class R, class S, class Extra>
+class D<R(S)> {}; // { dg-error "template parameters not deducible" }
--
2.52.0