From patchwork Sat Jun 26 21:33:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 57072 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A1A93B6EFF for ; Sun, 27 Jun 2010 07:34:09 +1000 (EST) Received: (qmail 3425 invoked by alias); 26 Jun 2010 21:34:08 -0000 Received: (qmail 3414 invoked by uid 22791); 26 Jun 2010 21:34:07 -0000 X-SWARE-Spam-Status: No, hits=-5.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 26 Jun 2010 21:34:01 +0000 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o5QLY0T0003917 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sat, 26 Jun 2010 17:34:00 -0400 Received: from [IPv6:::1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o5QLXxGX024755 for ; Sat, 26 Jun 2010 17:33:59 -0400 Message-ID: <4C267246.4020906@redhat.com> Date: Sat, 26 Jun 2010 17:33:58 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100619 Lightning/1.0b1 Shredder/3.0.6pre MIME-Version: 1.0 To: gcc-patches List Subject: C++0x PATCH to explicit conversion handling Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org In my earlier implementation of explicit conversion ops, I treated initialization of a reference temp for the argument of the copy constructor as direct-initialization. This was later adopted as core DR 899. In my recent work on implicit move constructors (to be committed soon) I noticed that we need the same handling of move constructors, and indeed any other constructor used to initialize a class from an object of the same type. The BAD_CONVERSION_RANK change is to fix comparison of bad conversions in order to keep the useful error ("bad conversion") on 20_util/unique_ptr/cons/pointer_array_convertible.cc; without that change the error changes to "no match". Tested x86_64-pc-linux-gnu, applying to trunk. commit bad8ef8482a6bd5ecc0450f791a5aff768dc6b80 Author: Jason Merrill Date: Fri Jun 25 15:20:17 2010 -0400 * call.c (add_function_candidate): Set LOOKUP_COPY_PARM for any constructor called with a single argument that takes a reference to the constructor's class. (BAD_CONVERSION_RANK): New. (compare_ics): Use it to compare bad ICSes. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 55089ed..faaab10 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -122,6 +122,11 @@ struct conversion { : (NODE)->user_conv_p ? cr_user \ : (NODE)->rank) +#define BAD_CONVERSION_RANK(NODE) \ + ((NODE)->ellipsis_p ? cr_ellipsis \ + : (NODE)->user_conv_p ? cr_user \ + : (NODE)->rank) + static struct obstack conversion_obstack; static bool conversion_obstack_initialized; @@ -1386,9 +1391,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) conversion operator). */ flags |= LOOKUP_NO_TEMP_BIND; - /* Temporaries are copy-initialized, except for this hack to allow - explicit conversion ops to the copy ctor. See also - add_function_candidate. */ + /* Core issue 899: When [copy-]initializing a temporary to be bound + to the first parameter of a copy constructor (12.8) called with + a single argument in the context of direct-initialization, + explicit conversion functions are also considered. + + So don't set LOOKUP_ONLYCONVERTING in that case. */ if (!(flags & LOOKUP_COPY_PARM)) flags |= LOOKUP_ONLYCONVERTING; @@ -1618,6 +1626,8 @@ add_function_candidate (struct z_candidate **candidates, tree parmtype = TREE_VALUE (parmnode); int lflags = flags; + parmnode = TREE_CHAIN (parmnode); + /* The type of the implicit object parameter ('this') for overload resolution is not always the same as for the function itself; conversion functions are considered to @@ -1634,13 +1644,25 @@ add_function_candidate (struct z_candidate **candidates, parmtype = build_pointer_type (parmtype); } - if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn) - && (len-skip == 1)) + /* Core issue 899: When [copy-]initializing a temporary to be bound + to the first parameter of a copy constructor (12.8) called with + a single argument in the context of direct-initialization, + explicit conversion functions are also considered. + + So set LOOKUP_COPY_PARM to let reference_binding know that + it's being called in that context. We generalize the above + to handle move constructors and template constructors as well; + the standardese should soon be updated similarly. */ + if (ctype && i == 0 && (len-skip == 1) + && !(flags & LOOKUP_ONLYCONVERTING) + && DECL_CONSTRUCTOR_P (fn) + && parmtype != error_mark_node + && (same_type_ignoring_top_level_qualifiers_p + (non_reference (parmtype), ctype))) { - /* Hack: Direct-initialize copy parm (i.e. suppress - LOOKUP_ONLYCONVERTING) to make explicit conversion ops - work. See also reference_binding. */ lflags |= LOOKUP_COPY_PARM; + /* We allow user-defined conversions within init-lists, but + not for the copy constructor. */ if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION) lflags |= LOOKUP_NO_CONVERSION; } @@ -1668,9 +1690,6 @@ add_function_candidate (struct z_candidate **candidates, if (t->bad_p) viable = -1; - - if (parmnode) - parmnode = TREE_CHAIN (parmnode); } out: @@ -6741,14 +6760,16 @@ compare_ics (conversion *ics1, conversion *ics2) if (rank1 == cr_bad) { - /* XXX Isn't this an extension? */ - /* Both ICS are bad. We try to make a decision based on what - would have happened if they'd been good. */ - if (ics1->user_conv_p > ics2->user_conv_p - || ics1->rank > ics2->rank) + /* Both ICS are bad. We try to make a decision based on what would + have happened if they'd been good. This is not an extension, + we'll still give an error when we build up the call; this just + helps us give a more helpful error message. */ + rank1 = BAD_CONVERSION_RANK (ics1); + rank2 = BAD_CONVERSION_RANK (ics2); + + if (rank1 > rank2) return -1; - else if (ics1->user_conv_p < ics2->user_conv_p - || ics1->rank < ics2->rank) + else if (rank1 < rank2) return 1; /* We couldn't make up our minds; try to figure it out below. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit5.C b/gcc/testsuite/g++.dg/cpp0x/explicit5.C new file mode 100644 index 0000000..88a4707 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/explicit5.C @@ -0,0 +1,25 @@ +// test for extension of DR 899 to handle template ctors +// { dg-options "-std=c++0x" } +// { dg-do run } + +int r = 1; + +struct C { + C() { } + template C(C&, T = 0) { r = 0; } +}; + +C c; + +struct A +{ + explicit operator C&() const { return c; } +}; + +int main() +{ + A a; + C c2 (a); + + return r; +}