From: Jason Merrill Date: Wed, 12 May 2010 17:34:38 +0000 (-0400) Subject: cp-tree.h (LOOKUP_LIST_ONLY): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d451d5b28fe184ef45c1275a544c91937b790bd8;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3872df21d16..97dcc8d7aec 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2010-05-12 Jason Merrill + * 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 x.operator type(). (convert_class_to_reference): Set LOOKUP_NO_CONVERSION. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 204a6bbcfc1..c618b2938af 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2860,6 +2860,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) if (ctors) { int ctorflags = flags; + bool try_single_arg = true; ctors = BASELINK_FUNCTIONS (ctors); 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) /* For list-initialization we consider explicit constructors, but give an error if one is selected. */ 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)) - args = make_tree_vector_single (expr); + ctorflags |= LOOKUP_LIST_ONLY; else - { - 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; - } + try_single_arg = false; } - else - args = make_tree_vector_single (expr); /* We should never try to call the abstract or base constructor from here. */ gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors))); - add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false, - TYPE_BINFO (totype), TYPE_BINFO (totype), - ctorflags, &candidates); + /* If EXPR is not an initializer-list, or if totype has a list + constructor, try EXPR as a single argument. */ + 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) { @@ -4009,6 +4026,7 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, { tree ctype; const VEC(tree,gc) *non_static_args; + bool check_list_ctor; bool check_converting; unification_kind_t strict; tree fn; @@ -4020,6 +4038,7 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, fn = OVL_CURRENT (fns); if (DECL_CONV_FN_P (fn)) { + check_list_ctor = false; check_converting = !!(flags & LOOKUP_ONLYCONVERTING); if (flags & LOOKUP_NO_CONVERSION) /* We're doing return_type(x). */ @@ -4036,9 +4055,15 @@ add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, else { if (DECL_CONSTRUCTOR_P (fn)) - check_converting = !!(flags & LOOKUP_ONLYCONVERTING); + { + check_list_ctor = !!(flags & LOOKUP_LIST_ONLY); + check_converting = !!(flags & LOOKUP_ONLYCONVERTING); + } else - check_converting = false; + { + check_list_ctor = false; + check_converting = false; + } strict = DEDUCE_CALL; 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, if (check_converting && DECL_NONCONVERTING_P (fn)) continue; + if (check_list_ctor && !is_list_ctor (fn)) + continue; /* Figure out which set of arguments to use. */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) @@ -6188,6 +6215,8 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, tree orig_fns; VEC(tree,gc) *orig_args = NULL; void *p; + tree list = NULL_TREE; + bool try_normal; gcc_assert (instance != NULL_TREE); @@ -6300,15 +6329,20 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, name = complete_dtor_identifier; /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form - initializer, not T({ }). If the type doesn't have a list ctor, - break apart the list into separate ctor args. */ + initializer, not T({ }). If the type doesn't have a list ctor (or no + 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) && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0)) - && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)) - && !TYPE_HAS_LIST_CTOR (basetype)) + && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0))) { 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; @@ -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. */ p = conversion_obstack_alloc (0); - add_candidates (fns, first_mem_arg, args ? *args : NULL, optype, - explicit_targs, template_only, conversion_path, - access_binfo, flags, &candidates); + any_viable_p = false; + if (try_normal) + { + 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 (complain & tf_error) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index df961e04856..6b35fb97ebc 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4137,6 +4137,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; #define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1) /* This is the first parameter of a copy constructor. */ #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) \ (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a431f8af503..f0f5c2390a9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2010-05-12 Jason Merrill + * g++.dg/cpp0x/initlist32.C: New. + * g++.dg/template/conv11.C: New. * g++.dg/conversion/op1.C: Adjust expected error. diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist32.C b/gcc/testsuite/g++.dg/cpp0x/initlist32.C new file mode 100644 index 00000000000..78bbb5ef996 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist32.C @@ -0,0 +1,21 @@ +// Test that we try normal init if no list ctor is viable. +// { dg-options "-std=c++0x" } + +#include + +struct B {}; + +struct C +{ + C(B); +}; + +struct A +{ + A(std::initializer_list); + A(B) { } + A(C); +}; + +B b; +A a{b};