]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
pt.c (type_unification_real): Fix handling of DEDUCE_CONV with no deducible template...
authorJason Merrill <jason@redhat.com>
Mon, 12 Sep 2011 18:05:03 +0000 (14:05 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 12 Sep 2011 18:05:03 +0000 (14:05 -0400)
* pt.c (type_unification_real): Fix handling of DEDUCE_CONV
with no deducible template parameters.
* call.c (rejection_reason_code): Add rr_template_conversion.
(print_z_candidate): Handle it.
(template_conversion_rejection): New.
(build_user_type_conversion_1): Use it.

From-SVN: r178791

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C

index 83bd7801cdcf3284d1bf70daddf6f6116c7af723..6b6c36da4ec8cc441a01daeba06db0507bb3e086 100644 (file)
@@ -1,5 +1,12 @@
 2011-09-12  Jason Merrill  <jason@redhat.com>
 
+       * pt.c (type_unification_real): Fix handling of DEDUCE_CONV
+       with no deducible template parameters.
+       * call.c (rejection_reason_code): Add rr_template_conversion.
+       (print_z_candidate): Handle it.
+       (template_conversion_rejection): New.
+       (build_user_type_conversion_1): Use it.
+
        * call.c (merge_conversion_sequences): Set bad_p and user_conv_p
        on all of the second conversion sequence.
        (build_user_type_conversion_1): Set bad_p on the ck_user conv.
index a97e8c79417d7302ff47b05b01907c7e4f9f2108..81df80ed88ecd093d7488a2781cf13a8d6acc567 100644 (file)
@@ -432,6 +432,7 @@ enum rejection_reason_code {
   rr_none,
   rr_arity,
   rr_explicit_conversion,
+  rr_template_conversion,
   rr_arg_conversion,
   rr_bad_arg_conversion,
   rr_template_unification,
@@ -653,6 +654,16 @@ explicit_conversion_rejection (tree from, tree to)
   return r;
 }
 
+static struct rejection_reason *
+template_conversion_rejection (tree from, tree to)
+{
+  struct rejection_reason *r = alloc_rejection (rr_template_conversion);
+  r->u.conversion.n_arg = 0;
+  r->u.conversion.from_type = from;
+  r->u.conversion.to_type = to;
+  return r;
+}
+
 static struct rejection_reason *
 template_unification_rejection (tree tmpl, tree explicit_targs, tree targs,
                                const tree *args, unsigned int nargs,
@@ -3135,6 +3146,12 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
                  "conversion", r->u.conversion.from_type,
                  r->u.conversion.to_type);
          break;
+       case rr_template_conversion:
+         inform (loc, "  conversion from return type %qT of template "
+                 "conversion function specialization to %qT is not an "
+                 "exact match", r->u.conversion.from_type,
+                 r->u.conversion.to_type);
+         break;
        case rr_template_unification:
          /* We use template_unification_error_rejection if unification caused
             actual non-SFINAE errors, in which case we don't need to repeat
@@ -3495,6 +3512,16 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
                = bad_arg_conversion_rejection (NULL_TREE, -1,
                                                rettype, totype);
            }
+         else if (primary_template_instantiation_p (cand->fn)
+                  && ics->rank > cr_exact)
+           {
+             /* 13.3.3.1.2: If the user-defined conversion is specified by
+                a specialization of a conversion function template, the
+                second standard conversion sequence shall have exact match
+                rank.  */
+             cand->viable = -1;
+             cand->reason = template_conversion_rejection (rettype, totype);
+           }
        }
     }
 
index d326c842c701a091faf8c8e06350970c5d48f6b7..9a5e3ddf13bbd930fb986231b6190f2fbe6d9894 100644 (file)
@@ -14709,10 +14709,18 @@ type_unification_real (tree tparms,
 
          if (same_type_p (parm, type))
            continue;
-         if (strict != DEDUCE_EXACT
-             && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg,
-                                 flags))
-           continue;
+         if (strict == DEDUCE_CONV)
+           {
+             if (can_convert_arg (type, parm, NULL_TREE, flags))
+               continue;
+           }
+         else if (strict != DEDUCE_EXACT)
+           {
+             if (can_convert_arg (parm, type,
+                                  TYPE_P (arg) ? NULL_TREE : arg,
+                                  flags))
+               continue;
+           }
 
          if (strict == DEDUCE_EXACT)
            return unify_type_mismatch (explain_p, parm, arg);
index 65bd35467997f5f3220107a13e14b00fe87ad5c3..dde09f5773fd21e47eb769a78d9cb566a9138082 100644 (file)
@@ -1,5 +1,7 @@
 2011-09-12  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/fntmpdefarg2.C: Add more tests.
+
        * g++.dg/cpp0x/explicit7.C: New.
 
 2011-09-12  Jakub Jelinek  <jakub@redhat.com>
index 12cc83659c59f126f309ee026c64756da289c858..d94843c1fe5687d561fc2c300d7a288544d56fcf 100644 (file)
@@ -4,11 +4,21 @@
 struct B { };
 struct D : B { };
 struct A {
-  template<typename T = void> operator D&();
+  template<typename T = void> operator D&(); // { dg-message "template conversion" }
   operator long();
 };
 
 void f(long);
 void f(B&);
 
-int main() { f(A()); }
+struct A2 {
+  template<typename T = void> operator B&();
+};
+
+void f2(const B&);
+
+int main() {
+  f(A());
+  f2(A2());
+  f2(A());                     // { dg-error "" }
+}