/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
static void push_member_name (tree);
static int spelling_length (void);
static char *print_spelling (char *);
-static void warning_init (const char *);
+static void warning_init (int, const char *);
static tree digest_init (tree, tree, bool, int);
static void output_init_element (tree, bool, tree, tree, int);
static void output_pending_init_elements (int);
tree pointed_to_1, mv1;
tree pointed_to_2, mv2;
tree target;
+ unsigned target_quals;
/* Save time if the two types are the same. */
if (TREE_CODE (mv2) != ARRAY_TYPE)
mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
target = composite_type (mv1, mv2);
- t1 = build_pointer_type (c_build_qualified_type
- (target,
- TYPE_QUALS (pointed_to_1) |
- TYPE_QUALS (pointed_to_2)));
+
+ /* For function types do not merge const qualifiers, but drop them
+ if used inconsistently. The middle-end uses these to mark const
+ and noreturn functions. */
+ if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
+ target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+ else
+ target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+ t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
return build_type_attribute_variant (t1, attributes);
}
{
int result;
-
- if (DECL_NAME (s1) == NULL
- || DECL_NAME (s1) != DECL_NAME (s2))
+ if (DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+
+ if (result != 1 && !DECL_NAME (s1))
+ break;
if (result == 0)
{
tu->val = 0;
{
bool ok = false;
- if (DECL_NAME (s1) != NULL)
- for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
- if (DECL_NAME (s1) == DECL_NAME (s2))
- {
- int result;
- result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
- if (result == 0)
- {
- tu->val = 0;
- return 0;
- }
- if (result == 2)
- needs_warning = true;
+ for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+ if (DECL_NAME (s1) == DECL_NAME (s2))
+ {
+ int result;
- if (TREE_CODE (s1) == FIELD_DECL
- && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
- DECL_FIELD_BIT_OFFSET (s2)) != 1)
- break;
+ result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
- ok = true;
+ if (result != 1 && !DECL_NAME (s1))
+ continue;
+ if (result == 0)
+ {
+ tu->val = 0;
+ return 0;
+ }
+ if (result == 2)
+ needs_warning = true;
+
+ if (TREE_CODE (s1) == FIELD_DECL
+ && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+ DECL_FIELD_BIT_OFFSET (s2)) != 1)
break;
- }
+
+ ok = true;
+ break;
+ }
if (!ok)
{
tu->val = 0;
bool lvalue_array_p;
while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
- || TREE_CODE (exp.value) == NOP_EXPR
- || TREE_CODE (exp.value) == CONVERT_EXPR)
+ || CONVERT_EXPR_P (exp.value))
&& TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
{
if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
if (TREE_CODE (type) == POINTER_TYPE)
{
- if (TREE_CODE (pointer) == CONVERT_EXPR
- || TREE_CODE (pointer) == NOP_EXPR
+ if (CONVERT_EXPR_P (pointer)
|| TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
{
/* If a warning is issued, mark it to avoid duplicates from
used_types_insert (TREE_TYPE (ref));
ref = DECL_INITIAL (ref);
TREE_CONSTANT (ref) = 1;
- TREE_INVARIANT (ref) = 1;
}
else if (current_function_decl != 0
&& !DECL_FILE_SCOPE_P (current_function_decl)
&& DECL_EXTERNAL (current_function_decl)
&& VAR_OR_FUNCTION_DECL_P (ref)
&& (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
- && ! TREE_PUBLIC (ref))
+ && ! TREE_PUBLIC (ref)
+ && DECL_CONTEXT (ref) != current_function_decl)
pedwarn ("%H%qD is static but used in inline function %qD "
"which is not static", &loc, ref, current_function_decl);
expression if necessary. This has the nice side-effect to prevent
the tree-inliner from generating invalid assignment trees which may
blow up in the RTL expander later. */
- if ((TREE_CODE (function) == NOP_EXPR
- || TREE_CODE (function) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (function)
&& TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
&& TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
&& !comptypes (fntype, TREE_TYPE (tem)))
if (nargs < 0)
return error_mark_node;
- /* Check that the arguments to the function are valid. */
+ /* Check that arguments to builtin functions match the expectations. */
+ if (fundecl
+ && DECL_BUILT_IN (fundecl)
+ && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
+ && !check_builtin_function_arguments (fundecl, nargs, argarray))
+ return error_mark_node;
+ /* Check that the arguments to the function are valid. */
check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
TYPE_ARG_TYPES (fntype));
different mode in place.)
So first try to find a common term here 'by hand'; we want to cover
at least the cases that occur in legal static initializers. */
- if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (op0)
&& (TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
con0 = TREE_OPERAND (op0, 0);
else
con0 = op0;
- if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (op1)
&& (TYPE_PRECISION (TREE_TYPE (op1))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
con1 = TREE_OPERAND (op1, 0);
&& tree_expr_nonnegative_warnv_p (op2, &ovf)))
/* OK */;
else
- warning (0, "signed and unsigned type in conditional expression");
+ warning (OPT_Wsign_compare, "signed and unsigned type in conditional expression");
}
}
}
if (!TREE_SIDE_EFFECTS (expr1))
{
/* The left-hand operand of a comma expression is like an expression
- statement: with -Wextra or -Wunused, we should warn if it doesn't have
+ statement: with -Wunused, we should warn if it doesn't have
any side-effects, unless it was explicitly cast to (void). */
if (warn_unused_value)
{
if (VOID_TYPE_P (TREE_TYPE (expr1))
- && (TREE_CODE (expr1) == NOP_EXPR
- || TREE_CODE (expr1) == CONVERT_EXPR))
+ && CONVERT_EXPR_P (expr1))
; /* (void) a, b */
else if (VOID_TYPE_P (TREE_TYPE (expr1))
&& TREE_CODE (expr1) == COMPOUND_EXPR
- && (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR
- || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
+ && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
; /* (void) a, (void) b, c */
else
warning (OPT_Wunused_value,
tree field;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
- TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+ if (TREE_TYPE (field) != error_mark_node
+ && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (value))))
break;
if (field)
build_constructor_single (type, field, value),
true, 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
- TREE_INVARIANT (t) = TREE_INVARIANT (value);
return t;
}
error ("cast to union type from type not present in union");
pedwarn ("(near initialization for %qs)", ofwhat);
}
-/* Issue a warning for a bad initializer component.
- MSGID identifies the message.
- The component name is taken from the spelling stack. */
+/* Issue a warning for a bad initializer component.
+
+ OPT is the OPT_W* value corresponding to the warning option that
+ controls this warning. MSGID identifies the message. The
+ component name is taken from the spelling stack. */
static void
-warning_init (const char *msgid)
+warning_init (int opt, const char *msgid)
{
char *ofwhat;
- warning (0, "%s", _(msgid));
+ warning (opt, "%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- warning (0, "(near initialization for %qs)", ofwhat);
+ warning (opt, "(near initialization for %qs)", ofwhat);
}
\f
/* If TYPE is an array type and EXPR is a parenthesized string
if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
- warning_init ("missing braces around initializer");
+ warning_init (OPT_Wmissing_braces, "missing braces around initializer");
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
else
{
if (constructor_type != error_mark_node)
- warning_init ("braces around scalar initializer");
+ warning_init (0, "braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
if (constructor_unfilled_fields && !constructor_designated)
{
push_member_name (constructor_unfilled_fields);
- warning_init ("missing initializer");
+ warning_init (OPT_Wmissing_field_initializers,
+ "missing initializer");
RESTORE_SPELLING_DEPTH (constructor_depth);
}
}
ret.value = build_constructor (constructor_type,
constructor_elements);
if (constructor_constant)
- TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
+ TREE_CONSTANT (ret.value) = 1;
if (constructor_constant && constructor_simple)
TREE_STATIC (ret.value) = 1;
}
else
{
if (TREE_SIDE_EFFECTS (p->value))
- warning_init ("initialized field with side-effects overwritten");
+ warning_init (0, "initialized field with side-effects overwritten");
else if (warn_override_init)
- warning_init ("initialized field overwritten");
+ warning_init (OPT_Woverride_init, "initialized field overwritten");
p->value = value;
return;
}
else
{
if (TREE_SIDE_EFFECTS (p->value))
- warning_init ("initialized field with side-effects overwritten");
+ warning_init (0, "initialized field with side-effects overwritten");
else if (warn_override_init)
- warning_init ("initialized field overwritten");
+ warning_init (OPT_Woverride_init, "initialized field overwritten");
p->value = value;
return;
}
{
if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
constructor_elements)->value))
- warning_init ("initialized field with side-effects overwritten");
+ warning_init (0, "initialized field with side-effects overwritten");
else if (warn_override_init)
- warning_init ("initialized field overwritten");
+ warning_init (OPT_Woverride_init, "initialized field overwritten");
/* We can have just one union field set. */
constructor_elements = 0;
{
switch (TREE_CODE (inner))
{
- case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
+ CASE_CONVERT: case NON_LVALUE_EXPR:
case PLUS_EXPR:
inner = TREE_OPERAND (inner, 0);
continue;
tree op1 = TREE_OPERAND (inner, 1);
while (!POINTER_TYPE_P (TREE_TYPE (op1))
- && (TREE_CODE (op1) == NOP_EXPR
- || TREE_CODE (op1) == NON_LVALUE_EXPR
- || TREE_CODE (op1) == CONVERT_EXPR))
+ && (CONVERT_EXPR_P (op1)
+ || TREE_CODE (op1) == NON_LVALUE_EXPR))
op1 = TREE_OPERAND (op1, 0);
if (POINTER_TYPE_P (TREE_TYPE (op1)))
if (skip)
return NULL_TREE;
+ if (!is_break)
+ add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
+
return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
}
case EQ_EXPR:
case NE_EXPR:
- if (code0 == REAL_TYPE || code1 == REAL_TYPE)
+ if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
warning (OPT_Wfloat_equal,
"comparing floating point with == or != is unsafe");
/* Result of comparison is always int,
c_common_signed_type (result_type)))
/* OK */;
else
- warning (0, "comparison between signed and unsigned");
+ warning (OPT_Wsign_compare, "comparison between signed and unsigned");
}
/* Warn if two unsigned values are being compared in a size
{
mask = (~(HOST_WIDE_INT) 0) << bits;
if ((mask & constant) != mask)
- warning (0, "comparison of promoted ~unsigned with constant");
+ warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with constant");
}
}
else if (unsignedp0 && unsignedp1
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (primop1))
< TYPE_PRECISION (result_type)))
- warning (0, "comparison of promoted ~unsigned with unsigned");
+ warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with unsigned");
}
}
}
required. */
tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
- bool *ti ATTRIBUTE_UNUSED, bool *se)
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
{
if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
{
bitmap_obstack_release (NULL);
return clauses;
}
+
+/* Make a variant type in the proper way for C/C++, propagating qualifiers
+ down to the element type of an array. */
+
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+ if (type == error_mark_node)
+ return type;
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree t;
+ tree element_type = c_build_qualified_type (TREE_TYPE (type),
+ type_quals);
+
+ /* See if we already have an identically qualified type. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ {
+ if (TYPE_QUALS (strip_array_types (t)) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+ && attribute_list_equal (TYPE_ATTRIBUTES (t),
+ TYPE_ATTRIBUTES (type)))
+ break;
+ }
+ if (!t)
+ {
+ tree domain = TYPE_DOMAIN (type);
+
+ t = build_variant_type_copy (type);
+ TREE_TYPE (t) = element_type;
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
+ || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (element_type) != element_type
+ || (domain && TYPE_CANONICAL (domain) != domain))
+ {
+ tree unqualified_canon
+ = build_array_type (TYPE_CANONICAL (element_type),
+ domain? TYPE_CANONICAL (domain)
+ : NULL_TREE);
+ TYPE_CANONICAL (t)
+ = c_build_qualified_type (unqualified_canon, type_quals);
+ }
+ else
+ TYPE_CANONICAL (t) = t;
+ }
+ return t;
+ }
+
+ /* A restrict-qualified pointer type must be a pointer to object or
+ incomplete type. Note that the use of POINTER_TYPE_P also allows
+ REFERENCE_TYPEs, which is appropriate for C++. */
+ if ((type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+ {
+ error ("invalid use of %<restrict%>");
+ type_quals &= ~TYPE_QUAL_RESTRICT;
+ }
+
+ return build_qualified_type (type, type_quals);
+}