Commit d451d5b2 by Jason Merrill Committed by Jason Merrill

cp-tree.h (LOOKUP_LIST_ONLY): New.

	* cp-tree.h (LOOKUP_LIST_ONLY): New.
	* call.c (add_candidates): Enforce it.
	(build_new_method_call): Try non-list ctor if no viable list ctor.
	(build_user_type_conversion_1): Likewise.

From-SVN: r159334
parent 404f08f8
2010-05-12 Jason Merrill <jason@redhat.com> 2010-05-12 Jason Merrill <jason@redhat.com>
* cp-tree.h (LOOKUP_LIST_ONLY): New.
* call.c (add_candidates): Enforce it.
(build_new_method_call): Try non-list ctor if no viable list ctor.
(build_user_type_conversion_1): Likewise.
* call.c (add_candidates): Distinguish between type(x) and * call.c (add_candidates): Distinguish between type(x) and
x.operator type(). x.operator type().
(convert_class_to_reference): Set LOOKUP_NO_CONVERSION. (convert_class_to_reference): Set LOOKUP_NO_CONVERSION.
......
...@@ -2860,6 +2860,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2860,6 +2860,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (ctors) if (ctors)
{ {
int ctorflags = flags; int ctorflags = flags;
bool try_single_arg = true;
ctors = BASELINK_FUNCTIONS (ctors); ctors = BASELINK_FUNCTIONS (ctors);
first_arg = build_int_cst (build_pointer_type (totype), 0); first_arg = build_int_cst (build_pointer_type (totype), 0);
...@@ -2868,28 +2869,44 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2868,28 +2869,44 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
/* For list-initialization we consider explicit constructors, but /* For list-initialization we consider explicit constructors, but
give an error if one is selected. */ give an error if one is selected. */
ctorflags &= ~LOOKUP_ONLYCONVERTING; ctorflags &= ~LOOKUP_ONLYCONVERTING;
/* If the class has a list ctor, try passing the list as a single
argument first, but only consider list ctors. */
if (TYPE_HAS_LIST_CTOR (totype)) if (TYPE_HAS_LIST_CTOR (totype))
args = make_tree_vector_single (expr); ctorflags |= LOOKUP_LIST_ONLY;
else else
{ try_single_arg = false;
args = ctor_to_vec (expr);
/* We still allow more conversions within an init-list. */
ctorflags &= ~LOOKUP_NO_CONVERSION;
/* But not for the copy ctor. */
ctorflags |= LOOKUP_NO_COPY_CTOR_CONVERSION;
}
} }
else
args = make_tree_vector_single (expr);
/* We should never try to call the abstract or base constructor /* We should never try to call the abstract or base constructor
from here. */ from here. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors))); && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false, /* If EXPR is not an initializer-list, or if totype has a list
TYPE_BINFO (totype), TYPE_BINFO (totype), constructor, try EXPR as a single argument. */
ctorflags, &candidates); if (try_single_arg)
{
args = make_tree_vector_single (expr);
add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
TYPE_BINFO (totype), TYPE_BINFO (totype),
ctorflags, &candidates);
}
/* If we didn't find a suitable list constructor for an initializer-list,
try breaking it apart. */
if (!candidates && BRACE_ENCLOSED_INITIALIZER_P (expr))
{
args = ctor_to_vec (expr);
/* We aren't looking for list-ctors anymore. */
ctorflags &= ~LOOKUP_LIST_ONLY;
/* We still allow more conversions within an init-list. */
ctorflags &= ~LOOKUP_NO_CONVERSION;
/* But not for the copy ctor. */
ctorflags |= LOOKUP_NO_COPY_CTOR_CONVERSION;
add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
TYPE_BINFO (totype), TYPE_BINFO (totype),
ctorflags, &candidates);
}
for (cand = candidates; cand; cand = cand->next) for (cand = candidates; cand; cand = cand->next)
{ {
...@@ -4009,6 +4026,7 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, ...@@ -4009,6 +4026,7 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
{ {
tree ctype; tree ctype;
const VEC(tree,gc) *non_static_args; const VEC(tree,gc) *non_static_args;
bool check_list_ctor;
bool check_converting; bool check_converting;
unification_kind_t strict; unification_kind_t strict;
tree fn; tree fn;
...@@ -4020,6 +4038,7 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, ...@@ -4020,6 +4038,7 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
fn = OVL_CURRENT (fns); fn = OVL_CURRENT (fns);
if (DECL_CONV_FN_P (fn)) if (DECL_CONV_FN_P (fn))
{ {
check_list_ctor = false;
check_converting = !!(flags & LOOKUP_ONLYCONVERTING); check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
if (flags & LOOKUP_NO_CONVERSION) if (flags & LOOKUP_NO_CONVERSION)
/* We're doing return_type(x). */ /* We're doing return_type(x). */
...@@ -4036,9 +4055,15 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, ...@@ -4036,9 +4055,15 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
else else
{ {
if (DECL_CONSTRUCTOR_P (fn)) if (DECL_CONSTRUCTOR_P (fn))
check_converting = !!(flags & LOOKUP_ONLYCONVERTING); {
check_list_ctor = !!(flags & LOOKUP_LIST_ONLY);
check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
}
else else
check_converting = false; {
check_list_ctor = false;
check_converting = false;
}
strict = DEDUCE_CALL; strict = DEDUCE_CALL;
ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE; ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
} }
...@@ -4058,6 +4083,8 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, ...@@ -4058,6 +4083,8 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
if (check_converting && DECL_NONCONVERTING_P (fn)) if (check_converting && DECL_NONCONVERTING_P (fn))
continue; continue;
if (check_list_ctor && !is_list_ctor (fn))
continue;
/* Figure out which set of arguments to use. */ /* Figure out which set of arguments to use. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
...@@ -6188,6 +6215,8 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, ...@@ -6188,6 +6215,8 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
tree orig_fns; tree orig_fns;
VEC(tree,gc) *orig_args = NULL; VEC(tree,gc) *orig_args = NULL;
void *p; void *p;
tree list = NULL_TREE;
bool try_normal;
gcc_assert (instance != NULL_TREE); gcc_assert (instance != NULL_TREE);
...@@ -6300,15 +6329,20 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, ...@@ -6300,15 +6329,20 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
name = complete_dtor_identifier; name = complete_dtor_identifier;
/* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
initializer, not T({ }). If the type doesn't have a list ctor, initializer, not T({ }). If the type doesn't have a list ctor (or no
break apart the list into separate ctor args. */ viable list ctor), break apart the list into separate ctor args. */
try_normal = true;
if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args) if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args)
&& BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0)) && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0))
&& CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)) && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)))
&& !TYPE_HAS_LIST_CTOR (basetype))
{ {
gcc_assert (VEC_length (tree, *args) == 1); gcc_assert (VEC_length (tree, *args) == 1);
*args = ctor_to_vec (VEC_index (tree, *args, 0)); list = VEC_index (tree, *args, 0);
if (TYPE_HAS_LIST_CTOR (basetype))
flags |= LOOKUP_LIST_ONLY;
else
try_normal = false;
} }
first_mem_arg = instance_ptr; first_mem_arg = instance_ptr;
...@@ -6316,11 +6350,25 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, ...@@ -6316,11 +6350,25 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
/* Get the high-water mark for the CONVERSION_OBSTACK. */ /* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0); p = conversion_obstack_alloc (0);
add_candidates (fns, first_mem_arg, args ? *args : NULL, optype, any_viable_p = false;
explicit_targs, template_only, conversion_path, if (try_normal)
access_binfo, flags, &candidates); {
add_candidates (fns, first_mem_arg, user_args, optype,
explicit_targs, template_only, conversion_path,
access_binfo, flags, &candidates);
candidates = splice_viable (candidates, pedantic, &any_viable_p);
}
if (!any_viable_p && list)
{
VEC(tree,gc) *list_args = ctor_to_vec (list);
flags &= ~LOOKUP_LIST_ONLY;
add_candidates (fns, first_mem_arg, list_args, optype,
explicit_targs, template_only, conversion_path,
access_binfo, flags, &candidates);
candidates = splice_viable (candidates, pedantic, &any_viable_p);
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p) if (!any_viable_p)
{ {
if (complain & tf_error) if (complain & tf_error)
......
...@@ -4137,6 +4137,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; ...@@ -4137,6 +4137,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
#define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1) #define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1)
/* This is the first parameter of a copy constructor. */ /* This is the first parameter of a copy constructor. */
#define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1) #define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1)
/* We only want to consider list constructors. */
#define LOOKUP_LIST_ONLY (LOOKUP_COPY_PARM << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \ #define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
......
2010-05-12 Jason Merrill <jason@redhat.com> 2010-05-12 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/initlist32.C: New.
* g++.dg/template/conv11.C: New. * g++.dg/template/conv11.C: New.
* g++.dg/conversion/op1.C: Adjust expected error. * g++.dg/conversion/op1.C: Adjust expected error.
......
// Test that we try normal init if no list ctor is viable.
// { dg-options "-std=c++0x" }
#include <initializer_list>
struct B {};
struct C
{
C(B);
};
struct A
{
A(std::initializer_list<int>);
A(B) { }
A(C);
};
B b;
A a{b};
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