commit ecd071290cad1fcfb33eee3889f94dd1e9374b24 Author: Jason Merrill Date: Fri Jun 16 13:10:53 2017 -0400 PR c++/81102 - Wrong error with partial specialization. * pt.c (unify) [TEMPLATE_PARM_INDEX]: Strip reference when comparing types. Do type deduction later. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b055507..8c6499f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -20632,18 +20632,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, return x; } - if (cxx_dialect >= cxx1z - /* We deduce from array bounds in try_array_deduction. */ - && !(strict & UNIFY_ALLOW_INTEGER) - && uses_template_parms (TREE_TYPE (parm)) - && !type_uses_auto (TREE_TYPE (parm))) - { - tree atype = TREE_TYPE (arg); - RECUR_AND_CHECK_FAILURE (tparms, targs, - TREE_TYPE (parm), atype, - UNIFY_ALLOW_NONE, explain_p); - } - /* [temp.deduct.type] If, in the declaration of a function template with a non-type template-parameter, the non-type template-parameter is used in an expression in the function @@ -20664,7 +20652,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* Template-parameter dependent expression. Just accept it for now. It will later be processed in convert_template_argument. */ ; - else if (same_type_p (TREE_TYPE (arg), tparm)) + else if (same_type_p (non_reference (TREE_TYPE (arg)), + non_reference (tparm))) /* OK */; else if ((strict & UNIFY_ALLOW_INTEGER) && CP_INTEGRAL_TYPE_P (tparm)) @@ -20673,9 +20662,22 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, corresponding parameter. */ arg = fold (build_nop (tparm, arg)); else if (uses_template_parms (tparm)) - /* We haven't deduced the type of this parameter yet. Try again - later. */ - return unify_success (explain_p); + { + /* We haven't deduced the type of this parameter yet. */ + if (cxx_dialect >= cxx1z + /* We deduce from array bounds in try_array_deduction. */ + && !(strict & UNIFY_ALLOW_INTEGER)) + { + /* Deduce it from the non-type argument. */ + tree atype = TREE_TYPE (arg); + RECUR_AND_CHECK_FAILURE (tparms, targs, + tparm, atype, + UNIFY_ALLOW_NONE, explain_p); + } + else + /* Try again later. */ + return unify_success (explain_p); + } else return unify_type_mismatch (explain_p, tparm, TREE_TYPE (arg)); diff --git a/gcc/testsuite/g++.dg/template/partial-specialization7.C b/gcc/testsuite/g++.dg/template/partial-specialization7.C new file mode 100644 index 0000000..aa42191 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial-specialization7.C @@ -0,0 +1,40 @@ +// PR c++/81102 + +template +struct HelperWrapper; + +// [...] + +template +struct HelperWrapper +{ + static inline int WrapFuncT(const int) + { + return 0; // Changed + } +}; + +// Unary +template +struct HelperWrapper +{ + static inline int WrapFuncT(const int) + { + return 1; // Changed + } +}; + +// Binary +template +struct HelperWrapper +{ + static inline int WrapFuncT(const int) + { + return 2; // Changed + } +}; + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/g++.dg/template/partial5.C b/gcc/testsuite/g++.dg/template/partial5.C index 1b56fb3..ee45a93 100644 --- a/gcc/testsuite/g++.dg/template/partial5.C +++ b/gcc/testsuite/g++.dg/template/partial5.C @@ -14,7 +14,7 @@ template struct Y { }; template -struct Y { }; // { dg-error "" } +struct Y { }; // { dg-error "" "" { target { ! c++1z } } } template