return 0;
/* If one of these types comes from a non-prototype fn definition,
compare that with the other type's arglist.
- If they don't match, ask for a warning (0, but no error). */
+ If they don't match, ask for a warning (but no error). */
if (TYPE_ACTUAL_ARG_TYPES (f1)
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
val = 2;
return ret;
}
-
-/* Perform the default conversion of arrays and functions to pointers.
- Return the result of converting EXP. For any other expression, just
- return EXP after removing NOPs. */
-
-tree
-default_function_array_conversion (tree exp)
+/* Convert the array expression EXP to a pointer. */
+static tree
+array_to_pointer_conversion (tree exp)
{
- tree orig_exp;
+ tree orig_exp = exp;
tree type = TREE_TYPE (exp);
- enum tree_code code = TREE_CODE (type);
- int not_lvalue = 0;
+ tree adr;
+ tree restype = TREE_TYPE (type);
+ tree ptrtype;
- /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
- an lvalue.
+ gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
- Do not use STRIP_NOPS here! It will remove conversions from pointer
- to integer and cause infinite recursion. */
- orig_exp = exp;
- while (TREE_CODE (exp) == NON_LVALUE_EXPR
- || (TREE_CODE (exp) == NOP_EXPR
- && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
- {
- if (TREE_CODE (exp) == NON_LVALUE_EXPR)
- not_lvalue = 1;
- exp = TREE_OPERAND (exp, 0);
- }
+ STRIP_TYPE_NOPS (exp);
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
- if (code == FUNCTION_TYPE)
+ ptrtype = build_pointer_type (restype);
+
+ if (TREE_CODE (exp) == INDIRECT_REF)
+ return convert (ptrtype, TREE_OPERAND (exp, 0));
+
+ if (TREE_CODE (exp) == VAR_DECL)
{
- return build_unary_op (ADDR_EXPR, exp, 0);
+ /* We are making an ADDR_EXPR of ptrtype. This is a valid
+ ADDR_EXPR because it's the best way of representing what
+ happens in C when we take the address of an array and place
+ it in a pointer to the element type. */
+ adr = build1 (ADDR_EXPR, ptrtype, exp);
+ if (!c_mark_addressable (exp))
+ return error_mark_node;
+ TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
+ return adr;
}
- if (code == ARRAY_TYPE)
- {
- tree adr;
- tree restype = TREE_TYPE (type);
- tree ptrtype;
- int constp = 0;
- int volatilep = 0;
- int lvalue_array_p;
- if (REFERENCE_CLASS_P (exp) || DECL_P (exp))
- {
- constp = TREE_READONLY (exp);
- volatilep = TREE_THIS_VOLATILE (exp);
- }
+ /* This way is better for a COMPONENT_REF since it can
+ simplify the offset for a component. */
+ adr = build_unary_op (ADDR_EXPR, exp, 1);
+ return convert (ptrtype, adr);
+}
- if (TYPE_QUALS (type) || constp || volatilep)
- restype
- = c_build_qualified_type (restype,
- TYPE_QUALS (type)
- | (constp * TYPE_QUAL_CONST)
- | (volatilep * TYPE_QUAL_VOLATILE));
+/* Convert the function expression EXP to a pointer. */
+static tree
+function_to_pointer_conversion (tree exp)
+{
+ tree orig_exp = exp;
- if (TREE_CODE (exp) == INDIRECT_REF)
- return convert (build_pointer_type (restype),
- TREE_OPERAND (exp, 0));
+ gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE);
- if (TREE_CODE (exp) == COMPOUND_EXPR)
- {
- tree op1 = default_conversion (TREE_OPERAND (exp, 1));
- return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
- TREE_OPERAND (exp, 0), op1);
- }
+ STRIP_TYPE_NOPS (exp);
- lvalue_array_p = !not_lvalue && lvalue_p (exp);
- if (!flag_isoc99 && !lvalue_array_p)
- {
- /* Before C99, non-lvalue arrays do not decay to pointers.
- Normally, using such an array would be invalid; but it can
- be used correctly inside sizeof or as a statement expression.
- Thus, do not give an error here; an error will result later. */
- return exp;
- }
+ if (TREE_NO_WARNING (orig_exp))
+ TREE_NO_WARNING (exp) = 1;
- ptrtype = build_pointer_type (restype);
+ return build_unary_op (ADDR_EXPR, exp, 0);
+}
- if (TREE_CODE (exp) == VAR_DECL)
- {
- /* We are making an ADDR_EXPR of ptrtype. This is a valid
- ADDR_EXPR because it's the best way of representing what
- happens in C when we take the address of an array and place
- it in a pointer to the element type. */
- adr = build1 (ADDR_EXPR, ptrtype, exp);
- if (!c_mark_addressable (exp))
- return error_mark_node;
- TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
- return adr;
- }
- /* This way is better for a COMPONENT_REF since it can
- simplify the offset for a component. */
- adr = build_unary_op (ADDR_EXPR, exp, 1);
- return convert (ptrtype, adr);
+/* Perform the default conversion of arrays and functions to pointers.
+ Return the result of converting EXP. For any other expression, just
+ return EXP after removing NOPs. */
+
+struct c_expr
+default_function_array_conversion (struct c_expr exp)
+{
+ tree orig_exp = exp.value;
+ tree type = TREE_TYPE (exp.value);
+ enum tree_code code = TREE_CODE (type);
+
+ switch (code)
+ {
+ case ARRAY_TYPE:
+ {
+ bool not_lvalue = false;
+ bool lvalue_array_p;
+
+ while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
+ || TREE_CODE (exp.value) == NOP_EXPR)
+ && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
+ {
+ if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
+ not_lvalue = true;
+ exp.value = TREE_OPERAND (exp.value, 0);
+ }
+
+ if (TREE_NO_WARNING (orig_exp))
+ TREE_NO_WARNING (exp.value) = 1;
+
+ lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
+ if (!flag_isoc99 && !lvalue_array_p)
+ {
+ /* Before C99, non-lvalue arrays do not decay to pointers.
+ Normally, using such an array would be invalid; but it can
+ be used correctly inside sizeof or as a statement expression.
+ Thus, do not give an error here; an error will result later. */
+ return exp;
+ }
+
+ exp.value = array_to_pointer_conversion (exp.value);
+ }
+ break;
+ case FUNCTION_TYPE:
+ exp.value = function_to_pointer_conversion (exp.value);
+ break;
+ default:
+ STRIP_TYPE_NOPS (exp.value);
+ if (TREE_NO_WARNING (orig_exp))
+ TREE_NO_WARNING (exp.value) = 1;
+ break;
}
+
return exp;
}
deliberately. ??? Existing practice has also been to warn only
when the char index is syntactically the index, not for
char[array]. */
- if (warn_char_subscripts && !swapped
+ if (!swapped
&& TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
- warning (0, "array subscript has type %<char%>");
+ warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
/* Apply default promotions *after* noticing character types. */
index = default_conversion (index);
name = DECL_NAME (function);
fundecl = function;
}
- function = default_function_array_conversion (function);
+ if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
+ function = function_to_pointer_conversion (function);
/* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
expressions, like those used for ObjC messenger dispatches. */
if (AGGREGATE_TYPE_P (return_type))
rhs = build_compound_literal (return_type,
- build_constructor (return_type,
- NULL_TREE));
+ build_constructor (return_type, 0));
else
rhs = fold_build1 (NOP_EXPR, return_type, integer_zero_node);
and the actual arg is that enum type. */
;
else if (formal_prec != TYPE_PRECISION (type1))
- warning (0, "passing argument %d of %qE with different "
- "width due to prototype", argnum, rname);
+ warning (OPT_Wconversion, "passing argument %d of %qE "
+ "with different width due to prototype",
+ argnum, rname);
else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
;
/* Don't complain if the formal parameter type
&& TYPE_UNSIGNED (TREE_TYPE (val)))
;
else if (TYPE_UNSIGNED (type))
- warning (0, "passing argument %d of %qE as unsigned "
- "due to prototype", argnum, rname);
+ warning (OPT_Wconversion, "passing argument %d of %qE "
+ "as unsigned due to prototype",
+ argnum, rname);
else
- warning (0, "passing argument %d of %qE as signed "
- "due to prototype", argnum, rname);
+ warning (OPT_Wconversion, "passing argument %d of %qE "
+ "as signed due to prototype", argnum, rname);
}
}
enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
tree val;
int noconvert = flag;
+ const char *invalid_op_diag;
if (typecode == ERROR_MARK)
return error_mark_node;
if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
typecode = INTEGER_TYPE;
+ if ((invalid_op_diag
+ = targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
+ {
+ error (invalid_op_diag);
+ return error_mark_node;
+ }
+
switch (code)
{
case CONVERT_EXPR:
/* For &x[y], return x+y */
if (TREE_CODE (arg) == ARRAY_REF)
{
- if (!c_mark_addressable (TREE_OPERAND (arg, 0)))
+ tree op0 = TREE_OPERAND (arg, 0);
+ if (!c_mark_addressable (op0))
return error_mark_node;
return build_binary_op (PLUS_EXPR,
- default_function_array_conversion
- (TREE_OPERAND (arg, 0)),
+ (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
+ ? array_to_pointer_conversion (op0)
+ : op0),
TREE_OPERAND (arg, 1), 1);
}
val = build1 (ADDR_EXPR, argtype, arg);
- if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
- TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
-
return val;
default:
if (pedantic)
pedwarn ("ISO C forbids casts to union type");
t = digest_init (type,
- build_constructor (type,
- build_tree_list (field, value)),
+ build_constructor_single (type, field, value),
true, 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
TREE_INVARIANT (t) = TREE_INVARIANT (value);
}
/* Warn about possible alignment problems. */
- if (STRICT_ALIGNMENT && warn_cast_align
+ if (STRICT_ALIGNMENT
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
|| TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
&& TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
&& TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
- warning (0, "cast increases required alignment of target type");
+ warning (OPT_Wcast_align,
+ "cast increases required alignment of target type");
- if (warn_pointer_to_int_cast
- && TREE_CODE (type) == INTEGER_TYPE
+ if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)
&& !TREE_CONSTANT (value))
- warning (0, "cast from pointer to integer of different size");
+ warning (OPT_Wpointer_to_int_cast,
+ "cast from pointer to integer of different size");
- if (warn_bad_function_cast
- && TREE_CODE (value) == CALL_EXPR
+ if (TREE_CODE (value) == CALL_EXPR
&& TREE_CODE (type) != TREE_CODE (otype))
- warning (0, "cast from function call of type %qT to non-matching "
- "type %qT", otype, type);
+ warning (OPT_Wbad_function_cast, "cast from function call of type %qT "
+ "to non-matching type %qT", otype, type);
- if (warn_int_to_pointer_cast
- && TREE_CODE (type) == POINTER_TYPE
+ if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == INTEGER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)
/* Don't warn about converting any constant. */
&& !TREE_CONSTANT (value))
- warning (0, "cast to pointer from integer of different size");
+ warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
+ "of different size");
if (flag_strict_aliasing && warn_strict_aliasing
&& TREE_CODE (type) == POINTER_TYPE
/* Casting the address of an object to non void pointer. Warn
if the cast breaks type based aliasing. */
if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
- warning (0, "type-punning to incomplete type might break strict-aliasing rules");
+ warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+ "might break strict-aliasing rules");
else
{
HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
if (!alias_sets_conflict_p (set1, set2))
- warning (0, "dereferencing type-punned pointer will break strict-aliasing rules");
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer will break strict-aliasing rules");
else if (warn_strict_aliasing > 1
&& !alias_sets_might_conflict_p (set1, set2))
- warning (0, "dereferencing type-punned pointer might break strict-aliasing rules");
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
}
}
warning (OPT_Wc___compat, "request for implicit conversion from "
"%qT to %qT not permitted in C++", rhstype, type);
+ /* Check if the right-hand side has a format attribute but the
+ left-hand side doesn't. */
+ if (warn_missing_format_attribute)
+ {
+ tree rattrs = TYPE_ATTRIBUTES (ttr), ra;
+ for (ra = rattrs; ra; ra = TREE_CHAIN (ra))
+ {
+ if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+ break;
+ }
+ if (ra)
+ {
+ tree lattrs = TYPE_ATTRIBUTES (ttl), la;
+ for (la = lattrs; la; la = TREE_CHAIN (la))
+ {
+ if (is_attribute_p ("format", TREE_PURPOSE (la)))
+ break;
+ }
+ if (!la)
+ switch (errtype)
+ {
+ case ic_argpass:
+ case ic_argpass_nonproto:
+ warning (OPT_Wmissing_format_attribute,
+ "argument %d of %qE might be "
+ "a candidate for a format attribute",
+ parmnum, rname);
+ break;
+ case ic_assign:
+ warning (OPT_Wmissing_format_attribute,
+ "assignment left-hand side might be "
+ "a candidate for a format attribute");
+ break;
+ case ic_init:
+ warning (OPT_Wmissing_format_attribute,
+ "initialization left-hand side might be "
+ "a candidate for a format attribute");
+ break;
+ case ic_return:
+ warning (OPT_Wmissing_format_attribute,
+ "return type might be "
+ "a candidate for a format attribute");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ }
+
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
/* Store the expression if valid; else report error. */
- if (warn_traditional && !in_system_header
+ if (!in_system_header
&& AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
- warning (0, "traditional C rejects automatic aggregate initialization");
+ warning (OPT_Wtraditional, "traditional C rejects automatic "
+ "aggregate initialization");
DECL_INITIAL (decl) = value;
if (TREE_CODE (inside_init) == CONSTRUCTOR)
{
- tree link;
+ unsigned HOST_WIDE_INT ix;
+ tree value;
+ bool constant_p = true;
/* Iterate through elements and check if all constructor
elements are *_CSTs. */
- for (link = CONSTRUCTOR_ELTS (inside_init);
- link;
- link = TREE_CHAIN (link))
- if (! CONSTANT_CLASS_P (TREE_VALUE (link)))
- break;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
+ if (!CONSTANT_CLASS_P (value))
+ {
+ constant_p = false;
+ break;
+ }
- if (link == NULL)
- return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
+ if (constant_p)
+ return build_vector_from_ctor (type,
+ CONSTRUCTOR_ELTS (inside_init));
}
}
{
if (code == POINTER_TYPE)
{
- if (TREE_CODE (inside_init) == STRING_CST
- || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
- inside_init = default_function_array_conversion (inside_init);
-
if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
{
- error_init ("invalid use of non-lvalue array");
- return error_mark_node;
+ if (TREE_CODE (inside_init) == STRING_CST
+ || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+ inside_init = array_to_pointer_conversion (inside_init);
+ else
+ {
+ error_init ("invalid use of non-lvalue array");
+ return error_mark_node;
+ }
}
- }
+ }
if (code == VECTOR_TYPE)
/* Although the types are compatible, we may require a
inside_init = error_mark_node;
}
+ /* Added to enable additional -Wmissing-format-attribute warnings. */
+ if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
+ inside_init = convert_for_assignment (type, inside_init, ic_init, NULL_TREE,
+ NULL_TREE, 0);
return inside_init;
}
|| code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
|| code == VECTOR_TYPE)
{
- if (TREE_CODE (init) == STRING_CST
- || TREE_CODE (init) == COMPOUND_LITERAL_EXPR)
- init = default_function_array_conversion (init);
+ if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
+ && (TREE_CODE (init) == STRING_CST
+ || TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
+ init = array_to_pointer_conversion (init);
inside_init
= convert_for_assignment (type, init, ic_init,
NULL_TREE, NULL_TREE, 0);
/* If we are saving up the elements rather than allocating them,
this is the list of elements so far (in reverse order,
most recent first). */
-static tree constructor_elements;
+static VEC(constructor_elt,gc) *constructor_elements;
/* 1 if constructor should be incrementally stored into a constructor chain,
0 if all the elements should be kept in AVL tree. */
tree unfilled_index;
tree unfilled_fields;
tree bit_index;
- tree elements;
+ VEC(constructor_elt,gc) *elements;
struct init_node *pending_elts;
int offset;
int depth;
tree decl;
struct constructor_stack *constructor_stack;
struct constructor_range_stack *constructor_range_stack;
- tree elements;
+ VEC(constructor_elt,gc) *elements;
struct spelling *spelling;
struct spelling *spelling_base;
int spelling_size;
constructor_constant = TREE_CONSTANT (value);
constructor_simple = TREE_STATIC (value);
constructor_elements = CONSTRUCTOR_ELTS (value);
- if (constructor_elements
+ if (!VEC_empty (constructor_elt, constructor_elements)
&& (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == ARRAY_TYPE))
set_nonincremental_init ();
{
/* A nonincremental scalar initializer--just return
the element, after verifying there is just one. */
- if (constructor_elements == 0)
+ if (VEC_empty (constructor_elt,constructor_elements))
{
if (!constructor_erroneous)
error_init ("empty scalar initializer");
ret.value = error_mark_node;
}
- else if (TREE_CHAIN (constructor_elements) != 0)
+ else if (VEC_length (constructor_elt,constructor_elements) != 1)
{
error_init ("extra elements in scalar initializer");
- ret.value = TREE_VALUE (constructor_elements);
+ ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
}
else
- ret.value = TREE_VALUE (constructor_elements);
+ ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
}
else
{
else
{
ret.value = build_constructor (constructor_type,
- nreverse (constructor_elements));
+ constructor_elements);
if (constructor_constant)
TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
if (constructor_constant && constructor_simple)
static void
set_nonincremental_init (void)
{
- tree chain;
+ unsigned HOST_WIDE_INT ix;
+ tree index, value;
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != ARRAY_TYPE)
return;
- for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
- add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
+ FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
+ add_pending_init (index, value);
constructor_elements = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
}
else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
- if (constructor_elements
- && TREE_PURPOSE (constructor_elements) == field)
- return TREE_VALUE (constructor_elements);
+ if (!VEC_empty (constructor_elt, constructor_elements)
+ && (VEC_last (constructor_elt, constructor_elements)->index
+ == field))
+ return VEC_last (constructor_elt, constructor_elements)->value;
}
return 0;
}
output_init_element (tree value, bool strict_string, tree type, tree field,
int pending)
{
+ constructor_elt *celt;
+
if (type == error_mark_node || value == error_mark_node)
{
constructor_erroneous = 1;
&& INTEGRAL_TYPE_P (TREE_TYPE (type)))
&& !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
TYPE_MAIN_VARIANT (type)))
- value = default_function_array_conversion (value);
+ value = array_to_pointer_conversion (value);
if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
&& require_constant_value && !flag_isoc99 && pending)
return;
}
else if (TREE_CODE (constructor_type) == UNION_TYPE
- && constructor_elements)
+ && !VEC_empty (constructor_elt, constructor_elements))
{
- if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+ if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+ constructor_elements)->value))
warning_init ("initialized field with side-effects overwritten");
/* We can have just one union field set. */
if (field && TREE_CODE (field) == INTEGER_CST)
field = copy_node (field);
- constructor_elements
- = tree_cons (field, value, constructor_elements);
+ celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
+ celt->index = field;
+ celt->value = value;
/* Advance the variable that indicates sequential elements output. */
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
again on the assumption that this must be conditional on
__STDC__ anyway (and we've already complained about the
member-designator already). */
- if (warn_traditional && !in_system_header && !constructor_designated
+ if (!in_system_header && !constructor_designated
&& !(value.value && (integer_zerop (value.value)
|| real_zerop (value.value))))
- warning (0, "traditional C rejects initialization of unions");
+ warning (OPT_Wtraditional, "traditional C rejects initialization "
+ "of unions");
/* Accept a string constant to initialize a subarray. */
if (value.value != 0
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
- if (warn_traditional && !in_system_header
+ if (!in_system_header
&& (type == long_integer_type_node
|| type == long_unsigned_type_node))
- warning (0, "%<long%> switch expression not converted to "
- "%<int%> in ISO C");
+ warning (OPT_Wtraditional, "%<long%> switch expression not "
+ "converted to %<int%> in ISO C");
exp = default_conversion (exp);
type = TREE_TYPE (exp);
tree type0, type1;
enum tree_code code0, code1;
tree op0, op1;
+ const char *invalid_op_diag;
/* Expression code to give to the expression when it is built.
Normally this is CODE, which is what the caller asked for,
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
return error_mark_node;
+ if ((invalid_op_diag
+ = targetm.invalid_binary_op (code, type0, type1)))
+ {
+ error (invalid_op_diag);
+ return error_mark_node;
+ }
+
objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
switch (code)
leaving those to give errors later? */
return c_common_truthvalue_conversion (expr);
}
+\f
+
+/* Convert EXPR to a contained DECL, updating *TC, *TI and *SE as
+ required. */
+
+tree
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
+ bool *ti ATTRIBUTE_UNUSED, bool *se)
+{
+ if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
+ {
+ tree decl = COMPOUND_LITERAL_EXPR_DECL (expr);
+ /* Executing a compound literal inside a function reinitializes
+ it. */
+ if (!TREE_STATIC (decl))
+ *se = true;
+ return decl;
+ }
+ else
+ return expr;
+}