Commit cef62ad4 by Jason Merrill Committed by Jason Merrill

call.c (add_function_candidate): Set LOOKUP_COPY_PARM for any constructor called…

call.c (add_function_candidate): Set LOOKUP_COPY_PARM for any constructor called with a single argument that...

	* 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.

From-SVN: r161443
parent d9816849
2010-06-26 Jason Merrill <jason@redhat.com>
* 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.
2010-06-25 Joseph Myers <joseph@codesourcery.com> 2010-06-25 Joseph Myers <joseph@codesourcery.com>
* lang-specs.h: Remove +e handling. * lang-specs.h: Remove +e handling.
......
...@@ -122,6 +122,11 @@ struct conversion { ...@@ -122,6 +122,11 @@ struct conversion {
: (NODE)->user_conv_p ? cr_user \ : (NODE)->user_conv_p ? cr_user \
: (NODE)->rank) : (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 struct obstack conversion_obstack;
static bool conversion_obstack_initialized; static bool conversion_obstack_initialized;
...@@ -1386,9 +1391,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags) ...@@ -1386,9 +1391,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
conversion operator). */ conversion operator). */
flags |= LOOKUP_NO_TEMP_BIND; flags |= LOOKUP_NO_TEMP_BIND;
/* Temporaries are copy-initialized, except for this hack to allow /* Core issue 899: When [copy-]initializing a temporary to be bound
explicit conversion ops to the copy ctor. See also to the first parameter of a copy constructor (12.8) called with
add_function_candidate. */ 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)) if (!(flags & LOOKUP_COPY_PARM))
flags |= LOOKUP_ONLYCONVERTING; flags |= LOOKUP_ONLYCONVERTING;
...@@ -1618,6 +1626,8 @@ add_function_candidate (struct z_candidate **candidates, ...@@ -1618,6 +1626,8 @@ add_function_candidate (struct z_candidate **candidates,
tree parmtype = TREE_VALUE (parmnode); tree parmtype = TREE_VALUE (parmnode);
int lflags = flags; int lflags = flags;
parmnode = TREE_CHAIN (parmnode);
/* The type of the implicit object parameter ('this') for /* The type of the implicit object parameter ('this') for
overload resolution is not always the same as for the overload resolution is not always the same as for the
function itself; conversion functions are considered to function itself; conversion functions are considered to
...@@ -1634,13 +1644,25 @@ add_function_candidate (struct z_candidate **candidates, ...@@ -1634,13 +1644,25 @@ add_function_candidate (struct z_candidate **candidates,
parmtype = build_pointer_type (parmtype); parmtype = build_pointer_type (parmtype);
} }
if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn) /* Core issue 899: When [copy-]initializing a temporary to be bound
&& (len-skip == 1)) 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; 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) if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
lflags |= LOOKUP_NO_CONVERSION; lflags |= LOOKUP_NO_CONVERSION;
} }
...@@ -1668,9 +1690,6 @@ add_function_candidate (struct z_candidate **candidates, ...@@ -1668,9 +1690,6 @@ add_function_candidate (struct z_candidate **candidates,
if (t->bad_p) if (t->bad_p)
viable = -1; viable = -1;
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
} }
out: out:
...@@ -6741,14 +6760,16 @@ compare_ics (conversion *ics1, conversion *ics2) ...@@ -6741,14 +6760,16 @@ compare_ics (conversion *ics1, conversion *ics2)
if (rank1 == cr_bad) if (rank1 == cr_bad)
{ {
/* XXX Isn't this an extension? */ /* Both ICS are bad. We try to make a decision based on what would
/* Both ICS are bad. We try to make a decision based on what have happened if they'd been good. This is not an extension,
would have happened if they'd been good. */ we'll still give an error when we build up the call; this just
if (ics1->user_conv_p > ics2->user_conv_p helps us give a more helpful error message. */
|| ics1->rank > ics2->rank) rank1 = BAD_CONVERSION_RANK (ics1);
rank2 = BAD_CONVERSION_RANK (ics2);
if (rank1 > rank2)
return -1; return -1;
else if (ics1->user_conv_p < ics2->user_conv_p else if (rank1 < rank2)
|| ics1->rank < ics2->rank)
return 1; return 1;
/* We couldn't make up our minds; try to figure it out below. */ /* We couldn't make up our minds; try to figure it out below. */
......
2010-06-26 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/explicit5.C: New.
2010-06-26 Richard Guenther <rguenther@suse.de> 2010-06-26 Richard Guenther <rguenther@suse.de>
PR tree-optimization/44393 PR tree-optimization/44393
......
// 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 <class T = int> 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment