From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 77777 invoked by alias); 18 Jan 2019 20:35:56 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 77716 invoked by uid 89); 18 Jan 2019 20:35:55 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=sk:copyli, sk:maybe_w, sk:copy-li, initializing X-HELO: mail-qt1-f195.google.com Received: from mail-qt1-f195.google.com (HELO mail-qt1-f195.google.com) (209.85.160.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 Jan 2019 20:35:53 +0000 Received: by mail-qt1-f195.google.com with SMTP id u47so16681439qtj.6 for ; Fri, 18 Jan 2019 12:35:52 -0800 (PST) Return-Path: Received: from orpheus.redhat.com (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id a185sm49240065qkb.1.2019.01.18.12.35.50 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 18 Jan 2019 12:35:50 -0800 (PST) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] PR c++/88875 - error with explicit list constructor. Date: Fri, 18 Jan 2019 20:35:00 -0000 Message-Id: <20190118203548.29886-1-jason@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes X-SW-Source: 2019-01/txt/msg01100.txt.bz2 In my patch for CWG issue 2267, I changed reference_binding to clear CONSTRUCTOR_IS_DIRECT_INIT on the argument init-list. But that breaks if there's another candidate for which CONSTRUCTOR_IS_DIRECT_INIT is correct. So instead, let's encode in the conversion that we want to override the flag. Tested x86_64-pc-linux-gnu, applying to trunk. * call.c (reference_binding): Don't modify EXPR. Set need_temporary_p on the ck_user conversion for a temporary. (convert_like_real): Check it. --- gcc/cp/call.c | 11 +++++++--- .../g++.dg/cpp0x/initlist-explicit2.C | 20 +++++++++++++++++++ gcc/cp/ChangeLog | 7 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-explicit2.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 499894b353f..16c3706cc5c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -94,7 +94,7 @@ 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. If KIND is ck_ambig, true if the context is + conversion. If KIND is ck_ambig or ck_user, true means force copy-initialization. */ BOOL_BITFIELD need_temporary_p : 1; /* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion @@ -1560,6 +1560,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, from = TREE_TYPE (expr); } + bool copy_list_init = false; if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)) { maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); @@ -1582,7 +1583,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, /* Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is copy-list-initialized, and the reference is bound to that temporary. */ - CONSTRUCTOR_IS_DIRECT_INIT (expr) = false; + copy_list_init = true; skip:; } @@ -1770,6 +1771,10 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, if (conv->user_conv_p) { + if (copy_list_init) + /* Remember this was copy-list-initialization. */ + conv->need_temporary_p = true; + /* If initializing the temporary used a conversion function, recalculate the second conversion sequence. */ for (conversion *t = conv; t; t = next_conversion (t)) @@ -6941,7 +6946,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn) && BRACE_ENCLOSED_INITIALIZER_P (expr) /* Unless this is for direct-list-initialization. */ - && !CONSTRUCTOR_IS_DIRECT_INIT (expr) + && (!CONSTRUCTOR_IS_DIRECT_INIT (expr) || convs->need_temporary_p) /* And in C++98 a default constructor can't be explicit. */ && cxx_dialect >= cxx11) { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-explicit2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-explicit2.C new file mode 100644 index 00000000000..26a63bf2aa7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-explicit2.C @@ -0,0 +1,20 @@ +// PR c++/88875 +// { dg-do compile { target c++11 } } + +#include + +struct X { + X(); + explicit X(const std::initializer_list& init); +}; + +struct Y +{ + X x { 1, 2 }; // error + + Y (int) + : x {1, 2} // ok + { + } + +}; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d224b72c0bb..4292930daf3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-01-18 Jason Merrill + + PR c++/88875 - error with explicit list constructor. + * call.c (reference_binding): Don't modify EXPR. Set + need_temporary_p on the ck_user conversion for a temporary. + (convert_like_real): Check it. + 2019-01-18 H.J. Lu PR c/51628 base-commit: 31975c5ea11cee1a66a59e6d941db4c6b3cc602c -- 2.20.1