From 4561285bf4a239e6ae6cb03245baff788cea025a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 11 Apr 2014 13:08:47 -0400 Subject: [PATCH] DR 1030 PR c++/51253 DR 1030 PR c++/51253 * cp-tree.h (CALL_EXPR_LIST_INIT_P): New. * call.c (struct z_candidate): Add flags field. (add_candidate): Add flags parm. (add_function_candidate, add_conv_candidate, build_builtin_candidate) (add_template_candidate_real): Pass it. (build_over_call): Set CALL_EXPR_LIST_INIT_P. * tree.c (build_aggr_init_expr): Copy it. * semantics.c (simplify_aggr_init_expr): Preevaluate args if it's set. From-SVN: r209309 --- gcc/cp/ChangeLog | 13 +++++++++++++ gcc/cp/call.c | 25 +++++++++++++++++-------- gcc/cp/cp-tree.h | 6 ++++++ gcc/cp/semantics.c | 30 ++++++++++++++++++++++-------- gcc/cp/tree.c | 1 + 5 files changed, 59 insertions(+), 16 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index afbf24ace950..77473fef3b00 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2014-04-11 Jason Merrill + + DR 1030 + PR c++/51253 + * cp-tree.h (CALL_EXPR_LIST_INIT_P): New. + * call.c (struct z_candidate): Add flags field. + (add_candidate): Add flags parm. + (add_function_candidate, add_conv_candidate, build_builtin_candidate) + (add_template_candidate_real): Pass it. + (build_over_call): Set CALL_EXPR_LIST_INIT_P. + * tree.c (build_aggr_init_expr): Copy it. + * semantics.c (simplify_aggr_init_expr): Preevaluate args if it's set. + 2014-04-10 Richard Biener Jakub Jelinek diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ae0d4fff9744..7c0dcc2d57a9 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -206,7 +206,7 @@ static conversion *maybe_handle_ref_bind (conversion **); static void maybe_handle_implicit_object (conversion **); static struct z_candidate *add_candidate (struct z_candidate **, tree, tree, const vec *, size_t, - conversion **, tree, tree, int, struct rejection_reason *); + conversion **, tree, tree, int, struct rejection_reason *, int); static tree source_type (conversion *); static void add_warning (struct z_candidate *, struct z_candidate *); static bool reference_compatible_p (tree, tree); @@ -520,7 +520,6 @@ struct z_candidate { sequence from the type returned by FN to the desired destination type. */ conversion *second_conv; - int viable; struct rejection_reason *reason; /* If FN is a member function, the binfo indicating the path used to qualify the name of FN at the call site. This path is used to @@ -538,6 +537,10 @@ struct z_candidate { tree explicit_targs; candidate_warning *warnings; z_candidate *next; + int viable; + + /* The flags active in add_candidate. */ + int flags; }; /* Returns true iff T is a null pointer constant in the sense of @@ -1810,7 +1813,8 @@ add_candidate (struct z_candidate **candidates, tree fn, tree first_arg, const vec *args, size_t num_convs, conversion **convs, tree access_path, tree conversion_path, - int viable, struct rejection_reason *reason) + int viable, struct rejection_reason *reason, + int flags) { struct z_candidate *cand = (struct z_candidate *) conversion_obstack_alloc (sizeof (struct z_candidate)); @@ -1825,6 +1829,7 @@ add_candidate (struct z_candidate **candidates, cand->viable = viable; cand->reason = reason; cand->next = *candidates; + cand->flags = flags; *candidates = cand; return cand; @@ -2061,7 +2066,7 @@ add_function_candidate (struct z_candidate **candidates, out: return add_candidate (candidates, fn, orig_first_arg, args, len, convs, - access_path, conversion_path, viable, reason); + access_path, conversion_path, viable, reason, flags); } /* Create an overload candidate for the conversion function FN which will @@ -2163,7 +2168,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, } return add_candidate (candidates, totype, first_arg, arglist, len, convs, - access_path, conversion_path, viable, reason); + access_path, conversion_path, viable, reason, flags); } static void @@ -2238,7 +2243,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, num_convs, convs, /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE, - viable, reason); + viable, reason, flags); } static bool @@ -3056,7 +3061,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, return cand; fail: return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL, - access_path, conversion_path, 0, reason); + access_path, conversion_path, 0, reason, flags); } @@ -7219,7 +7224,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return error_mark_node; } - return build_cxx_call (fn, nargs, argarray, complain|decltype_flag); + tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag); + if (TREE_CODE (call) == CALL_EXPR + && (cand->flags & LOOKUP_LIST_INIT_CTOR)) + CALL_EXPR_LIST_INIT_P (call) = true; + return call; } /* Build and return a call to FN, using NARGS arguments in ARGARRAY. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e9fe86ee4cd1..bafc32d57cd9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -101,12 +101,14 @@ c-common.h, not after. FNDECL_USED_AUTO (in FUNCTION_DECL) DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) REF_PARENTHESIZED_P (in COMPONENT_REF, SCOPE_REF) + AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR) 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE) BIND_EXPR_BODY_BLOCK (in BIND_EXPR) DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL) + CALL_EXPR_LIST_INIT_P (in CALL_EXPR, AGGR_INIT_EXPR) 4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) @@ -3026,6 +3028,10 @@ extern void decl_shadowed_for_var_insert (tree, tree); should be performed at instantiation time. */ #define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0 (CALL_EXPR_CHECK (NODE)) +/* True if CALL_EXPR expresses list-initialization of an object. */ +#define CALL_EXPR_LIST_INIT_P(NODE) \ + TREE_LANG_FLAG_3 (TREE_CHECK2 ((NODE),CALL_EXPR,AGGR_INIT_EXPR)) + /* Indicates whether a string literal has been parenthesized. Such usages are disallowed in certain circumstances. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3619e271df0b..795086a58543 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3867,6 +3867,7 @@ simplify_aggr_init_expr (tree *tp) aggr_init_expr_nargs (aggr_init_expr), AGGR_INIT_EXPR_ARGP (aggr_init_expr)); TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr); + tree ret = call_expr; if (style == ctor) { @@ -3882,7 +3883,7 @@ simplify_aggr_init_expr (tree *tp) expand_call{,_inline}. */ cxx_mark_addressable (slot); CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true; - call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr); + ret = build2 (INIT_EXPR, TREE_TYPE (ret), slot, ret); } else if (style == pcc) { @@ -3890,11 +3891,25 @@ simplify_aggr_init_expr (tree *tp) need to copy the returned value out of the static buffer into the SLOT. */ push_deferring_access_checks (dk_no_check); - call_expr = build_aggr_init (slot, call_expr, - DIRECT_BIND | LOOKUP_ONLYCONVERTING, - tf_warning_or_error); + ret = build_aggr_init (slot, ret, + DIRECT_BIND | LOOKUP_ONLYCONVERTING, + tf_warning_or_error); pop_deferring_access_checks (); - call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); + ret = build2 (COMPOUND_EXPR, TREE_TYPE (slot), ret, slot); + } + + /* DR 1030 says that we need to evaluate the elements of an + initializer-list in forward order even when it's used as arguments to + a constructor. So if the target wants to evaluate them in reverse + order and there's more than one argument other than 'this', force + pre-evaluation. */ + if (PUSH_ARGS_REVERSED && CALL_EXPR_LIST_INIT_P (aggr_init_expr) + && aggr_init_expr_nargs (aggr_init_expr) > 2) + { + tree preinit; + stabilize_call (call_expr, &preinit); + if (preinit) + ret = build2 (COMPOUND_EXPR, TREE_TYPE (ret), preinit, ret); } if (AGGR_INIT_ZERO_FIRST (aggr_init_expr)) @@ -3902,11 +3917,10 @@ simplify_aggr_init_expr (tree *tp) tree init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); init = build2 (INIT_EXPR, void_type_node, slot, init); - call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr), - init, call_expr); + ret = build2 (COMPOUND_EXPR, TREE_TYPE (ret), init, ret); } - *tp = call_expr; + *tp = ret; } /* Emit all thunks to FN that should be emitted when FN is emitted. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 3429d2396f2d..4b39b9039c69 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -453,6 +453,7 @@ build_aggr_init_expr (tree type, tree init) TREE_SIDE_EFFECTS (rval) = 1; AGGR_INIT_VIA_CTOR_P (rval) = is_ctor; TREE_NOTHROW (rval) = TREE_NOTHROW (init); + CALL_EXPR_LIST_INIT_P (rval) = CALL_EXPR_LIST_INIT_P (init); } else rval = init; -- 2.43.5