Commit 4561285b by Jason Merrill Committed by Jason Merrill

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
parent 6602e7fc
2014-04-11 Jason Merrill <jason@redhat.com>
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 <rguenther@suse.de> 2014-04-10 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com> Jakub Jelinek <jakub@redhat.com>
......
...@@ -206,7 +206,7 @@ static conversion *maybe_handle_ref_bind (conversion **); ...@@ -206,7 +206,7 @@ static conversion *maybe_handle_ref_bind (conversion **);
static void maybe_handle_implicit_object (conversion **); static void maybe_handle_implicit_object (conversion **);
static struct z_candidate *add_candidate static struct z_candidate *add_candidate
(struct z_candidate **, tree, tree, const vec<tree, va_gc> *, size_t, (struct z_candidate **, tree, tree, const vec<tree, va_gc> *, size_t,
conversion **, tree, tree, int, struct rejection_reason *); conversion **, tree, tree, int, struct rejection_reason *, int);
static tree source_type (conversion *); static tree source_type (conversion *);
static void add_warning (struct z_candidate *, struct z_candidate *); static void add_warning (struct z_candidate *, struct z_candidate *);
static bool reference_compatible_p (tree, tree); static bool reference_compatible_p (tree, tree);
...@@ -520,7 +520,6 @@ struct z_candidate { ...@@ -520,7 +520,6 @@ struct z_candidate {
sequence from the type returned by FN to the desired destination sequence from the type returned by FN to the desired destination
type. */ type. */
conversion *second_conv; conversion *second_conv;
int viable;
struct rejection_reason *reason; struct rejection_reason *reason;
/* If FN is a member function, the binfo indicating the path used to /* 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 qualify the name of FN at the call site. This path is used to
...@@ -538,6 +537,10 @@ struct z_candidate { ...@@ -538,6 +537,10 @@ struct z_candidate {
tree explicit_targs; tree explicit_targs;
candidate_warning *warnings; candidate_warning *warnings;
z_candidate *next; 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 /* Returns true iff T is a null pointer constant in the sense of
...@@ -1810,7 +1813,8 @@ add_candidate (struct z_candidate **candidates, ...@@ -1810,7 +1813,8 @@ add_candidate (struct z_candidate **candidates,
tree fn, tree first_arg, const vec<tree, va_gc> *args, tree fn, tree first_arg, const vec<tree, va_gc> *args,
size_t num_convs, conversion **convs, size_t num_convs, conversion **convs,
tree access_path, tree conversion_path, 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 *) struct z_candidate *cand = (struct z_candidate *)
conversion_obstack_alloc (sizeof (struct z_candidate)); conversion_obstack_alloc (sizeof (struct z_candidate));
...@@ -1825,6 +1829,7 @@ add_candidate (struct z_candidate **candidates, ...@@ -1825,6 +1829,7 @@ add_candidate (struct z_candidate **candidates,
cand->viable = viable; cand->viable = viable;
cand->reason = reason; cand->reason = reason;
cand->next = *candidates; cand->next = *candidates;
cand->flags = flags;
*candidates = cand; *candidates = cand;
return cand; return cand;
...@@ -2061,7 +2066,7 @@ add_function_candidate (struct z_candidate **candidates, ...@@ -2061,7 +2066,7 @@ add_function_candidate (struct z_candidate **candidates,
out: out:
return add_candidate (candidates, fn, orig_first_arg, args, len, convs, 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 /* 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, ...@@ -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, 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 static void
...@@ -2238,7 +2243,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, ...@@ -2238,7 +2243,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
num_convs, convs, num_convs, convs,
/*access_path=*/NULL_TREE, /*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
viable, reason); viable, reason, flags);
} }
static bool static bool
...@@ -3056,7 +3061,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, ...@@ -3056,7 +3061,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
return cand; return cand;
fail: fail:
return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL, 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) ...@@ -7219,7 +7224,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
return error_mark_node; 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. /* Build and return a call to FN, using NARGS arguments in ARGARRAY.
......
...@@ -101,12 +101,14 @@ c-common.h, not after. ...@@ -101,12 +101,14 @@ c-common.h, not after.
FNDECL_USED_AUTO (in FUNCTION_DECL) FNDECL_USED_AUTO (in FUNCTION_DECL)
DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
REF_PARENTHESIZED_P (in COMPONENT_REF, SCOPE_REF) 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). 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV) ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK) FN_TRY_BLOCK_P (in TRY_BLOCK)
IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE) IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE)
BIND_EXPR_BODY_BLOCK (in BIND_EXPR) BIND_EXPR_BODY_BLOCK (in BIND_EXPR)
DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL) 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, 4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL). or FIELD_DECL).
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
...@@ -3026,6 +3028,10 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -3026,6 +3028,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
should be performed at instantiation time. */ should be performed at instantiation time. */
#define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0 (CALL_EXPR_CHECK (NODE)) #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 /* Indicates whether a string literal has been parenthesized. Such
usages are disallowed in certain circumstances. */ usages are disallowed in certain circumstances. */
......
...@@ -3867,6 +3867,7 @@ simplify_aggr_init_expr (tree *tp) ...@@ -3867,6 +3867,7 @@ simplify_aggr_init_expr (tree *tp)
aggr_init_expr_nargs (aggr_init_expr), aggr_init_expr_nargs (aggr_init_expr),
AGGR_INIT_EXPR_ARGP (aggr_init_expr)); AGGR_INIT_EXPR_ARGP (aggr_init_expr));
TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr); TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr);
tree ret = call_expr;
if (style == ctor) if (style == ctor)
{ {
...@@ -3882,7 +3883,7 @@ simplify_aggr_init_expr (tree *tp) ...@@ -3882,7 +3883,7 @@ simplify_aggr_init_expr (tree *tp)
expand_call{,_inline}. */ expand_call{,_inline}. */
cxx_mark_addressable (slot); cxx_mark_addressable (slot);
CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true; 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) else if (style == pcc)
{ {
...@@ -3890,11 +3891,25 @@ simplify_aggr_init_expr (tree *tp) ...@@ -3890,11 +3891,25 @@ simplify_aggr_init_expr (tree *tp)
need to copy the returned value out of the static buffer into the need to copy the returned value out of the static buffer into the
SLOT. */ SLOT. */
push_deferring_access_checks (dk_no_check); push_deferring_access_checks (dk_no_check);
call_expr = build_aggr_init (slot, call_expr, ret = build_aggr_init (slot, ret,
DIRECT_BIND | LOOKUP_ONLYCONVERTING, DIRECT_BIND | LOOKUP_ONLYCONVERTING,
tf_warning_or_error); tf_warning_or_error);
pop_deferring_access_checks (); 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)) if (AGGR_INIT_ZERO_FIRST (aggr_init_expr))
...@@ -3902,11 +3917,10 @@ simplify_aggr_init_expr (tree *tp) ...@@ -3902,11 +3917,10 @@ simplify_aggr_init_expr (tree *tp)
tree init = build_zero_init (type, NULL_TREE, tree init = build_zero_init (type, NULL_TREE,
/*static_storage_p=*/false); /*static_storage_p=*/false);
init = build2 (INIT_EXPR, void_type_node, slot, init); init = build2 (INIT_EXPR, void_type_node, slot, init);
call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr), ret = build2 (COMPOUND_EXPR, TREE_TYPE (ret), init, ret);
init, call_expr);
} }
*tp = call_expr; *tp = ret;
} }
/* Emit all thunks to FN that should be emitted when FN is emitted. */ /* Emit all thunks to FN that should be emitted when FN is emitted. */
......
...@@ -453,6 +453,7 @@ build_aggr_init_expr (tree type, tree init) ...@@ -453,6 +453,7 @@ build_aggr_init_expr (tree type, tree init)
TREE_SIDE_EFFECTS (rval) = 1; TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval) = is_ctor; AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
TREE_NOTHROW (rval) = TREE_NOTHROW (init); TREE_NOTHROW (rval) = TREE_NOTHROW (init);
CALL_EXPR_LIST_INIT_P (rval) = CALL_EXPR_LIST_INIT_P (init);
} }
else else
rval = init; rval = init;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment