diff mbox

[C++] PR 57466 (DR 1584)

Message ID 53EE5C8D.4030300@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Aug. 15, 2014, 7:16 p.m. UTC
... in practice, something like the below.

Paolo.

///////////////////

Comments

Jason Merrill Aug. 15, 2014, 7:22 p.m. UTC | #1
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
Paolo Carlini Aug. 15, 2014, 7:37 p.m. UTC | #2
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<class T> 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:

  <tree_vec 0x7ffff6da7300
     type <template_decl 0x7ffff6da9100 f2
         type <function_type 0x7ffff6daa150 type <void_type 
0x7ffff6c48f18 void>
             type_0 type_6 QI
             size <integer_cst 0x7ffff6c2eed0 constant 8>
             unit size <integer_cst 0x7ffff6c2eee8 constant 1>
             align 8 symtab 0 alias set -1 canonical type 0x7ffff6daa150
             arg-types <tree_list 0x7ffff6d99370 value <pointer_type 
0x7ffff6daa0a8>
                 chain <tree_list 0x7ffff6c3eb40 value <void_type 
0x7ffff6c48f18 void>>>>
         VOID file 57466_1.C line 3 col 24
         align 1 context <translation_unit_decl 0x7ffff7ff7078 D.1>
         full-name "template<class T> void f2(const T*)"

         chain <function_decl 0x7ffff6d95600 __cxa_call_unexpected type 
<function_type 0x7ffff6c5b0a8>
             volatile public external QI file <built-in> line 0 col 0 
align 8
             full-name "void __cxa_call_unexpected(void*)"
             chain <function_decl 0x7ffff6d95200 operator delete []>>>

     elt 0 <tree_list 0x7ffff6d992f8
         value <type_decl 0x7ffff6d982f8 T type <template_type_parm 
0x7ffff6d97f18 T>
             decl_0 VOID file 57466_1.C line 3 col 10
             align 1>>>

Paolo.
Jason Merrill Aug. 18, 2014, 7:01 p.m. UTC | #3
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
Paolo Carlini Aug. 18, 2014, 7:05 p.m. UTC | #4
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.
Jason Merrill Aug. 18, 2014, 7:47 p.m. UTC | #5
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
diff mbox

Patch

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<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" );
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<class T> 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 <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);
 }