aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/c-format.c140
2 files changed, 78 insertions, 68 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 40a75a5..231dccd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2003-06-19 Osku Salerma <osku@iki.fi>
+
+ * c-format.c (check_format_string, get_constant): New.
+ (handle_format_attribute, handle_format_arg_attribute,
+ decode_format_attr): Change to use above functions.
+
2003-06-09 Richard Henderson <rth@redhat.com>
* stmt.c (expand_asm_operands): Re-word warning.
diff --git a/gcc/c-format.c b/gcc/c-format.c
index a6ae983..1199667 100644
--- a/gcc/c-format.c
+++ b/gcc/c-format.c
@@ -71,6 +71,11 @@ static bool decode_format_attr PARAMS ((tree,
function_format_info *, int));
static enum format_type decode_format_type PARAMS ((const char *));
+static bool check_format_string (tree argument,
+ unsigned HOST_WIDE_INT format_num,
+ int flags, bool *no_add_attrs);
+static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value,
+ int validated_p);
/* Handle a "format_arg" attribute; arguments as in
@@ -86,46 +91,20 @@ handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
tree type = *node;
tree format_num_expr = TREE_VALUE (args);
unsigned HOST_WIDE_INT format_num;
- unsigned HOST_WIDE_INT arg_num;
tree argument;
- /* Strip any conversions from the first arg number and verify it
- is a constant. */
- while (TREE_CODE (format_num_expr) == NOP_EXPR
- || TREE_CODE (format_num_expr) == CONVERT_EXPR
- || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
- format_num_expr = TREE_OPERAND (format_num_expr, 0);
-
- if (TREE_CODE (format_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (format_num_expr) != 0)
+ if (!get_constant (format_num_expr, &format_num, 0))
{
error ("format string has invalid operand number");
*no_add_attrs = true;
return NULL_TREE;
}
- format_num = TREE_INT_CST_LOW (format_num_expr);
-
- /* If a parameter list is specified, verify that the format_num
- argument is actually a string, in case the format attribute
- is in error. */
argument = TYPE_ARG_TYPES (type);
if (argument)
{
- for (arg_num = 1; argument != 0 && arg_num != format_num;
- ++arg_num, argument = TREE_CHAIN (argument))
- ;
-
- if (! argument
- || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
- || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
- != char_type_node))
- {
- if (!(flags & (int) ATTR_FLAG_BUILT_IN))
- error ("format string arg not a string type");
- *no_add_attrs = true;
- return NULL_TREE;
- }
+ if (!check_format_string (argument, format_num, flags, no_add_attrs))
+ return NULL_TREE;
}
if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
@@ -141,6 +120,57 @@ handle_format_arg_attribute (node, name, args, flags, no_add_attrs)
return NULL_TREE;
}
+/* Verify that the format_num argument is actually a string, in case
+ the format attribute is in error. */
+bool
+check_format_string (tree argument, unsigned HOST_WIDE_INT format_num,
+ int flags, bool *no_add_attrs)
+{
+ unsigned HOST_WIDE_INT i;
+
+ for (i = 1; i != format_num; i++)
+ {
+ if (argument == 0)
+ break;
+ argument = TREE_CHAIN (argument);
+ }
+
+ if (!argument
+ || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
+ != char_type_node))
+ {
+ if (!(flags & (int) ATTR_FLAG_BUILT_IN))
+ error ("format string arg not a string type");
+ *no_add_attrs = true;
+ return false;
+ }
+
+ return true;
+}
+
+/* Strip any conversions from the expression, verify it is a constant,
+ and store its value. If validated_p is true, abort on errors.
+ Returns true on success, false otherwise. */
+bool
+get_constant(tree expr, unsigned HOST_WIDE_INT *value, int validated_p)
+{
+ while (TREE_CODE (expr) == NOP_EXPR
+ || TREE_CODE (expr) == CONVERT_EXPR
+ || TREE_CODE (expr) == NON_LVALUE_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ if (TREE_CODE (expr) != INTEGER_CST || TREE_INT_CST_HIGH (expr) != 0)
+ {
+ if (validated_p)
+ abort ();
+ return false;
+ }
+
+ *value = TREE_INT_CST_LOW (expr);
+
+ return true;
+}
/* Decode the arguments to a "format" attribute into a function_format_info
structure. It is already known that the list is of the right length.
@@ -182,31 +212,18 @@ decode_format_attr (args, info, validated_p)
}
}
- /* Strip any conversions from the string index and first arg number
- and verify they are constants. */
- while (TREE_CODE (format_num_expr) == NOP_EXPR
- || TREE_CODE (format_num_expr) == CONVERT_EXPR
- || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
- format_num_expr = TREE_OPERAND (format_num_expr, 0);
-
- while (TREE_CODE (first_arg_num_expr) == NOP_EXPR
- || TREE_CODE (first_arg_num_expr) == CONVERT_EXPR
- || TREE_CODE (first_arg_num_expr) == NON_LVALUE_EXPR)
- first_arg_num_expr = TREE_OPERAND (first_arg_num_expr, 0);
-
- if (TREE_CODE (format_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (format_num_expr) != 0
- || TREE_CODE (first_arg_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (first_arg_num_expr) != 0)
+ if (!get_constant (format_num_expr, &info->format_num, validated_p))
{
- if (validated_p)
- abort ();
error ("format string has invalid operand number");
return false;
}
- info->format_num = TREE_INT_CST_LOW (format_num_expr);
- info->first_arg_num = TREE_INT_CST_LOW (first_arg_num_expr);
+ if (!get_constant (first_arg_num_expr, &info->first_arg_num, validated_p))
+ {
+ error ("'...' has invalid operand number");
+ return false;
+ }
+
if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)
{
if (validated_p)
@@ -2363,7 +2380,6 @@ handle_format_attribute (node, name, args, flags, no_add_attrs)
tree type = *node;
function_format_info info;
tree argument;
- unsigned HOST_WIDE_INT arg_num;
if (!decode_format_attr (args, &info, 0))
{
@@ -2371,29 +2387,17 @@ handle_format_attribute (node, name, args, flags, no_add_attrs)
return NULL_TREE;
}
- /* If a parameter list is specified, verify that the format_num
- argument is actually a string, in case the format attribute
- is in error. */
argument = TYPE_ARG_TYPES (type);
if (argument)
{
- for (arg_num = 1; argument != 0 && arg_num != info.format_num;
- ++arg_num, argument = TREE_CHAIN (argument))
- ;
-
- if (! argument
- || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
- || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
- != char_type_node))
- {
- if (!(flags & (int) ATTR_FLAG_BUILT_IN))
- error ("format string arg not a string type");
- *no_add_attrs = true;
- return NULL_TREE;
- }
+ if (!check_format_string (argument, info.format_num, flags,
+ no_add_attrs))
+ return NULL_TREE;
- else if (info.first_arg_num != 0)
+ if (info.first_arg_num != 0)
{
+ unsigned HOST_WIDE_INT arg_num = 1;
+
/* Verify that first_arg_num points to the last arg,
the ... */
while (argument)