if (error_operand_p (destination))
return NULL_TREE;
}
- /* We don't inline calls to functions with computed gotos.
- Those functions are typically up to some funny business,
- and may be depending on the labels being at particular
- addresses, or some such. */
- DECL_UNINLINABLE (current_function_decl) = 1;
}
check_goto (destination);
{
tree r, scope;
scope = do_pushlevel (sk_block);
- r = build_stmt (input_location, IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
- TREE_CHAIN (r) = scope;
+ r = build_stmt (input_location, IF_STMT, NULL_TREE,
+ NULL_TREE, NULL_TREE, scope);
begin_cond (&IF_COND (r));
return r;
}
void
finish_if_stmt (tree if_stmt)
{
- tree scope = TREE_CHAIN (if_stmt);
- TREE_CHAIN (if_stmt) = NULL;
+ tree scope = IF_SCOPE (if_stmt);
+ IF_SCOPE (if_stmt) = NULL;
add_stmt (do_poplevel (scope));
finish_stmt ();
}
tree r;
r = build_stmt (input_location, FOR_STMT, NULL_TREE, NULL_TREE,
- NULL_TREE, NULL_TREE);
+ NULL_TREE, NULL_TREE, NULL_TREE);
if (scope == NULL_TREE)
{
scope = begin_for_scope (&init);
}
FOR_INIT_STMT (r) = init;
- TREE_CHAIN (r) = scope;
+ FOR_SCOPE (r) = scope;
return r;
}
/* Pop the scope for the body of the loop. */
if (flag_new_for_scope > 0)
{
- tree scope = TREE_CHAIN (for_stmt);
- TREE_CHAIN (for_stmt) = NULL;
+ tree scope;
+ tree *scope_ptr = (TREE_CODE (for_stmt) == RANGE_FOR_STMT
+ ? &RANGE_FOR_SCOPE (for_stmt)
+ : &FOR_SCOPE (for_stmt));
+ scope = *scope_ptr;
+ *scope_ptr = NULL;
add_stmt (do_poplevel (scope));
}
tree r;
r = build_stmt (input_location, RANGE_FOR_STMT,
- NULL_TREE, NULL_TREE, NULL_TREE);
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
if (scope == NULL_TREE)
{
pop it now. */
if (init)
pop_stmt_list (init);
- TREE_CHAIN (r) = scope;
+ RANGE_FOR_SCOPE (r) = scope;
return r;
}
{
tree r, scope;
- r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
-
scope = do_pushlevel (sk_block);
- TREE_CHAIN (r) = scope;
+ r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE, scope);
+
begin_cond (&SWITCH_STMT_COND (r));
return r;
pop_switch ();
finish_stmt ();
- scope = TREE_CHAIN (switch_stmt);
- TREE_CHAIN (switch_stmt) = NULL;
+ scope = SWITCH_STMT_SCOPE (switch_stmt);
+ SWITCH_STMT_SCOPE (switch_stmt) = NULL;
add_stmt (do_poplevel (scope));
}
/* It actually has a value we need to deal with. First, force it
to be an rvalue so that we won't need to build up a copy
constructor call later when we try to assign it to something. */
- expr = force_rvalue (expr);
+ expr = force_rvalue (expr, tf_warning_or_error);
if (error_operand_p (expr))
return error_mark_node;
temporary object created by the final expression is destroyed at
the end of the full-expression containing the
statement-expression. */
- result = force_target_expr (type, result);
+ result = force_target_expr (type, result, tf_warning_or_error);
}
return result;
is not included in *ARGS even though it is considered to
be part of the list of arguments. Note that this is
related to CWG issues 515 and 1005. */
- || ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ || (((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ || BASELINK_P (fn))
&& current_class_ref
&& type_dependent_expression_p (current_class_ref)))
{
make_args_non_dependent (*args);
}
+ if (TREE_CODE (fn) == COMPONENT_REF)
+ {
+ tree member = TREE_OPERAND (fn, 1);
+ if (BASELINK_P (member))
+ {
+ tree object = TREE_OPERAND (fn, 0);
+ return build_new_method_call (object, member,
+ args, NULL_TREE,
+ (disallow_virtual
+ ? LOOKUP_NORMAL | LOOKUP_NONVIRTUAL
+ : LOOKUP_NORMAL),
+ /*fn_p=*/NULL,
+ complain);
+ }
+ }
+
if (is_overloaded_fn (fn))
fn = baselink_for_fns (fn);
result = build_new_method_call (object, fn, args, NULL_TREE,
(disallow_virtual
- ? LOOKUP_NONVIRTUAL : 0),
+ ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
+ : LOOKUP_NORMAL),
/*fn_p=*/NULL,
complain);
}
{
if (TREE_CODE (result) == INDIRECT_REF)
result = TREE_OPERAND (result, 0);
- gcc_assert (TREE_CODE (result) == CALL_EXPR
- /* FIXME cp_build_function_call_vec should avoid argument
- and return transformations like build_over_call does. */
- || TREE_CODE (result) == TARGET_EXPR
- || TREE_CODE (fn) == PSEUDO_DTOR_EXPR
- || errorcount);
result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args);
KOENIG_LOOKUP_P (result) = koenig_p;
release_tree_vector (orig_args);
result = convert_from_reference (result);
}
+ if (koenig_p)
+ {
+ /* Free garbage OVERLOADs from arg-dependent lookup. */
+ tree next = NULL_TREE;
+ for (fn = orig_fn;
+ fn && TREE_CODE (fn) == OVERLOAD && OVL_ARG_DEPENDENT (fn);
+ fn = next)
+ {
+ if (processing_template_decl)
+ /* In a template, we'll re-use them at instantiation time. */
+ OVL_ARG_DEPENDENT (fn) = false;
+ else
+ {
+ next = OVL_CHAIN (fn);
+ ggc_free (fn);
+ }
+ }
+ }
+
return result;
}
the CONSTRUCTOR in COMPOUND_LITERAL is being cast. */
tree
-finish_compound_literal (tree type, tree compound_literal)
+finish_compound_literal (tree type, tree compound_literal,
+ tsubst_flags_t complain)
{
if (type == error_mark_node)
return error_mark_node;
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ compound_literal
+ = finish_compound_literal (TREE_TYPE (type), compound_literal,
+ complain);
+ return cp_build_c_cast (type, compound_literal, complain);
+ }
+
if (!TYPE_OBJ_P (type))
{
- error ("compound literal of non-object type %qT", type);
+ if (complain & tf_error)
+ error ("compound literal of non-object type %qT", type);
return error_mark_node;
}
that it came from T{} rather than T({}). */
CONSTRUCTOR_IS_DIRECT_INIT (compound_literal) = 1;
compound_literal = build_tree_list (NULL_TREE, compound_literal);
- return build_functional_cast (type, compound_literal, tf_error);
+ return build_functional_cast (type, compound_literal, complain);
}
if (TREE_CODE (type) == ARRAY_TYPE
&& check_array_initializer (NULL_TREE, type, compound_literal))
return error_mark_node;
compound_literal = reshape_init (type, compound_literal);
- if (TREE_CODE (type) == ARRAY_TYPE)
- cp_complete_array_type (&type, compound_literal, false);
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) == NULL_TREE)
+ {
+ cp_complete_array_type_or_error (&type, compound_literal,
+ false, complain);
+ if (type == error_mark_node)
+ return error_mark_node;
+ }
compound_literal = digest_init (type, compound_literal);
- return get_target_expr (compound_literal);
+ /* Put static/constant array temporaries in static variables, but always
+ represent class temporaries with TARGET_EXPR so we elide copies. */
+ if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
+ && TREE_CODE (type) == ARRAY_TYPE
+ && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ && initializer_constant_valid_p (compound_literal, type))
+ {
+ tree decl = create_temporary_var (type);
+ DECL_INITIAL (decl) = compound_literal;
+ TREE_STATIC (decl) = 1;
+ if (literal_type_p (type) && CP_TYPE_CONST_NON_VOLATILE_P (type))
+ {
+ /* 5.19 says that a constant expression can include an
+ lvalue-rvalue conversion applied to "a glvalue of literal type
+ that refers to a non-volatile temporary object initialized
+ with a constant expression". Rather than try to communicate
+ that this VAR_DECL is a temporary, just mark it constexpr. */
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
+ TREE_CONSTANT (decl) = true;
+ }
+ cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
+ decl = pushdecl_top_level (decl);
+ DECL_NAME (decl) = make_anon_name ();
+ SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+ return decl;
+ }
+ else
+ return get_target_expr_sfinae (compound_literal, complain);
}
/* Return the declaration for the function-name variable indicated by
return type;
}
+/* Implement the __underlying_type keyword: Return the underlying
+ type of TYPE, suitable for use as a type-specifier. */
+
+tree
+finish_underlying_type (tree type)
+{
+ tree underlying_type;
+
+ if (processing_template_decl)
+ {
+ underlying_type = cxx_make_type (UNDERLYING_TYPE);
+ UNDERLYING_TYPE_TYPE (underlying_type) = type;
+ SET_TYPE_STRUCTURAL_EQUALITY (underlying_type);
+
+ return underlying_type;
+ }
+
+ complete_type (type);
+
+ if (TREE_CODE (type) != ENUMERAL_TYPE)
+ {
+ error ("%qE is not an enumeration type", type);
+ return error_mark_node;
+ }
+
+ underlying_type = ENUM_UNDERLYING_TYPE (type);
+
+ /* Fixup necessary in this case because ENUM_UNDERLYING_TYPE
+ includes TYPE_MIN_VALUE and TYPE_MAX_VALUE information.
+ See finish_enum_value_list for details. */
+ if (!ENUM_FIXED_UNDERLYING_TYPE_P (type))
+ underlying_type
+ = c_common_type_for_mode (TYPE_MODE (underlying_type),
+ TYPE_UNSIGNED (underlying_type));
+
+ return underlying_type;
+}
+
/* Perform C++-specific checks for __builtin_offsetof before calling
fold_offsetof. */
a full expression. */
tree
-finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
+finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
+ tsubst_flags_t complain)
{
- tree orig_expr = expr;
tree type = NULL_TREE;
if (!expr || error_operand_p (expr))
|| (TREE_CODE (expr) == BIT_NOT_EXPR
&& TYPE_P (TREE_OPERAND (expr, 0))))
{
- error ("argument to decltype must be an expression");
+ if (complain & tf_error)
+ error ("argument to decltype must be an expression");
return error_mark_node;
}
expr = resolve_nondeduced_context (expr);
+ if (type_unknown_p (expr))
+ {
+ if (complain & tf_error)
+ error ("decltype cannot resolve address of overloaded function");
+ return error_mark_node;
+ }
+
/* To get the size of a static data member declared as an array of
unknown bound, we need to instantiate it. */
if (TREE_CODE (expr) == VAR_DECL
expr = TREE_OPERAND (expr, 1);
if (TREE_CODE (expr) == BASELINK)
- /* See through BASELINK nodes to the underlying functions. */
+ /* See through BASELINK nodes to the underlying function. */
expr = BASELINK_FUNCTIONS (expr);
- if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
- expr = TREE_OPERAND (expr, 0);
-
- if (TREE_CODE (expr) == OVERLOAD)
- {
- if (OVL_CHAIN (expr)
- || TREE_CODE (OVL_FUNCTION (expr)) == TEMPLATE_DECL)
- {
- error ("%qE refers to a set of overloaded functions", orig_expr);
- return error_mark_node;
- }
- else
- /* An overload set containing only one function: just look
- at that function. */
- expr = OVL_FUNCTION (expr);
- }
-
switch (TREE_CODE (expr))
{
case FIELD_DECL:
break;
default:
- gcc_assert (TYPE_P (expr) || DECL_P (expr)
- || TREE_CODE (expr) == SCOPE_REF);
- error ("argument to decltype must be an expression");
+ gcc_unreachable ();
return error_mark_node;
}
}
}
}
- if (!type || type == unknown_type_node)
- {
- error ("type of %qE is unknown", expr);
- return error_mark_node;
- }
-
return type;
}
bool
literal_type_p (tree t)
{
- if (SCALAR_TYPE_P (t))
+ if (SCALAR_TYPE_P (t)
+ || TREE_CODE (t) == REFERENCE_TYPE)
return true;
if (CLASS_TYPE_P (t))
return CLASSTYPE_LITERAL_P (t);
return (constexpr_fundef *) htab_find (constexpr_fundef_table, &fundef);
}
-/* Return true if type expression T is a valid parameter type, or
- a valid return type, of a constexpr function. */
-
-static bool
-valid_type_in_constexpr_fundecl_p (tree t)
-{
- return (literal_type_p (t)
- /* FIXME we allow ref to non-literal; should change standard to
- match, or change back if not. */
- || TREE_CODE (t) == REFERENCE_TYPE);
-}
-
/* Check whether the parameter and return types of FUN are valid for a
constexpr function, and complain if COMPLAIN. */
tree parm = FUNCTION_FIRST_USER_PARM (fun);
bool ret = true;
for (; parm != NULL; parm = TREE_CHAIN (parm))
- if (!valid_type_in_constexpr_fundecl_p (TREE_TYPE (parm)))
+ if (!literal_type_p (TREE_TYPE (parm)))
{
ret = false;
if (complain)
if (!DECL_CONSTRUCTOR_P (fun))
{
tree rettype = TREE_TYPE (TREE_TYPE (fun));
- if (!valid_type_in_constexpr_fundecl_p (rettype))
+ if (!literal_type_p (rettype))
{
ret = false;
if (complain)
}
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
- && COMPLETE_TYPE_P (DECL_CONTEXT (fun))
- && !valid_type_in_constexpr_fundecl_p (DECL_CONTEXT (fun)))
+ && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
{
ret = false;
if (complain)
non_constant_p);
tree index, oldidx;
HOST_WIDE_INT i;
- unsigned len;
+ unsigned len, elem_nchars = 1;
if (*non_constant_p)
return t;
oldidx = TREE_OPERAND (t, 1);
return t;
else if (addr)
return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
- len = (TREE_CODE (ary) == CONSTRUCTOR
- ? CONSTRUCTOR_NELTS (ary)
- : (unsigned)TREE_STRING_LENGTH (ary));
+ if (TREE_CODE (ary) == CONSTRUCTOR)
+ len = CONSTRUCTOR_NELTS (ary);
+ else
+ {
+ elem_nchars = (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (ary)))
+ / TYPE_PRECISION (char_type_node));
+ len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+ }
if (compare_tree_int (index, len) >= 0)
{
if (!allow_non_constant)
i = tree_low_cst (index, 0);
if (TREE_CODE (ary) == CONSTRUCTOR)
return VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ary), i)->value;
- else
+ else if (elem_nchars == 1)
return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))),
TREE_STRING_POINTER (ary)[i]);
+ else
+ {
+ tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary)));
+ return native_interpret_expr (type, (const unsigned char *)
+ TREE_STRING_POINTER (ary)
+ + i * elem_nchars, elem_nchars);
+ }
/* Don't VERIFY_CONSTANT here. */
}
tree type = TREE_TYPE (r);
error ("the value of %qD is not usable in a constant "
"expression", r);
+ /* Avoid error cascade. */
+ if (DECL_INITIAL (r) == error_mark_node)
+ return;
if (DECL_DECLARED_CONSTEXPR_P (r))
inform (DECL_SOURCE_LOCATION (r),
"%qD used in its own initializer", r);
class member access expression, including the result of the
implicit transformation in the body of the non-static
member function (9.3.1); */
+ /* FIXME this restriction seems pointless since the standard dropped
+ "potential constant expression". */
if (is_this_parameter (t))
{
if (flags & tf_error)
{
tree fun = get_function_named_in_call (t);
const int nargs = call_expr_nargs (t);
- if (TREE_CODE (fun) != FUNCTION_DECL)
- {
- if (potential_constant_expression_1 (fun, rval, flags))
- /* Might end up being a constant function pointer. */
- return true;
- if (flags & tf_error)
- error ("%qE is not a function name", fun);
- return false;
- }
- /* Skip initial arguments to base constructors. */
- if (DECL_BASE_CONSTRUCTOR_P (fun))
- i = num_artificial_parms_for (fun);
+ i = 0;
+
+ if (is_overloaded_fn (fun))
+ {
+ if (TREE_CODE (fun) == FUNCTION_DECL)
+ {
+ if (builtin_valid_in_constant_expr_p (fun))
+ return true;
+ if (!DECL_DECLARED_CONSTEXPR_P (fun)
+ && !morally_constexpr_builtin_function_p (fun))
+ {
+ if (flags & tf_error)
+ error ("%qD is not %<constexpr%>", fun);
+ return false;
+ }
+ /* A call to a non-static member function takes the address
+ of the object as the first argument. But in a constant
+ expression the address will be folded away, so look
+ through it now. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
+ && !DECL_CONSTRUCTOR_P (fun))
+ {
+ tree x = get_nth_callarg (t, 0);
+ if (is_this_parameter (x))
+ /* OK. */;
+ else if (!potential_constant_expression_1 (x, rval, flags))
+ {
+ if (flags & tf_error)
+ error ("object argument is not a potential "
+ "constant expression");
+ return false;
+ }
+ i = 1;
+ }
+ }
+ else
+ fun = get_first_fn (fun);
+ /* Skip initial arguments to base constructors. */
+ if (DECL_BASE_CONSTRUCTOR_P (fun))
+ i = num_artificial_parms_for (fun);
+ fun = DECL_ORIGIN (fun);
+ }
else
- i = 0;
- fun = DECL_ORIGIN (fun);
- if (builtin_valid_in_constant_expr_p (fun))
- return true;
- if (!DECL_DECLARED_CONSTEXPR_P (fun)
- && !morally_constexpr_builtin_function_p (fun))
{
- if (flags & tf_error)
- error ("%qD is not %<constexpr%>", fun);
- return false;
+ if (potential_constant_expression_1 (fun, rval, flags))
+ /* Might end up being a constant function pointer. */;
+ else
+ {
+ if (flags & tf_error)
+ error ("%qE is not a function name", fun);
+ return false;
+ }
}
for (; i < nargs; ++i)
{
tree x = get_nth_callarg (t, i);
- /* A call to a non-static member function takes the
- address of the object as the first argument.
- But in a constant expression the address will be folded
- away, so look through it now. */
- if (i == 0 && DECL_NONSTATIC_MEMBER_P (fun)
- && !DECL_CONSTRUCTOR_P (fun))
- {
- if (is_this_parameter (x))
- /* OK. */;
- else if (!potential_constant_expression_1 (x, rval, flags))
- {
- if (flags & tf_error)
- error ("object argument is not a potential constant "
- "expression");
- return false;
- }
- }
- else if (!potential_constant_expression_1 (x, rval, flags))
+ if (!potential_constant_expression_1 (x, rval, flags))
{
if (flags & tf_error)
error ("argument in position %qP is not a "
if (DECL_CONSTRUCTOR_P (DECL_CONTEXT (x)) && want_rval)
{
if (flags & tf_error)
- error ("the value of the object being constructed is "
- "not a constant expression");
+ sorry ("use of the value of the object being constructed "
+ "in a constant expression");
return false;
}
return true;
case BIT_XOR_EXPR:
case BIT_AND_EXPR:
case TRUTH_XOR_EXPR:
+ case UNORDERED_EXPR:
+ case ORDERED_EXPR:
case UNLT_EXPR:
case UNLE_EXPR:
case UNGT_EXPR:
There's normally no way to express direct-initialization
from an element of a CONSTRUCTOR, so we build up a special
TARGET_EXPR to bypass the usual copy-initialization. */
- val = force_rvalue (val);
+ val = force_rvalue (val, tf_warning_or_error);
if (TREE_CODE (val) == TARGET_EXPR)
TARGET_EXPR_DIRECT_INIT_P (val) = true;
}
But we briefly treat it as an aggregate to make this simpler. */
type = TREE_TYPE (lambda_expr);
CLASSTYPE_NON_AGGREGATE (type) = 0;
- expr = finish_compound_literal (type, expr);
+ expr = finish_compound_literal (type, expr, tf_warning_or_error);
CLASSTYPE_NON_AGGREGATE (type) = 1;
out:
/* Put the thunk in the same comdat group as the call op. */
struct cgraph_node *callop_node, *thunk_node;
DECL_COMDAT_GROUP (statfn) = DECL_COMDAT_GROUP (callop);
- callop_node = cgraph_node (callop);
- thunk_node = cgraph_node (statfn);
+ callop_node = cgraph_get_create_node (callop);
+ thunk_node = cgraph_get_create_node (statfn);
gcc_assert (callop_node->same_comdat_group == NULL);
gcc_assert (thunk_node->same_comdat_group == NULL);
callop_node->same_comdat_group = thunk_node;
VEC_address (tree, argvec));
CALL_FROM_THUNK_P (call) = 1;
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
- call = build_cplus_new (TREE_TYPE (call), call);
+ call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
call = convert_from_reference (call);
finish_return_stmt (call);