From 4ea08463a743ae12a5273368c2cc50743818ad48 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 2 Jun 2009 13:02:38 -0400 Subject: [PATCH] re PR c++/40308 (Brace initialization fails for member initializers in constructor for class templates) PR c++/40308 PR c++/40311 * typeck.c (cp_build_modify_expr): Always pass init-lists to the conversion code. * call.c (implicit_conversion): Allow init-list conversion to scalar during direct-initialization, too. Mark the conversion bad if it has too many levels of braces. (convert_like_real): And give a helpful error. From-SVN: r148089 --- gcc/cp/ChangeLog | 11 ++++++++++- gcc/cp/call.c | 26 +++++++++++++++++++------ gcc/cp/typeck.c | 5 ++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.dg/cpp0x/initlist13.C | 5 ++++- gcc/testsuite/g++.dg/cpp0x/initlist18.C | 19 ++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/initlist19.C | 8 ++++++++ 7 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist18.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist19.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 448b5581563..e3eb576e544 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,4 +1,13 @@ -2009-06-01 Jason Merrill +2009-06-02 Jason Merrill + + PR c++/40308 + PR c++/40311 + * typeck.c (cp_build_modify_expr): Always pass init-lists to the + conversion code. + * call.c (implicit_conversion): Allow init-list conversion to scalar + during direct-initialization, too. Mark the conversion bad if it + has too many levels of braces. + (convert_like_real): And give a helpful error. PR c++/40306 PR c++/40307 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 138abe017fe..1ab27c738e2 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1406,21 +1406,27 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, 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)) + scalar type. */ + if (SCALAR_TYPE_P (to)) { + int nelts = CONSTRUCTOR_NELTS (expr); tree elt; - if (CONSTRUCTOR_NELTS (expr) == 1) + + if (nelts == 0) + elt = integer_zero_node; + else if (nelts == 1) elt = CONSTRUCTOR_ELT (expr, 0)->value; else - elt = integer_zero_node; + elt = error_mark_node; + conv = implicit_conversion (to, TREE_TYPE (elt), elt, c_cast_p, flags); if (conv) { conv->check_narrowing = true; + if (BRACE_ENCLOSED_INITIALIZER_P (elt)) + /* Too many levels of braces, i.e. '{{1}}'. */ + conv->bad_p = true; return conv; } } @@ -4698,6 +4704,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, && convs->kind != ck_base) { conversion *t = convs; + + /* Give a helpful error if this is bad because of excess braces. */ + if (BRACE_ENCLOSED_INITIALIZER_P (expr) + && SCALAR_TYPE_P (totype) + && CONSTRUCTOR_NELTS (expr) > 0 + && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value)) + permerror (input_location, "too many braces around initializer for %qT", totype); + for (; t; t = convs->u.next) { if (t->kind == ck_user || !t->bad_p) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 6f6bd3923b0..b384feae1a4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6081,8 +6081,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, if (modifycode == INIT_EXPR) { - if (TREE_CODE (rhs) == CONSTRUCTOR) + if (BRACE_ENCLOSED_INITIALIZER_P (rhs)) + /* Do the default thing. */; + else if (TREE_CODE (rhs) == CONSTRUCTOR) { + /* Compound literal. */ if (! same_type_p (TREE_TYPE (rhs), lhstype)) /* Call convert to generate an error; see PR 11063. */ rhs = convert (lhstype, rhs); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9743b5dafec..fda5ce3068b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2009-06-02 Jason Merrill + * g++.dg/cpp0x/initlist13.C: Remove expected error. + * g++.dg/cpp0x/initlist18.C: New. + * g++.dg/cpp0x/initlist19.C: New. + * g++.dg/cpp0x/auto14.C: New. 2009-06-02 Eric Botcazou diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist13.C b/gcc/testsuite/g++.dg/cpp0x/initlist13.C index 98af92bca53..9ed6c74419f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist13.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist13.C @@ -2,4 +2,7 @@ // { dg-do compile } // { dg-options "-std=gnu++0x" } -__complex__ int i ({0}); // { dg-error "cannot convert" } +#include + +__complex__ int i ({0}); +std::complex i2 ({0}); diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist18.C b/gcc/testsuite/g++.dg/cpp0x/initlist18.C new file mode 100644 index 00000000000..c9a9bcd9415 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist18.C @@ -0,0 +1,19 @@ +// PR c++/40308, 40311 +// { dg-do run } +// { dg-options "-std=c++0x" } + +template< typename T > +struct test { + test() : data{} {} + + T data; +}; + +int main() +{ + test x; + test y; + int * a = new int{}; + int * b = new int{5}; + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist19.C b/gcc/testsuite/g++.dg/cpp0x/initlist19.C new file mode 100644 index 00000000000..418cddc618a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist19.C @@ -0,0 +1,8 @@ +// { dg-options "-std=c++0x" } + +void f(double); +int main() +{ + f({{1}}); // { dg-error "too many braces" } + // { dg-error "" "" { target *-*-* } 6 } allow other errors, too +} -- 2.30.2