From 757f2b35e56a25143c1d2c1b8623f0cb3cb2230d Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 27 May 2009 22:23:41 +0000 Subject: [PATCH] * call.c (implicit_conversion): Handle conversion from initializer-list to scalar. (convert_like_real): Likewise. Avoid crashing on list initialization with bad conversions. (can_convert): Use LOOKUP_EXPLICIT. (can_convert_arg_bad): Add flags parm. * cp-tree.h: Adjust. * typeck.c (convert_for_assignment): Pass flags. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147933 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 11 ++++++ gcc/cp/call.c | 46 +++++++++++++++++++--- gcc/cp/cp-tree.h | 2 +- gcc/cp/typeck.c | 2 +- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp0x/initlist15.C | 17 ++++++++ gcc/testsuite/g++.dg/cpp0x/initlist16.C | 12 ++++++ gcc/testsuite/g++.dg/cpp0x/initlist17.C | 9 +++++ .../error_code/operators/bool_neg.cc | 2 +- .../error_condition/operators/bool_neg.cc | 2 +- 10 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist15.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist16.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist17.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd057f0e3a2..9efd93eb4bd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2009-05-27 Jason Merrill + + * call.c (implicit_conversion): Handle conversion from + initializer-list to scalar. + (convert_like_real): Likewise. Avoid crashing on list + initialization with bad conversions. + (can_convert): Use LOOKUP_EXPLICIT. + (can_convert_arg_bad): Add flags parm. + * cp-tree.h: Adjust. + * typeck.c (convert_for_assignment): Pass flags. + 2009-05-27 Ian Lance Taylor * Make-lang.in (g++$(exeext)): Change $(COMPILER) to $(LINKER). diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a9c036746db..138abe017fe 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1400,9 +1400,31 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, if (conv) return conv; - if (is_std_init_list (to) && expr - && BRACE_ENCLOSED_INITIALIZER_P (expr)) - return build_list_conv (to, expr, flags); + if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)) + { + if (is_std_init_list (to)) + return build_list_conv (to, expr, flags); + + /* Allow conversion from an initializer-list with one element to a + scalar type if this is copy-initialization. Direct-initialization + would be something like int i({1}), which is invalid. */ + if (SCALAR_TYPE_P (to) && CONSTRUCTOR_NELTS (expr) <= 1 + && (flags & LOOKUP_ONLYCONVERTING)) + { + tree elt; + if (CONSTRUCTOR_NELTS (expr) == 1) + elt = CONSTRUCTOR_ELT (expr, 0)->value; + else + elt = integer_zero_node; + conv = implicit_conversion (to, TREE_TYPE (elt), elt, + c_cast_p, flags); + if (conv) + { + conv->check_narrowing = true; + return conv; + } + } + } if (expr != NULL_TREE && (MAYBE_CLASS_TYPE_P (from) @@ -4669,6 +4691,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (convs->bad_p && convs->kind != ck_user + && convs->kind != ck_list && convs->kind != ck_ambig && convs->kind != ck_ref_bind && convs->kind != ck_rvalue @@ -4748,6 +4771,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, return expr; } case ck_identity: + if (BRACE_ENCLOSED_INITIALIZER_P (expr)) + { + int nelts = CONSTRUCTOR_NELTS (expr); + if (nelts == 0) + expr = integer_zero_node; + else if (nelts == 1) + expr = CONSTRUCTOR_ELT (expr, 0)->value; + else + gcc_unreachable (); + } + if (type_unknown_p (expr)) expr = instantiate_type (totype, expr, complain); /* Convert a constant to its underlying value, unless we are @@ -7185,7 +7219,7 @@ tourney (struct z_candidate *candidates) bool can_convert (tree to, tree from) { - return can_convert_arg (to, from, NULL_TREE, LOOKUP_NORMAL); + return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT); } /* Returns nonzero if ARG (of type FROM) can be converted to TO. */ @@ -7213,7 +7247,7 @@ can_convert_arg (tree to, tree from, tree arg, int flags) /* Like can_convert_arg, but allows dubious conversions as well. */ bool -can_convert_arg_bad (tree to, tree from, tree arg) +can_convert_arg_bad (tree to, tree from, tree arg, int flags) { conversion *t; void *p; @@ -7222,7 +7256,7 @@ can_convert_arg_bad (tree to, tree from, tree arg) p = conversion_obstack_alloc (0); /* Try to perform the conversion. */ t = implicit_conversion (to, from, arg, /*c_cast_p=*/false, - LOOKUP_NORMAL); + flags); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 79bc9284b0a..e47369501c6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4191,7 +4191,7 @@ extern tree build_op_call (tree, VEC(tree,gc) **, extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); extern bool can_convert (tree, tree); extern bool can_convert_arg (tree, tree, tree, int); -extern bool can_convert_arg_bad (tree, tree, tree); +extern bool can_convert_arg_bad (tree, tree, tree, int); extern bool enforce_access (tree, tree, tree); extern tree convert_default_arg (tree, tree, tree, int); extern tree convert_arg_to_ellipsis (tree); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d7fddb11211..29ae831488f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6702,7 +6702,7 @@ convert_for_assignment (tree type, tree rhs, We allow bad conversions here because by the time we get to this point we are committed to doing the conversion. If we end up doing a bad conversion, convert_like will complain. */ - if (!can_convert_arg_bad (type, rhstype, rhs)) + if (!can_convert_arg_bad (type, rhstype, rhs, flags)) { /* When -Wno-pmf-conversions is use, we just silently allow conversions from pointers-to-members to plain pointers. If diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3d6f394f691..f47ac1fad89 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-05-27 Jason Merrill + + * g++.dg/cpp0x/initlist15.C: New. + * g++.dg/cpp0x/initlist16.C: New. + * g++.dg/cpp0x/initlist17.C: New. + 2009-05-27 Janne Blomqvist PR fortran/39178 diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist15.C b/gcc/testsuite/g++.dg/cpp0x/initlist15.C new file mode 100644 index 00000000000..d59e5af640b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist15.C @@ -0,0 +1,17 @@ +// { dg-options "-std=c++0x" } + +#include +#include + +using namespace std; + +template< typename ... ArgTypes > +void test( ArgTypes ... args ) { + vector x = { &typeid(ArgTypes)... }; // { dg-error "" } +} + +int main() +{ + test( 1, 3.14f, 2.78 ); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist16.C b/gcc/testsuite/g++.dg/cpp0x/initlist16.C new file mode 100644 index 00000000000..86a00396051 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist16.C @@ -0,0 +1,12 @@ +// { dg-options "-std=c++0x" } +// { dg-do run } + +extern "C" void abort(); + +void f(int i) { if (i != 42) abort(); } + +int main() +{ + f({42}); + return {0}; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist17.C b/gcc/testsuite/g++.dg/cpp0x/initlist17.C new file mode 100644 index 00000000000..86371e81969 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist17.C @@ -0,0 +1,9 @@ +// { dg-options "-std=c++0x" } + +void f(int i); + +int main() +{ + f({42.0}); // { dg-error "narrowing" } + return {1.0}; // { dg-error "narrowing" } +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/bool_neg.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/bool_neg.cc index 554b59f3e7a..539dd891cd5 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/bool_neg.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/operators/bool_neg.cc @@ -30,4 +30,4 @@ int main() return i; } -// { dg-error "could not convert" "" { target *-*-* } 28 } +// { dg-error "cannot convert" "" { target *-*-* } 28 } diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/bool_neg.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/bool_neg.cc index 776179f3efa..6b8d129d2ff 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/bool_neg.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/operators/bool_neg.cc @@ -29,4 +29,4 @@ int test01() return i; } -// { dg-error "could not convert" "" { target *-*-* } 27 } +// { dg-error "cannot convert" "" { target *-*-* } 27 } -- 2.11.0