From 929a01229393f32b47d4915e48437c091a7baeec Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 16 Mar 2018 14:55:54 -0400 Subject: [PATCH] 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. From-SVN: r258603 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/call.c | 11 ++++++++--- gcc/testsuite/g++.dg/cpp1y/auto-fn50.C | 23 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/auto-fn50.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7428c4bf20b..60fe5423ba6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2018-03-16 Jason Merrill + 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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a32f41915fc..23d4f82a1a0 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 index 00000000000..a2c7e40755b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn50.C @@ -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"); +} -- 2.30.2