PR c++/84906 - silent wrong code with ambiguous conversion.
authorJason Merrill <jason@redhat.com>
Fri, 16 Mar 2018 18:55:54 +0000 (14:55 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 16 Mar 2018 18:55:54 +0000 (14:55 -0400)
* call.c (build_user_type_conversion_1): Set need_temporary_p on
ambiguous conversion.
(convert_like_real): Check it.

From-SVN: r258603

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/cpp1y/auto-fn50.C [new file with mode: 0644]

index 7428c4bf20bc3bb4c84810d2b5e46b0c2a4a3de7..60fe5423ba6e6189895269e03a7055c29bb52e55 100644 (file)
@@ -1,5 +1,10 @@
 2018-03-16  Jason Merrill  <jason@redhat.com>
 
+       PR c++/84906 - silent wrong code with ambiguous conversion.
+       * call.c (build_user_type_conversion_1): Set need_temporary_p on
+       ambiguous conversion.
+       (convert_like_real): Check it.
+
        PR c++/83937 - wrong C++17 handling of init-list ctor argument.
        * call.c (build_special_member_call): Don't convert an init-list
        argument directly to the class type.
index a32f41915fc00a4dcba119158e9ec71dbaeec58a..23d4f82a1a0c4182905574784fcd36008c713e16 100644 (file)
@@ -93,7 +93,8 @@ struct conversion {
   BOOL_BITFIELD bad_p : 1;
   /* If KIND is ck_ref_bind ck_base_conv, true to indicate that a
      temporary should be created to hold the result of the
-     conversion.  */
+     conversion.  If KIND is ck_ambig, true if the context is
+     copy-initialization.  */
   BOOL_BITFIELD need_temporary_p : 1;
   /* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion
      from a pointer-to-derived to pointer-to-base is being performed.  */
@@ -3943,6 +3944,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
       cand->second_conv->user_conv_p = true;
       if (!any_strictly_viable (candidates))
        cand->second_conv->bad_p = true;
+      if (flags & LOOKUP_ONLYCONVERTING)
+       cand->second_conv->need_temporary_p = true;
       /* If there are viable candidates, don't set ICS_BAD_FLAG; an
         ambiguous conversion is no worse than another user-defined
         conversion.  */
@@ -6834,8 +6837,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
       if (complain & tf_error)
        {
          /* Call build_user_type_conversion again for the error.  */
-         build_user_type_conversion (totype, convs->u.expr, LOOKUP_IMPLICIT,
-                                     complain);
+         int flags = (convs->need_temporary_p
+                      ? LOOKUP_IMPLICIT : LOOKUP_NORMAL);
+         build_user_type_conversion (totype, convs->u.expr, flags, complain);
+         gcc_assert (seen_error ());
          if (fn)
            inform (DECL_SOURCE_LOCATION (fn),
                    "  initializing argument %P of %qD", argnum, fn);
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C
new file mode 100644 (file)
index 0000000..a2c7e40
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/84906
+// { dg-do compile { target c++14 } }
+
+extern "C" int puts(const char*);
+
+struct aa {
+  operator auto() {
+    puts("auto");
+    return false;
+  }
+  explicit operator bool() {
+    puts("bool");
+    return true;
+  }
+};
+
+int main() {
+  aa x;
+  if (x)                       // { dg-error "ambiguous" }
+    puts("here");
+  else
+    puts("there");
+}