===================================================================
@@ -162,7 +162,7 @@ static tree tsubst_friend_class (tree, tree);
static int can_complete_type_without_circularity (tree);
static tree get_bindings (tree, tree, tree, bool);
static int template_decl_level (tree);
-static int check_cv_quals_for_unify (int, tree, tree);
+static int check_cv_quals_for_unify (int, tree, tree, bool);
static void template_parm_level_and_index (tree, int*, int*);
static int unify_pack_expansion (tree, tree, tree,
tree, unification_kind_t, bool, bool);
@@ -17279,11 +17279,16 @@ template_decl_level (tree decl)
Returns nonzero iff the unification is OK on that basis. */
static int
-check_cv_quals_for_unify (int strict, tree arg, tree parm)
+check_cv_quals_for_unify (int strict, tree arg, tree parm, bool in_function)
{
int arg_quals = cp_type_quals (arg);
int parm_quals = cp_type_quals (parm);
+ /* DR 1584: cv-qualification of a deduced function type is
+ ignored; see 8.3.5 [dcl.fct]. */
+ if (in_function && TREE_CODE (arg) == FUNCTION_TYPE)
+ return 1;
+
if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
&& !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
{
@@ -17644,6 +17649,8 @@ unify (tree tparms, tree targs, tree parm, tree ar
tree targ;
tree tparm;
int strict_in = strict;
+ bool in_function = (TREE_TYPE (tparms)
+ && DECL_FUNCTION_TEMPLATE_P (TREE_TYPE (tparms)));
/* I don't think this will do the right thing with respect to types.
But the only case I've seen it in so far has been array bounds, where
@@ -17750,7 +17757,7 @@ unify (tree tparms, tree targs, tree parm, tree ar
PARM `T' for example, when computing which of two templates
is more specialized, for example. */
&& TREE_CODE (arg) != TEMPLATE_TYPE_PARM
- && !check_cv_quals_for_unify (strict_in, arg, parm))
+ && !check_cv_quals_for_unify (strict_in, arg, parm, in_function))
return unify_cv_qual_mismatch (explain_p, parm, arg);
if (!(strict & UNIFY_ALLOW_OUTER_LEVEL)
@@ -17927,7 +17934,7 @@ unify (tree tparms, tree targs, tree parm, tree ar
If ARG is `const int' and PARM is just `T' that's OK;
that binds `const int' to `T'. */
if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
- arg, parm))
+ arg, parm, in_function))
return unify_cv_qual_mismatch (explain_p, parm, arg);
/* Consider the case where ARG is `const volatile int' and
@@ -18273,7 +18280,7 @@ unify (tree tparms, tree targs, tree parm, tree ar
&& (!check_cv_quals_for_unify
(UNIFY_ALLOW_NONE,
class_of_this_parm (arg),
- class_of_this_parm (parm))))
+ class_of_this_parm (parm), in_function)))
return unify_cv_qual_mismatch (explain_p, parm, arg);
RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm),
@@ -18298,7 +18305,8 @@ unify (tree tparms, tree targs, tree parm, tree ar
if (TYPE_PTRMEMFUNC_P (arg))
{
/* Check top-level cv qualifiers */
- if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
+ if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm,
+ in_function))
return unify_cv_qual_mismatch (explain_p, parm, arg);
RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
===================================================================
@@ -0,0 +1,18 @@
+// PR c++/57466
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+ constexpr bool
+ is_pointer(const T*)
+ { return true; }
+
+template<typename T>
+ constexpr bool
+ is_pointer(const T&)
+ { return false; }
+
+using F = void();
+
+constexpr F* f = nullptr;
+
+static_assert( is_pointer(f), "function pointer is a pointer" );
===================================================================
@@ -0,0 +1,8 @@
+// DR 1584, PR c++/57466
+
+template<class T> void f2(const T*);
+void g2();
+
+void m() {
+ f2(g2); // OK: cv-qualification of deduced function type ignored
+}
===================================================================
@@ -3,21 +3,20 @@
void Baz ();
-template <typename T> void Foo1 (T *); // #1
-template <typename T> void Foo1 (T const *a) {a (1);} // #2
+template <typename T> void Foo1 (T *);
+template <typename T> void Foo1 (T const *a) {a (1);} // { dg-error "too many arguments" }
template <typename T> T const *Foo2 (T *);
-template <typename T> void Foo3 (T *, T const * = 0); // { dg-message "note" }
+template <typename T> void Foo3 (T *, T const * = 0);
void Bar ()
{
- Foo1 (&Baz); // #1
+ Foo1 (&Baz); // { dg-message "required from here" }
Foo2 (&Baz);
Foo3 (&Baz);
- Foo3 (&Baz, &Baz); // { dg-error "no matching function" "" }
- // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 21 }
+ Foo3 (&Baz, &Baz);
}