call.c (merge_conversion_sequences): Set bad_p and user_conv_p on all of the second conversion sequence.
* call.c (merge_conversion_sequences): Set bad_p and user_conv_p on all of the second conversion sequence. (build_user_type_conversion_1): Set bad_p on the ck_user conv. (convert_like_real): Handle bad ck_ref_bind with user_conv_p in the first section. Fix loop logic. (initialize_reference): Call convert_like for diagnostics when we have a (bad) conversion. From-SVN: r178790
This commit is contained in:
parent
62a405ddf3
commit
940023f4ba
@ -1,5 +1,13 @@
|
|||||||
2011-09-12 Jason Merrill <jason@redhat.com>
|
2011-09-12 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* call.c (merge_conversion_sequences): Set bad_p and user_conv_p
|
||||||
|
on all of the second conversion sequence.
|
||||||
|
(build_user_type_conversion_1): Set bad_p on the ck_user conv.
|
||||||
|
(convert_like_real): Handle bad ck_ref_bind with user_conv_p in the
|
||||||
|
first section. Fix loop logic.
|
||||||
|
(initialize_reference): Call convert_like for diagnostics when
|
||||||
|
we have a (bad) conversion.
|
||||||
|
|
||||||
* call.c (convert_class_to_reference)
|
* call.c (convert_class_to_reference)
|
||||||
(convert_class_to_reference_1): Remove.
|
(convert_class_to_reference_1): Remove.
|
||||||
(reference_binding): Use build_user_type_conversion_1 instead.
|
(reference_binding): Use build_user_type_conversion_1 instead.
|
||||||
|
@ -3242,21 +3242,23 @@ static conversion *
|
|||||||
merge_conversion_sequences (conversion *user_seq, conversion *std_seq)
|
merge_conversion_sequences (conversion *user_seq, conversion *std_seq)
|
||||||
{
|
{
|
||||||
conversion **t;
|
conversion **t;
|
||||||
|
bool bad = user_seq->bad_p;
|
||||||
|
|
||||||
gcc_assert (user_seq->kind == ck_user);
|
gcc_assert (user_seq->kind == ck_user);
|
||||||
|
|
||||||
/* Find the end of the second conversion sequence. */
|
/* Find the end of the second conversion sequence. */
|
||||||
t = &(std_seq);
|
for (t = &std_seq; (*t)->kind != ck_identity; t = &((*t)->u.next))
|
||||||
while ((*t)->kind != ck_identity)
|
{
|
||||||
t = &((*t)->u.next);
|
/* The entire sequence is a user-conversion sequence. */
|
||||||
|
(*t)->user_conv_p = true;
|
||||||
|
if (bad)
|
||||||
|
(*t)->bad_p = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Replace the identity conversion with the user conversion
|
/* Replace the identity conversion with the user conversion
|
||||||
sequence. */
|
sequence. */
|
||||||
*t = user_seq;
|
*t = user_seq;
|
||||||
|
|
||||||
/* The entire sequence is a user-conversion sequence. */
|
|
||||||
std_seq->user_conv_p = true;
|
|
||||||
|
|
||||||
return std_seq;
|
return std_seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3533,6 +3535,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
|
|||||||
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
|
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
|
||||||
build_identity_conv (TREE_TYPE (expr), expr));
|
build_identity_conv (TREE_TYPE (expr), expr));
|
||||||
conv->cand = cand;
|
conv->cand = cand;
|
||||||
|
if (cand->viable == -1)
|
||||||
|
conv->bad_p = true;
|
||||||
|
|
||||||
/* Remember that this was a list-initialization. */
|
/* Remember that this was a list-initialization. */
|
||||||
if (flags & LOOKUP_NO_NARROWING)
|
if (flags & LOOKUP_NO_NARROWING)
|
||||||
@ -3542,9 +3546,6 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
|
|||||||
cand->second_conv = merge_conversion_sequences (conv,
|
cand->second_conv = merge_conversion_sequences (conv,
|
||||||
cand->second_conv);
|
cand->second_conv);
|
||||||
|
|
||||||
if (cand->viable == -1)
|
|
||||||
cand->second_conv->bad_p = true;
|
|
||||||
|
|
||||||
return cand;
|
return cand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5529,7 +5530,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||||||
&& convs->kind != ck_user
|
&& convs->kind != ck_user
|
||||||
&& convs->kind != ck_list
|
&& convs->kind != ck_list
|
||||||
&& convs->kind != ck_ambig
|
&& convs->kind != ck_ambig
|
||||||
&& convs->kind != ck_ref_bind
|
&& (convs->kind != ck_ref_bind
|
||||||
|
|| convs->user_conv_p)
|
||||||
&& convs->kind != ck_rvalue
|
&& convs->kind != ck_rvalue
|
||||||
&& convs->kind != ck_base)
|
&& convs->kind != ck_base)
|
||||||
{
|
{
|
||||||
@ -5542,7 +5544,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||||||
&& BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
|
&& BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
|
||||||
permerror (input_location, "too many braces around initializer for %qT", totype);
|
permerror (input_location, "too many braces around initializer for %qT", totype);
|
||||||
|
|
||||||
for (; t; t = convs->u.next)
|
for (; t; t = t->u.next)
|
||||||
{
|
{
|
||||||
if (t->kind == ck_user && t->cand->reason)
|
if (t->kind == ck_user && t->cand->reason)
|
||||||
{
|
{
|
||||||
@ -5553,7 +5555,11 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||||||
/*issue_conversion_warnings=*/false,
|
/*issue_conversion_warnings=*/false,
|
||||||
/*c_cast_p=*/false,
|
/*c_cast_p=*/false,
|
||||||
complain);
|
complain);
|
||||||
return cp_convert (totype, expr);
|
if (convs->kind == ck_ref_bind)
|
||||||
|
return convert_to_reference (totype, expr, CONV_IMPLICIT,
|
||||||
|
LOOKUP_NORMAL, NULL_TREE);
|
||||||
|
else
|
||||||
|
return cp_convert (totype, expr);
|
||||||
}
|
}
|
||||||
else if (t->kind == ck_user || !t->bad_p)
|
else if (t->kind == ck_user || !t->bad_p)
|
||||||
{
|
{
|
||||||
@ -5788,9 +5794,11 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||||||
{
|
{
|
||||||
tree ref_type = totype;
|
tree ref_type = totype;
|
||||||
|
|
||||||
if (convs->bad_p && TYPE_REF_IS_RVALUE (ref_type)
|
if (convs->bad_p && !convs->u.next->bad_p)
|
||||||
&& real_lvalue_p (expr))
|
|
||||||
{
|
{
|
||||||
|
gcc_assert (TYPE_REF_IS_RVALUE (ref_type)
|
||||||
|
&& real_lvalue_p (expr));
|
||||||
|
|
||||||
error ("cannot bind %qT lvalue to %qT",
|
error ("cannot bind %qT lvalue to %qT",
|
||||||
TREE_TYPE (expr), totype);
|
TREE_TYPE (expr), totype);
|
||||||
if (fn)
|
if (fn)
|
||||||
@ -8581,9 +8589,11 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
|
|||||||
{
|
{
|
||||||
if (complain & tf_error)
|
if (complain & tf_error)
|
||||||
{
|
{
|
||||||
if (!CP_TYPE_CONST_P (TREE_TYPE (type))
|
if (conv)
|
||||||
&& !TYPE_REF_IS_RVALUE (type)
|
convert_like (conv, expr, complain);
|
||||||
&& !real_lvalue_p (expr))
|
else if (!CP_TYPE_CONST_P (TREE_TYPE (type))
|
||||||
|
&& !TYPE_REF_IS_RVALUE (type)
|
||||||
|
&& !real_lvalue_p (expr))
|
||||||
error ("invalid initialization of non-const reference of "
|
error ("invalid initialization of non-const reference of "
|
||||||
"type %qT from an rvalue of type %qT",
|
"type %qT from an rvalue of type %qT",
|
||||||
type, TREE_TYPE (expr));
|
type, TREE_TYPE (expr));
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2011-09-12 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* g++.dg/cpp0x/explicit7.C: New.
|
||||||
|
|
||||||
2011-09-12 Jakub Jelinek <jakub@redhat.com>
|
2011-09-12 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR rtl-optimization/50212
|
PR rtl-optimization/50212
|
||||||
|
17
gcc/testsuite/g++.dg/cpp0x/explicit7.C
Normal file
17
gcc/testsuite/g++.dg/cpp0x/explicit7.C
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// [over.match.conv]: For direct-initialization, those explicit conversion
|
||||||
|
// functions that are not hidden within S and yield type T or a type that
|
||||||
|
// can be converted to type T with a qualification conversion (4.4) are
|
||||||
|
// also candidate functions.
|
||||||
|
|
||||||
|
// { dg-options -std=c++0x }
|
||||||
|
|
||||||
|
struct A { };
|
||||||
|
struct B: A { };
|
||||||
|
struct C {
|
||||||
|
explicit operator B*(); // { dg-message "explicit" }
|
||||||
|
explicit operator B&(); // { dg-message "explicit" }
|
||||||
|
};
|
||||||
|
|
||||||
|
C c;
|
||||||
|
A* ap (c); // { dg-error "" }
|
||||||
|
A& ar (c); // { dg-error "" }
|
Loading…
x
Reference in New Issue
Block a user