extern struct obstack permanent_obstack;
+/* Nonzero means the expression being parsed will never be evaluated.
+ This is a count, since unevaluated expressions can nest. */
+int skip_evaluation;
+
enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};
/* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES
and install them in NODE, which is either a DECL (including a TYPE_DECL)
or a TYPE. PREFIX_ATTRIBUTES can appear after the declaration specifiers
- and declaration modifiers but before the declaration proper. */
+ and declaration modifiers but before the declaration proper. */
void
decl_attributes (node, attributes, prefix_attributes)
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST)
{
if (TREE_CODE (decl) == VAR_DECL
- && current_function_decl != NULL_TREE)
+ && current_function_decl != NULL_TREE
+ && ! TREE_STATIC (decl))
error_with_decl (decl,
"section attribute cannot be specified for local variables");
/* The decl may have already been given a section attribute from
if (first_arg_num != 0)
{
/* Verify that first_arg_num points to the last arg,
- the ... */
+ the ... */
while (argument)
arg_num++, argument = TREE_CHAIN (argument);
if (arg_num != first_arg_num)
case A_ALIAS:
if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
- || TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))
+ || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
error_with_decl (decl,
"`%s' defined both normally and as an alias");
else if (decl_function_context (decl) == 0)
}
}
}
+
+/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
+ lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
+
+ The head of the declspec list is stored in DECLSPECS.
+ The head of the attribute list is stored in PREFIX_ATTRIBUTES.
+
+ Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
+ the list elements. We drop the containing TREE_LIST nodes and link the
+ resulting attributes together the way decl_attributes expects them. */
+
+void
+split_specs_attrs (specs_attrs, declspecs, prefix_attributes)
+ tree specs_attrs;
+ tree *declspecs, *prefix_attributes;
+{
+ tree t, s, a, next, specs, attrs;
+
+ /* This can happen in c++ (eg: decl: typespec initdecls ';'). */
+ if (specs_attrs != NULL_TREE
+ && TREE_CODE (specs_attrs) != TREE_LIST)
+ {
+ *declspecs = specs_attrs;
+ *prefix_attributes = NULL_TREE;
+ return;
+ }
+
+ /* Remember to keep the lists in the same order, element-wise. */
+
+ specs = s = NULL_TREE;
+ attrs = a = NULL_TREE;
+ for (t = specs_attrs; t; t = next)
+ {
+ next = TREE_CHAIN (t);
+ /* Declspecs have a non-NULL TREE_VALUE. */
+ if (TREE_VALUE (t) != NULL_TREE)
+ {
+ if (specs == NULL_TREE)
+ specs = s = t;
+ else
+ {
+ TREE_CHAIN (s) = t;
+ s = t;
+ }
+ }
+ else
+ {
+ if (attrs == NULL_TREE)
+ attrs = a = TREE_PURPOSE (t);
+ else
+ {
+ TREE_CHAIN (a) = TREE_PURPOSE (t);
+ a = TREE_PURPOSE (t);
+ }
+ /* More attrs can be linked here, move A to the end. */
+ while (TREE_CHAIN (a) != NULL_TREE)
+ a = TREE_CHAIN (a);
+ }
+ }
+
+ /* Terminate the lists. */
+ if (s != NULL_TREE)
+ TREE_CHAIN (s) = NULL_TREE;
+ if (a != NULL_TREE)
+ TREE_CHAIN (a) = NULL_TREE;
+
+ /* All done. */
+ *declspecs = specs;
+ *prefix_attributes = attrs;
+}
\f
/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against
a parameter list. */
the number of the argument which is the format control string (starting
from 1). */
-void
+static void
record_international_format (name, assembler_name, format_num)
tree name;
tree assembler_name;
|| format_char == 'x' || format_char == 'x'))
{
sprintf (message,
- "precision and `0' flag not both allowed with `%c' format",
+ "`0' flag ignored with precision specifier and `%c' format",
format_char);
warning (message);
}
&& TREE_OVERFLOW (value))
{
TREE_OVERFLOW (value) = 0;
- warning ("integer overflow in expression");
+ if (skip_evaluation == 0)
+ warning ("integer overflow in expression");
}
else if ((TREE_CODE (value) == REAL_CST
|| (TREE_CODE (value) == COMPLEX_CST
&& TREE_OVERFLOW (value))
{
TREE_OVERFLOW (value) = 0;
- warning ("floating point overflow in expression");
+ if (skip_evaluation == 0)
+ warning ("floating point overflow in expression");
}
}
if (TREE_CODE (operand) == INTEGER_CST
&& TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
&& TREE_UNSIGNED (TREE_TYPE (result))
+ && skip_evaluation == 0
&& !int_fits_type_p (operand, TREE_TYPE (result)))
{
if (!int_fits_type_p (operand, signed_type (TREE_TYPE (result))))
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
/* If EXPR fits in the unsigned version of TYPE,
don't warn unless pedantic. */
- if (pedantic
- || TREE_UNSIGNED (type)
- || ! int_fits_type_p (expr, unsigned_type (type)))
- warning ("overflow in implicit constant conversion");
+ if ((pedantic
+ || TREE_UNSIGNED (type)
+ || ! int_fits_type_p (expr, unsigned_type (type)))
+ && skip_evaluation == 0)
+ warning ("overflow in implicit constant conversion");
}
else
unsigned_conversion_warning (t, expr);
if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
break;
- /* fall through... */
+ /* fall through... */
case NOP_EXPR:
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr))
if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
&& TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
break;
- /* fall through... */
+ /* fall through... */
case BIT_XOR_EXPR:
/* This and MINUS_EXPR can be changed into a comparison of the
two objects. */