static void readonly_error (tree, enum lvalue_use);
static void readonly_warning (tree, enum lvalue_use);
static int lvalue_or_else (const_tree, enum lvalue_use);
-static int lvalue_p (const_tree);
static void record_maybe_used_decl (tree);
static int comptypes_internal (const_tree, const_tree);
\f
&& (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
&& ! TREE_PUBLIC (ref)
&& DECL_CONTEXT (ref) != current_function_decl)
- pedwarn (loc, 0, "%qD is static but used in inline function %qD "
- "which is not static", ref, current_function_decl);
+ record_inline_static (loc, current_function_decl, ref,
+ csi_internal);
return ref;
}
ret.value = c_sizeof (type);
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
- if (type_expr && c_vla_type_p (type))
- {
+ if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
+ && c_vla_type_p (type))
+ {
+ /* If the type is a [*] array, it is a VLA but is represented as
+ having a size of zero. In such a case we must ensure that
+ the result of sizeof does not get folded to a constant by
+ c_fully_fold, because if the size is evaluated the result is
+ not constant and so constraints on zero or negative size
+ arrays must not be applied when this sizeof call is inside
+ another array declarator. */
+ if (!type_expr)
+ type_expr = integer_zero_node;
ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
type_expr, ret.value);
C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
}
arg = c_objc_common_truthvalue_conversion (location, arg);
ret = invert_truthvalue (arg);
+ /* If the TRUTH_NOT_EXPR has been folded, reset the location. */
+ if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
+ location = EXPR_LOCATION (ret);
goto return_build_unary_op;
case REALPART_EXPR:
Lvalues can be assigned, unless their type has TYPE_READONLY.
Lvalues can have their address taken, unless they have C_DECL_REGISTER. */
-static int
+bool
lvalue_p (const_tree ref)
{
const enum tree_code code = TREE_CODE (ref);
}
\f
/* Build an assignment expression of lvalue LHS from value RHS.
+ If LHS_ORIGTYPE is not NULL, it is the original type of LHS, which
+ may differ from TREE_TYPE (LHS) for an enum bitfield.
MODIFYCODE is the code for a binary operator that we use
to combine the old value of LHS with RHS to get the new value.
Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
LOCATION is the location of the MODIFYCODE operator. */
tree
-build_modify_expr (location_t location,
- tree lhs, enum tree_code modifycode, tree rhs,
- tree rhs_origtype)
+build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
+ enum tree_code modifycode, tree rhs, tree rhs_origtype)
{
tree result;
tree newrhs;
if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
{
tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs),
- modifycode, rhs, rhs_origtype);
+ lhs_origtype, modifycode, rhs,
+ rhs_origtype);
if (inner == error_mark_node)
return error_mark_node;
result = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
TREE_TYPE (lhs) = lhstype;
}
+ /* Issue -Wc++-compat warnings about an assignment to an enum type
+ when LHS does not have its original type. This happens for,
+ e.g., an enum bitfield in a struct. */
+ if (warn_cxx_compat
+ && lhs_origtype != NULL_TREE
+ && lhs_origtype != lhstype
+ && TREE_CODE (lhs_origtype) == ENUMERAL_TYPE)
+ {
+ tree checktype = (rhs_origtype != NULL_TREE
+ ? rhs_origtype
+ : TREE_TYPE (rhs));
+ if (checktype != error_mark_node
+ && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype))
+ warning_at (location, OPT_Wc___compat,
+ "enum conversion in assignment is invalid in C++");
+ }
+
/* Convert new value to destination type. Fold it first, then
restore any excess precision information, for the sake of
conversion warnings. */
&& TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
{
/* FIXME: Until the gcc source code is converted, we only
- warn about parameter passing. We will add the other
- cases when bootstrap succeeds with them. */
- if (errtype == ic_argpass)
+ warn about assignment and parameter passing. We will add
+ the other cases when bootstrap succeeds with them. */
+ if (errtype == ic_argpass || errtype == ic_assign)
{
WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
G_("enum conversion when passing argument "
}
if (TREE_CODE (first) != INTEGER_CST)
+ {
+ first = c_fully_fold (first, false, NULL);
+ if (TREE_CODE (first) == INTEGER_CST)
+ pedwarn_init (input_location, OPT_pedantic,
+ "array index in initializer is not "
+ "an integer constant expression");
+ }
+
+ if (last && TREE_CODE (last) != INTEGER_CST)
+ {
+ last = c_fully_fold (last, false, NULL);
+ if (TREE_CODE (last) == INTEGER_CST)
+ pedwarn_init (input_location, OPT_pedantic,
+ "array index in initializer is not "
+ "an integer constant expression");
+ }
+
+ if (TREE_CODE (first) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
process_init_element (pop_init_level (1), true);
- else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
+ || TREE_CODE (constructor_type) == VECTOR_TYPE)
&& (constructor_max_index == 0
|| tree_int_cst_lt (constructor_max_index,
constructor_index)))
&& value.value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
- || fieldcode == UNION_TYPE))
+ || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
push_init_level (1);
continue;
&& value.value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
- || fieldcode == UNION_TYPE))
+ || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
push_init_level (1);
continue;
&& value.value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
- || eltcode == UNION_TYPE))
+ || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
{
push_init_level (1);
continue;
/* Now output the actual element. */
if (value.value)
- output_init_element (value.value, value.original_type,
- strict_string, elttype,
- constructor_index, 1, implicit);
+ {
+ if (TREE_CODE (value.value) == VECTOR_CST)
+ elttype = TYPE_MAIN_VARIANT (constructor_type);
+ output_init_element (value.value, value.original_type,
+ strict_string, elttype,
+ constructor_index, 1, implicit);
+ }
constructor_index
= size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);