Re: [C++ Patch] PR 57466 (DR 1584)

2014-08-18 Thread Jason Merrill

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)

2014-08-18 Thread Paolo Carlini

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)

2014-08-18 Thread Jason Merrill

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)

2014-08-15 Thread Paolo Carlini

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)

2014-08-15 Thread Jason Merrill

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)

2014-08-15 Thread Paolo Carlini

... 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)

2014-08-15 Thread Paolo Carlini

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)

2014-08-15 Thread Jason Merrill

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)

2014-08-15 Thread Paolo Carlini
.. 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)

2014-07-09 Thread Jason Merrill

OK.

Jason


Re: [C++ Patch] PR 57466 (DR 1584)

2014-07-09 Thread Paolo Carlini

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)

2014-07-08 Thread Jason Merrill

I'd rather handle this in check_cv_quals_for_unify.

Jason