diff options
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/call.c | 6 | ||||
-rw-r--r-- | gcc/cp/init.c | 26 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C | 32 |
6 files changed, 79 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 564203aae21..88f7d020b32 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,15 @@ 2011-11-02 Jason Merrill <jason@redhat.com> + PR c++/50930 + * init.c (build_aggr_init): Don't set LOOKUP_ONLYCONVERTING + if the initializer has TARGET_EXPR_DIRECT_INIT_P. + (expand_default_init): An initializer with TARGET_EXPR_DIRECT_INIT_P + or TARGET_EXPR_LIST_INIT_P doesn't need more processing. + * tree.c (bot_manip): Propagate TARGET_EXPR_IMPLICIT_P, + TARGET_EXPR_LIST_INIT_P, TARGET_EXPR_DIRECT_INIT_P. + * call.c (convert_like_real): Set TARGET_EXPR_DIRECT_INIT_P + as appropriate on list-value-initialization. + * parser.c (cp_parser_decl_specifier_seq): Change "C++0x" to "C++11" in warnings. (cp_lexer_get_preprocessor_token): Likewise. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 439a1fe7c4f..ce8933afda9 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5655,10 +5655,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, && CONSTRUCTOR_NELTS (expr) == 0 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)) { + bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr); expr = build_value_init (totype, complain); expr = get_target_expr_sfinae (expr, complain); if (expr != error_mark_node) - TARGET_EXPR_LIST_INIT_P (expr) = true; + { + TARGET_EXPR_LIST_INIT_P (expr) = true; + TARGET_EXPR_DIRECT_INIT_P (expr) = direct; + } return expr; } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 6b57eb60a65..ec7ba0e802a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1377,6 +1377,8 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) TREE_THIS_VOLATILE (exp) = 0; if (init && TREE_CODE (init) != TREE_LIST + && !(TREE_CODE (init) == TARGET_EXPR + && TARGET_EXPR_DIRECT_INIT_P (init)) && !(BRACE_ENCLOSED_INITIALIZER_P (init) && CONSTRUCTOR_IS_DIRECT_INIT (init))) flags |= LOOKUP_ONLYCONVERTING; @@ -1459,10 +1461,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, if (init && BRACE_ENCLOSED_INITIALIZER_P (init) && CP_AGGREGATE_TYPE_P (type)) + /* A brace-enclosed initializer for an aggregate. In C++0x this can + happen for direct-initialization, too. */ + init = digest_init (type, init, complain); + + /* A CONSTRUCTOR of the target's type is a previously digested + initializer, whether that happened just above or in + cp_parser_late_parsing_nsdmi. + + A TARGET_EXPR with TARGET_EXPR_DIRECT_INIT_P or TARGET_EXPR_LIST_INIT_P + set represents the whole initialization, so we shouldn't build up + another ctor call. */ + if (init + && (TREE_CODE (init) == CONSTRUCTOR + || (TREE_CODE (init) == TARGET_EXPR + && (TARGET_EXPR_DIRECT_INIT_P (init) + || TARGET_EXPR_LIST_INIT_P (init)))) + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init), type)) { - /* A brace-enclosed initializer for an aggregate. In C++0x this can - happen for direct-initialization, too. */ - init = digest_init (type, init, complain); + /* Early initialization via a TARGET_EXPR only works for + complete objects. */ + gcc_assert (TREE_CODE (init) == CONSTRUCTOR || true_exp == exp); + init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 707f2c8aeba..dc9fc954e41 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1889,6 +1889,10 @@ bot_manip (tree* tp, int* walk_subtrees, void* data) u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t), tf_warning_or_error); + TARGET_EXPR_IMPLICIT_P (u) = TARGET_EXPR_IMPLICIT_P (t); + TARGET_EXPR_LIST_INIT_P (u) = TARGET_EXPR_LIST_INIT_P (t); + TARGET_EXPR_DIRECT_INIT_P (u) = TARGET_EXPR_DIRECT_INIT_P (t); + /* Map the old variable to the new one. */ splay_tree_insert (target_remap, (splay_tree_key) TREE_OPERAND (t, 0), diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2975ff2cec3..52ca3c93016 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-11-02 Jason Merrill <jason@redhat.com> + + PR c++/50930 + * g++.dg/cpp0x/nsdmi-list2.C: New. + 2011-11-02 Paolo Carlini <paolo.carlini@oracle.com> PR c++/50810 diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C new file mode 100644 index 00000000000..a6321ffb605 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C @@ -0,0 +1,32 @@ +// PR c++/50930 +// { dg-options -std=c++0x } + +struct nmc { + nmc() = default; + nmc(nmc&&) = delete; // line 3 +}; + +struct A { // line 6 + nmc n{}; + nmc n2 = {}; +} a; // line 8 + +// ------ + +struct lock_t { + int lock[4]; +}; + +struct pthread_mutex_t { + volatile lock_t __spinlock; +}; + +struct mutex { + pthread_mutex_t m = { }; + mutex() = default; +}; + +int main() +{ + mutex mx; +} |