https://gcc.gnu.org/g:488c997aeb6669c333287a1f0063ce5fb706a8b5

commit r15-9690-g488c997aeb6669c333287a1f0063ce5fb706a8b5
Author: Patrick Palka <ppa...@redhat.com>
Date:   Thu May 15 11:07:53 2025 -0400

    c++: unifying specializations of non-primary tmpls [PR120161]
    
    Here unification of P=Wrap<int>::type, A=Wrap<long>::type wrongly
    succeeds ever since r14-4112 which made the RECORD_TYPE case of unify
    no longer recurse into template arguments for non-primary templates
    (since they're a non-deduced context) and so the int/long mismatch that
    makes the two types distinct goes unnoticed.
    
    In the case of (comparing specializations of) a non-primary template,
    unify should still go on to compare the types directly before returning
    success.
    
            PR c++/120161
    
    gcc/cp/ChangeLog:
    
            * pt.cc (unify) <case RECORD_TYPE>: When comparing specializations
            of a non-primary template, still perform a type comparison.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/unify13.C: New test.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>
    (cherry picked from commit 0c430503f2849ebb20105695b8ad40d43d797c7b)

Diff:
---
 gcc/cp/pt.cc                            |  6 +++---
 gcc/testsuite/g++.dg/template/unify13.C | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 96230b444c01..be9af50f44f8 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -25797,10 +25797,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
                          INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
                          INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (t)),
                          UNIFY_ALLOW_NONE, explain_p);
-         else
-           return unify_success (explain_p);
+         gcc_checking_assert (t == arg);
        }
-      else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
+
+      if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
        return unify_type_mismatch (explain_p, parm, arg);
       return unify_success (explain_p);
 
diff --git a/gcc/testsuite/g++.dg/template/unify13.C 
b/gcc/testsuite/g++.dg/template/unify13.C
new file mode 100644
index 000000000000..ec7ca9d17a44
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/unify13.C
@@ -0,0 +1,18 @@
+// PR c++/120161
+
+template<class T, class U>
+struct mp_list { };
+
+template<class T>
+struct Wrap { struct type { }; };
+
+struct A : mp_list<Wrap<int>::type, void>
+         , mp_list<Wrap<long>::type, void> { };
+
+template<class U>
+void f(mp_list<Wrap<int>::type, U>*);
+
+int main() {
+  A a;
+  f(&a);
+}

Reply via email to