}
}
-/* Look up the binding of the function parameter T in a constexpr
- function call context CALL. */
-
-static tree
-lookup_parameter_binding (const constexpr_call *call, tree t)
-{
- tree b = purpose_member (t, call->bindings);
- return TREE_VALUE (b);
-}
-
/* Attempt to evaluate T which represents a call to a builtin function.
We assume here that all builtin functions evaluate to scalar types
represented by _CST nodes. */
return cp_fold_convert (type, temp);
}
-/* True if we want to use the new handling of constexpr calls based on
- DECL_SAVED_TREE. */
-#define use_new_call true
-
/* Subroutine of cxx_eval_call_expression.
We are processing a call expression (either CALL_EXPR or
AGGR_INIT_EXPR) in the context of CTX. Evaluate
x = cp_build_addr_expr (x, tf_warning_or_error);
}
bool lval = false;
- if (parms && DECL_BY_REFERENCE (parms) && !use_new_call)
- {
- /* cp_genericize made this a reference for argument passing, but
- we don't want to treat it like one for C++11 constexpr
- evaluation. C++14 constexpr evaluation uses the genericized
- DECL_SAVED_TREE. */
- gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
- gcc_assert (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE);
- type = TREE_TYPE (type);
- x = convert_from_reference (x);
- lval = true;
- }
arg = cxx_eval_constant_expression (ctx, x, lval,
non_constant_p, overflow_p);
/* Don't VERIFY_CONSTANT here. */
{
if (!result || result == error_mark_node)
{
- if (!use_new_call)
+ if (DECL_SAVED_TREE (fun) == NULL_TREE
+ && (DECL_CONSTRUCTOR_P (fun) || DECL_DESTRUCTOR_P (fun)))
+ /* The maybe-in-charge 'tor had its DECL_SAVED_TREE
+ cleared, try a clone. */
+ for (fun = DECL_CHAIN (fun);
+ fun && DECL_CLONED_FUNCTION_P (fun);
+ fun = DECL_CHAIN (fun))
+ if (DECL_SAVED_TREE (fun))
+ break;
+ gcc_assert (DECL_SAVED_TREE (fun));
+ tree parms, res;
+
+ /* Unshare the whole function body. */
+ tree body = copy_fn (fun, parms, res);
+
+ /* Associate the bindings with the remapped parms. */
+ tree bound = new_call.bindings;
+ tree remapped = parms;
+ while (bound)
{
- new_ctx.call = &new_call;
- result = (cxx_eval_constant_expression
- (&new_ctx, new_call.fundef->body,
- lval,
- non_constant_p, overflow_p));
+ tree oparm = TREE_PURPOSE (bound);
+ tree arg = TREE_VALUE (bound);
+ gcc_assert (DECL_NAME (remapped) == DECL_NAME (oparm));
+ ctx->values->put (remapped, arg);
+ bound = TREE_CHAIN (bound);
+ remapped = DECL_CHAIN (remapped);
}
- else
+ /* Add the RESULT_DECL to the values map, too. */
+ tree slot = NULL_TREE;
+ if (DECL_BY_REFERENCE (res))
{
- if (DECL_SAVED_TREE (fun) == NULL_TREE
- && (DECL_CONSTRUCTOR_P (fun) || DECL_DESTRUCTOR_P (fun)))
- /* The maybe-in-charge 'tor had its DECL_SAVED_TREE
- cleared, try a clone. */
- for (fun = DECL_CHAIN (fun);
- fun && DECL_CLONED_FUNCTION_P (fun);
- fun = DECL_CHAIN (fun))
- if (DECL_SAVED_TREE (fun))
- break;
- gcc_assert (DECL_SAVED_TREE (fun));
- tree parms, res;
+ slot = AGGR_INIT_EXPR_SLOT (t);
+ tree addr = build_address (slot);
+ addr = build_nop (TREE_TYPE (res), addr);
+ ctx->values->put (res, addr);
+ ctx->values->put (slot, NULL_TREE);
+ }
+ else
+ ctx->values->put (res, NULL_TREE);
- /* Unshare the whole function body. */
- tree body = copy_fn (fun, parms, res);
+ tree jump_target = NULL_TREE;
+ cxx_eval_constant_expression (ctx, body,
+ lval, non_constant_p, overflow_p,
+ &jump_target);
- /* Associate the bindings with the remapped parms. */
- tree bound = new_call.bindings;
- tree remapped = parms;
- while (bound)
- {
- tree oparm = TREE_PURPOSE (bound);
- tree arg = TREE_VALUE (bound);
- gcc_assert (DECL_NAME (remapped) == DECL_NAME (oparm));
- ctx->values->put (remapped, arg);
- bound = TREE_CHAIN (bound);
- remapped = DECL_CHAIN (remapped);
- }
- /* Add the RESULT_DECL to the values map, too. */
- tree slot = NULL_TREE;
- if (DECL_BY_REFERENCE (res))
- {
- slot = AGGR_INIT_EXPR_SLOT (t);
- tree addr = build_address (slot);
- addr = build_nop (TREE_TYPE (res), addr);
- ctx->values->put (res, addr);
- ctx->values->put (slot, NULL_TREE);
- }
- else
- ctx->values->put (res, NULL_TREE);
-
- tree jump_target = NULL_TREE;
- cxx_eval_constant_expression (ctx, body,
- lval, non_constant_p, overflow_p,
- &jump_target);
-
- if (DECL_CONSTRUCTOR_P (fun))
- /* This can be null for a subobject constructor call, in
- which case what we care about is the initialization
- side-effects rather than the value. We could get at the
- value by evaluating *this, but we don't bother; there's
- no need to put such a call in the hash table. */
- result = lval ? ctx->object : ctx->ctor;
- else if (VOID_TYPE_P (TREE_TYPE (res)))
- result = void_node;
- else
+ if (DECL_CONSTRUCTOR_P (fun))
+ /* This can be null for a subobject constructor call, in
+ which case what we care about is the initialization
+ side-effects rather than the value. We could get at the
+ value by evaluating *this, but we don't bother; there's
+ no need to put such a call in the hash table. */
+ result = lval ? ctx->object : ctx->ctor;
+ else if (VOID_TYPE_P (TREE_TYPE (res)))
+ result = void_node;
+ else
+ {
+ result = *ctx->values->get (slot ? slot : res);
+ if (result == NULL_TREE && !*non_constant_p)
{
- result = *ctx->values->get (slot ? slot : res);
- if (result == NULL_TREE && !*non_constant_p)
- {
- if (!ctx->quiet)
- error ("constexpr call flows off the end "
- "of the function");
- *non_constant_p = true;
- }
+ if (!ctx->quiet)
+ error ("constexpr call flows off the end "
+ "of the function");
+ *non_constant_p = true;
}
-
- /* Remove the parms/result from the values map. Is it worth
- bothering to do this when the map itself is only live for
- one constexpr evaluation? If so, maybe also clear out
- other vars from call, maybe in BIND_EXPR handling? */
- ctx->values->remove (res);
- if (slot)
- ctx->values->remove (slot);
- for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
- ctx->values->remove (parm);
}
+
+ /* Remove the parms/result from the values map. Is it worth
+ bothering to do this when the map itself is only live for
+ one constexpr evaluation? If so, maybe also clear out
+ other vars from call, maybe in BIND_EXPR handling? */
+ ctx->values->remove (res);
+ if (slot)
+ ctx->values->remove (slot);
+ for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
+ ctx->values->remove (parm);
}
if (result == error_mark_node)
*non_constant_p = true;
if (*non_constant_p)
result = error_mark_node;
- else if (result)
- {
- /* If this was a call to initialize an object, set the type of
- the CONSTRUCTOR to the type of that object. */
- if (DECL_CONSTRUCTOR_P (fun) && !use_new_call)
- {
- tree ob_arg = get_nth_callarg (t, 0);
- STRIP_NOPS (ob_arg);
- gcc_assert (TYPE_PTR_P (TREE_TYPE (ob_arg))
- && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (ob_arg))));
- result = adjust_temp_type (TREE_TYPE (TREE_TYPE (ob_arg)),
- result);
- }
- }
- else
+ else if (!result)
result = void_node;
if (entry)
entry->result = result;
return t;
case PARM_DECL:
- if (!use_new_call && ctx
- && ctx->call && DECL_CONTEXT (t) == ctx->call->fundef->decl)
- r = lookup_parameter_binding (ctx->call, t);
- else if (lval && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
+ if (lval && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
/* glvalue use. */;
else if (tree *p = ctx->values->get (r))
r = *p;
break;
case INIT_EXPR:
- if (!use_new_call)
- {
- /* In C++11 constexpr evaluation we are looking for the value,
- not the side-effect of the initialization. */
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- false,
- non_constant_p, overflow_p);
- break;
- }
- /* else fall through */
case MODIFY_EXPR:
r = cxx_eval_store_expression (ctx, t, lval,
non_constant_p, overflow_p);