Re: [C++ Patch] PR 57466 (DR 1584)
On 08/18/2014 03:05 PM, Paolo Carlini wrote: I understand... It would be nice to also have a testcase for the class template counterpart of the snippet in DR 1584, where it makes a real difference. Then figuring out a complete patch not causing regressions will be easier. I think this is a problem with DR 1584; I'll raise it on the core list. Jason
Re: [C++ Patch] PR 57466 (DR 1584)
Hi, On 08/18/2014 09:01 PM, Jason Merrill wrote: On 08/15/2014 03:37 PM, Paolo Carlini wrote: On 08/15/2014 09:22 PM, Jason Merrill wrote: On 08/15/2014 03:16 PM, Paolo Carlini wrote: + bool in_function = (TREE_TYPE (tparms) + && DECL_FUNCTION_TEMPLATE_P (TREE_TYPE (tparms))); Huh? There's no such thing as a template parameter of function type. Oh, I see, you're using that TREE_TYPE of the parameter vec points to the primary template for those template parms. But I don't see any rationale in the standard for distinguishing between deduction for a function template vs. another kind of template for the DR 1584 change. I understand... It would be nice to also have a testcase for the class template counterpart of the snippet in DR 1584, where it makes a real difference. Then figuring out a complete patch not causing regressions will be easier. Paolo.
Re: [C++ Patch] PR 57466 (DR 1584)
On 08/15/2014 03:37 PM, Paolo Carlini wrote: On 08/15/2014 09:22 PM, Jason Merrill wrote: On 08/15/2014 03:16 PM, Paolo Carlini wrote: + bool in_function = (TREE_TYPE (tparms) + && DECL_FUNCTION_TEMPLATE_P (TREE_TYPE (tparms))); Huh? There's no such thing as a template parameter of function type. Oh, I see, you're using that TREE_TYPE of the parameter vec points to the primary template for those template parms. But I don't see any rationale in the standard for distinguishing between deduction for a function template vs. another kind of template for the DR 1584 change. Jason
Re: [C++ Patch] PR 57466 (DR 1584)
Hi, On 08/15/2014 09:22 PM, Jason Merrill wrote: On 08/15/2014 03:16 PM, Paolo Carlini wrote: + bool in_function = (TREE_TYPE (tparms) + && DECL_FUNCTION_TEMPLATE_P (TREE_TYPE (tparms))); Huh? There's no such thing as a template parameter of function type. Works fine, in fact, I have just finished regtesting the patch. Consider, eg, from the DR: template void f2(const T*); void g2(); void m() { f2(g2);// OK: cv-qualification of deduced function type ignored } when unify is called by unify_one_argument is a TREE_VEC and the TREE_TYPE contains the information we need: type 0x76c48f18 void> type_0 type_6 QI size unit size align 8 symtab 0 alias set -1 canonical type 0x76daa150 arg-types 0x76daa0a8> chain 0x76c48f18 void VOID file 57466_1.C line 3 col 24 align 1 context full-name "template void f2(const T*)" chain volatile public external QI file line 0 col 0 align 8 full-name "void __cxa_call_unexpected(void*)" chain >> elt 0 value 0x76d97f18 T> decl_0 VOID file 57466_1.C line 3 col 10 align 1>>> Paolo.
Re: [C++ Patch] PR 57466 (DR 1584)
On 08/15/2014 03:16 PM, Paolo Carlini wrote: + bool in_function = (TREE_TYPE (tparms) + && DECL_FUNCTION_TEMPLATE_P (TREE_TYPE (tparms))); Huh? There's no such thing as a template parameter of function type. Jason
Re: [C++ Patch] PR 57466 (DR 1584)
... in practice, something like the below. Paolo. /// Index: cp/pt.c === --- cp/pt.c (revision 214027) +++ cp/pt.c (working copy) @@ -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), Index: testsuite/g++.dg/cpp0x/pr57466.C === --- testsuite/g++.dg/cpp0x/pr57466.C(revision 0) +++ testsuite/g++.dg/cpp0x/pr57466.C(working copy) @@ -0,0 +1,18 @@ +// PR c++/57466 +// { dg-do compile { target c++11 } } + +template + constexpr bool + is_pointer(const T*) + { return true; } + +template + 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" ); Index: testsuite/g++.dg/template/pr57466.C === --- testsuite/g++.dg/template/pr57466.C (revision 0) +++ testsuite/g++.dg/template/pr57466.C (working copy) @@ -0,0 +1,8 @@ +// DR 1584, PR c++/57466 + +template void f2(const T*); +void g2(); + +void m() { + f2(g2);// OK: cv-qualification of deduced function type ignored +} Index: testsuite/g++.dg/template/unify6.C === --- testsuite/g++.dg/template/unify6.C (revision 214027) +++ testsuite/g++.dg/template/unify6.C (working copy) @@ -3,21 +3,20 @@ void Baz (); -template void Foo1 (T *); // #1 -template void Foo1 (T const
Re: [C++ Patch] PR 57466 (DR 1584)
Hi, On 08/15/2014 07:30 PM, Jason Merrill wrote: On 08/15/2014 12:17 PM, Paolo Carlini wrote: By the way, more generally, I don't understand at the moment how we can safely use complete_type in the middle of tsubst & co: it can emit hard errors about, eg, incompleteness (see c++/62072) irrespective of the tsubst_flags_t argument... Yes, it can, that's part of the language; remember "Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure", invalid constructs outside that context result in hard errors. I see, it boils down again to that "famous" wording... Now, is it possible that the issue we are facing with implementing DR 1584 has to do with the fact that our unify doesn't tell template functions vs template classes?!? Thus we should return 1 from check_cv_quals_for_unify when arg is a FUNCTION_TYPE *and* DECL_TYPE_TEMPLATE_P (TREE_TYPE (tparms)) is true?!? (we could pass the information in a flag) Because I don't think an equivalent of the key bits of c++/62072: template struct tuple_size { }; template struct tuple_size : tuple_size { }; can be constructed for template functions?!? Paolo.
Re: [C++ Patch] PR 57466 (DR 1584)
On 08/15/2014 12:17 PM, Paolo Carlini wrote: By the way, more generally, I don't understand at the moment how we can safely use complete_type in the middle of tsubst & co: it can emit hard errors about, eg, incompleteness (see c++/62072) irrespective of the tsubst_flags_t argument... Yes, it can, that's part of the language; remember "Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure", invalid constructs outside that context result in hard errors. Jason
Re: [C++ Patch] PR 57466 (DR 1584)
.. unfortunately something is wrong with this commit, thus c++/62072. For the time being I'm simply reverting it and adding the new testcase. By the way, more generally, I don't understand at the moment how we can safely use complete_type in the middle of tsubst & co: it can emit hard errors about, eg, incompleteness (see c++/62072) irrespective of the tsubst_flags_t argument... Thanks, Paolo.
Re: [C++ Patch] PR 57466 (DR 1584)
OK. Jason
Re: [C++ Patch] PR 57466 (DR 1584)
Hi, On 07/09/2014 12:26 AM, Jason Merrill wrote: I'd rather handle this in check_cv_quals_for_unify. Yes, the below passes testing. Thanks, Paolo. / /cp 2014-07-09 Paolo Carlini DR 1584 PR c++/57466 * pt.c (check_cv_quals_for_unify): Implement resolution, disregard cv-qualifiers of function types. /testsuite 2014-07-09 Paolo Carlini DR 1584 PR c++/57466 * g++.dg/template/pr57466.C: New. * g++.dg/cpp0x/pr57466.C: Likewise. * g++.dg/template/unify6.C: Update. Index: cp/pt.c === --- cp/pt.c (revision 212385) +++ cp/pt.c (working copy) @@ -17189,6 +17189,11 @@ check_cv_quals_for_unify (int strict, tree arg, tr 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 (TREE_CODE (arg) == FUNCTION_TYPE) +return 1; + if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM && !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL)) { Index: testsuite/g++.dg/cpp0x/pr57466.C === --- testsuite/g++.dg/cpp0x/pr57466.C(revision 0) +++ testsuite/g++.dg/cpp0x/pr57466.C(working copy) @@ -0,0 +1,18 @@ +// PR c++/57466 +// { dg-do compile { target c++11 } } + +template + constexpr bool + is_pointer(const T*) + { return true; } + +template + 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" ); Index: testsuite/g++.dg/template/pr57466.C === --- testsuite/g++.dg/template/pr57466.C (revision 0) +++ testsuite/g++.dg/template/pr57466.C (working copy) @@ -0,0 +1,8 @@ +// DR 1584, PR c++/57466 + +template void f2(const T*); +void g2(); + +void m() { + f2(g2);// OK: cv-qualification of deduced function type ignored +} Index: testsuite/g++.dg/template/unify6.C === --- testsuite/g++.dg/template/unify6.C (revision 212385) +++ testsuite/g++.dg/template/unify6.C (working copy) @@ -3,21 +3,20 @@ void Baz (); -template void Foo1 (T *); // #1 -template void Foo1 (T const *a) {a (1);} // #2 +template void Foo1 (T *); +template void Foo1 (T const *a) {a (1);} // { dg-error "too many arguments" } template T const *Foo2 (T *); -template void Foo3 (T *, T const * = 0); // { dg-message "note" } +template 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); }
Re: [C++ Patch] PR 57466 (DR 1584)
I'd rather handle this in check_cv_quals_for_unify. Jason