PR c++/81102 - Wrong error with partial specialization.
authorJason Merrill <jason@redhat.com>
Sat, 17 Jun 2017 02:27:59 +0000 (22:27 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 17 Jun 2017 02:27:59 +0000 (22:27 -0400)
* pt.c (unify) [TEMPLATE_PARM_INDEX]: Strip reference when comparing
types.  Do type deduction later.

From-SVN: r249320

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/partial-specialization7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/partial5.C

index 330f0f205a0c685e7b2fb24f08db889fc2ab650a..2d47d7b4a7f4a0b5dd67bb7f84bba0d685c4c16a 100644 (file)
@@ -1,5 +1,9 @@
 2017-06-16  Jason Merrill  <jason@redhat.com>
 
+       PR c++/81102 - Wrong error with partial specialization.
+       * pt.c (unify) [TEMPLATE_PARM_INDEX]: Strip reference when comparing
+       types.  Do type deduction later.
+
        PR c++/80174 - ICE with partial specialization of member template.
        PR c++/71747
        * pt.c (get_partial_spec_bindings): Only coerce innermost args.
index 0a5816303472f216734f1a5cbb78881853750f4a..d2b91b2435642883b177c746d5dc575a51d7686b 100644 (file)
@@ -20628,18 +20628,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
@@ -20660,7 +20648,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))
@@ -20669,9 +20658,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 (file)
index 0000000..aa42191
--- /dev/null
@@ -0,0 +1,40 @@
+// PR c++/81102
+
+template <typename FuncSig, FuncSig f>
+struct HelperWrapper;
+
+// [...]
+
+template <typename Ret, Ret (&Func)()>
+struct HelperWrapper<Ret (&)(), Func>
+{
+    static inline int WrapFuncT(const int)
+    {
+        return 0; // Changed
+    }
+};
+
+// Unary
+template <typename Ret, typename Arg1, Ret (&Func)(Arg1)>
+struct HelperWrapper<Ret (&)(Arg1), Func>
+{
+    static inline int WrapFuncT(const int)
+    {
+        return 1; // Changed
+    }
+};
+
+// Binary
+template <typename Ret, typename Arg1, typename Arg2, Ret (&Func)(Arg1, Arg2)>
+struct HelperWrapper<Ret (&)(Arg1, Arg2), Func>
+{
+    static inline int WrapFuncT(const int)
+    {
+        return 2; // Changed
+    }
+};
+
+int main()
+{
+  return 0;
+}
index 1b56fb39fa1f64289906d514b1138ffcef96ce91..ee45a936a0c88e647e41c8d7d9d54af385bed122 100644 (file)
@@ -14,7 +14,7 @@ template<typename T, typename T::foo V>
 struct Y { };
 
 template<typename T, typename U, U v>
-struct Y<T, v> { }; // { dg-error "" }
+struct Y<T, v> { }; // { dg-error "" "" { target { ! c++1z } } }
 
 
 template<typename T, T V>