finish_unary_op_expr (enum tree_code code, tree expr)
{
tree result = build_x_unary_op (code, expr, tf_warning_or_error);
- /* Inside a template, build_x_unary_op does not fold the
- expression. So check whether the result is folded before
- setting TREE_NEGATED_INT. */
- if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST
- && TREE_CODE (result) == INTEGER_CST
- && !TYPE_UNSIGNED (TREE_TYPE (result))
- && INT_CST_LT (result, integer_zero_node))
- {
- /* RESULT may be a cached INTEGER_CST, so we must copy it before
- setting TREE_NEGATED_INT. */
- result = copy_node (result);
- TREE_NEGATED_INT (result) = 1;
- }
if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
overflow_warning (input_location, result);
static inline bool
is_instantiation_of_constexpr (tree fun)
{
- return (DECL_TEMPLATE_INFO (fun)
+ return (DECL_TEMPLOID_INSTANTIATION (fun)
&& DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
(DECL_TI_TEMPLATE (fun))));
}
void
finish_omp_barrier (void)
{
- tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
void
finish_omp_flush (void)
{
- tree fn = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+ tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
void
finish_omp_taskwait (void)
{
- tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
void
finish_omp_taskyield (void)
{
- tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
}
}
-/* Returns true if TYPE is a complete type, an array of unknown bound,
- or (possibly cv-qualified) void, returns false otherwise. */
+/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
+ void, or a complete type, returns it, otherwise NULL_TREE. */
-static bool
+static tree
check_trait_type (tree type)
{
- if (COMPLETE_TYPE_P (type))
- return true;
-
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
- return true;
+ return type;
if (VOID_TYPE_P (type))
- return true;
+ return type;
- return false;
+ return complete_type_or_else (strip_array_types (type), NULL_TREE);
}
/* Process a trait expression. */
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1))
- {
- error ("incomplete type %qT not allowed", type1);
- return error_mark_node;
- }
+ return error_mark_node;
break;
case CPTK_IS_BASE_OF:
if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
&& !same_type_ignoring_top_level_qualifiers_p (type1, type2)
- && !COMPLETE_TYPE_P (type2))
- {
- error ("incomplete type %qT not allowed", type2);
- return error_mark_node;
- }
+ && !complete_type_or_else (type2, NULL_TREE))
+ /* We already issued an error. */
+ return error_mark_node;
break;
case CPTK_IS_CLASS:
}
}
- /* Check this again here for cxx_eval_call_expression. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
&& !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
{
return ret;
}
-/* Return non-null if FUN certainly designates a valid constexpr function
- declaration. Otherwise return NULL. Issue appropriate diagnostics
- if necessary. Note that we only check the declaration, not the body
- of the function. */
-
-tree
-validate_constexpr_fundecl (tree fun)
-{
- if (processing_template_decl || !DECL_DECLARED_CONSTEXPR_P (fun))
- return NULL;
- else if (DECL_CLONED_FUNCTION_P (fun))
- /* We already checked the original function. */
- return fun;
-
- if (!is_valid_constexpr_fn (fun, !DECL_TEMPLATE_INFO (fun)))
- {
- DECL_DECLARED_CONSTEXPR_P (fun) = false;
- return NULL;
- }
-
- return fun;
-}
-
/* Subroutine of build_constexpr_constructor_member_initializers.
The expression tree T represents a data member initialization
in a (constexpr) constructor definition. Build a pairing of
else
{
index = CONSTRUCTOR_ELT (body, i)->index;
- /* Skip base vtable inits. */
- if (TREE_CODE (index) == COMPONENT_REF)
+ /* Skip base and vtable inits. */
+ if (TREE_CODE (index) != FIELD_DECL)
continue;
}
for (; field != index; field = DECL_CHAIN (field))
{
+ tree ftype;
if (TREE_CODE (field) != FIELD_DECL
|| (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)))
continue;
if (!complain)
return true;
+ ftype = strip_array_types (TREE_TYPE (field));
+ if (type_has_constexpr_default_constructor (ftype))
+ {
+ /* It's OK to skip a member with a trivial constexpr ctor.
+ A constexpr ctor that isn't trivial should have been
+ added in by now. */
+ gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype));
+ continue;
+ }
error ("uninitialized member %qD in %<constexpr%> constructor",
field);
bad = true;
constexpr_fundef entry;
constexpr_fundef **slot;
+ if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
+ return NULL;
+
body = massage_constexpr_body (fun, body);
if (body == NULL_TREE || body == error_mark_node)
{
- error ("body of constexpr function %qD not a return-statement", fun);
- DECL_DECLARED_CONSTEXPR_P (fun) = false;
+ if (!DECL_CONSTRUCTOR_P (fun))
+ error ("body of constexpr function %qD not a return-statement", fun);
return NULL;
}
if (!potential_rvalue_constant_expression (body))
{
- if (!DECL_TEMPLATE_INFO (fun))
+ if (!DECL_GENERATED_P (fun))
require_potential_rvalue_constant_expression (body);
return NULL;
}
if (DECL_CONSTRUCTOR_P (fun)
- && cx_check_missing_mem_inits (fun, body, !DECL_TEMPLATE_INFO (fun)))
+ && cx_check_missing_mem_inits (fun, body, !DECL_GENERATED_P (fun)))
return NULL;
/* Create the constexpr function table if necessary. */
static struct pointer_set_t *diagnosed;
tree body;
location_t save_loc;
- /* Only diagnose instantiations of constexpr templates. */
- if (!is_instantiation_of_constexpr (fun))
+ /* Only diagnose defaulted functions or instantiations. */
+ if (!DECL_DEFAULTED_FN (fun)
+ && !is_instantiation_of_constexpr (fun))
return;
if (diagnosed == NULL)
diagnosed = pointer_set_create ();
{
if (!allow_non_constant)
{
- if (DECL_SAVED_TREE (fun))
+ if (DECL_INITIAL (fun))
{
/* The definition of fun was somehow unsuitable. */
error_at (loc, "%qD called in a constant expression", fun);
allow_non_constant, addr,
non_constant_p);
VERIFY_CONSTANT (lhs);
- if (lhs == bailout_value)
+ if (tree_int_cst_equal (lhs, bailout_value))
return lhs;
- gcc_assert (lhs == continue_value);
+ gcc_assert (tree_int_cst_equal (lhs, continue_value));
r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
allow_non_constant, addr, non_constant_p);
VERIFY_CONSTANT (r);
return t;
case LAMBDA_EXPR:
- case DYNAMIC_CAST_EXPR:
- case PSEUDO_DTOR_EXPR:
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
/* We can see a FIELD_DECL in a pointer-to-member expression. */
case FIELD_DECL:
case PARM_DECL:
+ case USING_DECL:
return true;
case AGGR_INIT_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
return (potential_constant_expression_1
(TREE_OPERAND (t, 0),
TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
/* N2927: "[The closure] class type is not an aggregate."
But we briefly treat it as an aggregate to make this simpler. */
- type = TREE_TYPE (lambda_expr);
+ type = LAMBDA_EXPR_CLOSURE (lambda_expr);
CLASSTYPE_NON_AGGREGATE (type) = 0;
expr = finish_compound_literal (type, expr, tf_warning_or_error);
CLASSTYPE_NON_AGGREGATE (type) = 1;
type = begin_class_definition (type, /*attributes=*/NULL_TREE);
/* Cross-reference the expression and the type. */
- TREE_TYPE (lambda) = type;
+ LAMBDA_EXPR_CLOSURE (lambda) = type;
CLASSTYPE_LAMBDA_EXPR (type) = lambda;
return type;
{
tree type;
if (TREE_CODE (lambda) == LAMBDA_EXPR)
- type = TREE_TYPE (lambda);
+ type = LAMBDA_EXPR_CLOSURE (lambda);
else
type = lambda;
gcc_assert (LAMBDA_TYPE_P (type));
/* If TREE_TYPE isn't set, we're still in the introducer, so check
for duplicates. */
- if (!TREE_TYPE (lambda))
+ if (!LAMBDA_EXPR_CLOSURE (lambda))
{
if (IDENTIFIER_MARKED (name))
{
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
/* Add it to the appropriate closure class if we've started it. */
- if (current_class_type && current_class_type == TREE_TYPE (lambda))
+ if (current_class_type
+ && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
finish_member_declaration (member);
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
- if (TREE_TYPE (lambda))
+ if (LAMBDA_EXPR_CLOSURE (lambda))
return build_capture_proxy (member);
/* For explicit captures we haven't started the function yet, so we wait
and build the proxy from cp_parser_lambda_body. */
{
tree lambda = TREE_VALUE (node);
- current_class_type = TREE_TYPE (lambda);
+ current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
var = add_capture (lambda,
id,
initializer,
if (!this_capture
&& LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
{
- tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda));
+ tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda));
tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
tree init = NULL_TREE;
else
{
/* To make sure that current_class_ref is for the lambda. */
- gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
+ gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+ == LAMBDA_EXPR_CLOSURE (lambda));
result = this_capture;