aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2004-09-05 02:55:28 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2004-09-05 02:55:28 +0000
commit254986c7ff3175c29307b999f161cfcc7961baf4 (patch)
tree35944d27904d831ba5d78370c59d633d19c4fe13 /gcc/c-common.c
parent44269c4093f881d5321ee09d40490e1989345bae (diff)
downloadgcc-254986c7ff3175c29307b999f161cfcc7961baf4.zip
gcc-254986c7ff3175c29307b999f161cfcc7961baf4.tar.gz
gcc-254986c7ff3175c29307b999f161cfcc7961baf4.tar.bz2
builtin-attrs.def (ATTR_NOTHROW_SENTINEL_1): New.
* builtin-attrs.def (ATTR_NOTHROW_SENTINEL_1): New. * builtins.def (BUILT_IN_EXECLE): Set ATTR_NOTHROW_SENTINEL_1. * c-common.c (c_common_attribute_table): Accept parameters to sentinel attribute. (check_function_sentinel, handle_sentinel_attribute): Likewise. * doc/extend.texi: Update accordingly. testsuite: * gcc.dg/format/sentinel-1.c: Update for parameter option. From-SVN: r87098
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c84
1 files changed, 67 insertions, 17 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 3af1e64..1a10570 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -636,7 +636,7 @@ const struct attribute_spec c_common_attribute_table[] =
handle_cleanup_attribute },
{ "warn_unused_result", 0, 0, false, true, true,
handle_warn_unused_result_attribute },
- { "sentinel", 0, 0, false, true, true,
+ { "sentinel", 0, 1, false, true, true,
handle_sentinel_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -5047,7 +5047,8 @@ check_function_nonnull (tree attrs, tree params)
}
}
-/* Check the last argument of a function call is (pointer)0. */
+/* Check that the Nth argument of a function call (counting backwards
+ from the end) is a (pointer)0. */
static void
check_function_sentinel (tree attrs, tree params)
@@ -5060,11 +5061,40 @@ check_function_sentinel (tree attrs, tree params)
warning ("missing sentinel in function call");
else
{
- /* Find the last parameter. */
- while (TREE_CHAIN (params))
- params = TREE_CHAIN (params);
- if (!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (params)))
- || !integer_zerop (TREE_VALUE (params)))
+ tree sentinel, end;
+ unsigned pos = 0;
+
+ if (TREE_VALUE (attr))
+ {
+ tree p = TREE_VALUE (TREE_VALUE (attr));
+ STRIP_NOPS (p);
+ pos = TREE_INT_CST_LOW (p);
+ }
+
+ sentinel = end = params;
+
+ /* Advance `end' ahead of `sentinel' by `pos' positions. */
+ while (pos > 0 && TREE_CHAIN (end))
+ {
+ pos--;
+ end = TREE_CHAIN (end);
+ }
+ if (pos > 0)
+ {
+ warning ("not enough arguments to fit a sentinel");
+ return;
+ }
+
+ /* Now advance both until we find the last parameter. */
+ while (TREE_CHAIN (end))
+ {
+ end = TREE_CHAIN (end);
+ sentinel = TREE_CHAIN (sentinel);
+ }
+
+ /* Validate the sentinel. */
+ if (!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
+ || !integer_zerop (TREE_VALUE (sentinel)))
warning ("missing sentinel in function call");
}
}
@@ -5215,8 +5245,7 @@ handle_warn_unused_result_attribute (tree *node, tree name,
/* Handle a "sentinel" attribute. */
static tree
-handle_sentinel_attribute (tree *node, tree name,
- tree ARG_UNUSED (args),
+handle_sentinel_attribute (tree *node, tree name, tree args,
int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree params = TYPE_ARG_TYPES (*node);
@@ -5226,17 +5255,38 @@ handle_sentinel_attribute (tree *node, tree name,
warning ("`%s' attribute requires prototypes with named arguments",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
- return NULL_TREE;
}
+ else
+ {
+ while (TREE_CHAIN (params))
+ params = TREE_CHAIN (params);
- while (TREE_CHAIN (params))
- params = TREE_CHAIN (params);
-
- if (VOID_TYPE_P (TREE_VALUE (params)))
+ if (VOID_TYPE_P (TREE_VALUE (params)))
+ {
+ warning ("`%s' attribute only applies to variadic functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ }
+
+ if (args)
{
- warning ("`%s' attribute only applies to variadic functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
+ tree position = TREE_VALUE (args);
+
+ STRIP_NOPS (position);
+ if (TREE_CODE (position) != INTEGER_CST)
+ {
+ warning ("requested position is not an integer constant");
+ *no_add_attrs = true;
+ }
+ else
+ {
+ if (tree_int_cst_lt (position, integer_zero_node))
+ {
+ warning ("requested position is less than zero");
+ *no_add_attrs = true;
+ }
+ }
}
return NULL_TREE;