diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2004-09-05 02:55:28 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2004-09-05 02:55:28 +0000 |
commit | 254986c7ff3175c29307b999f161cfcc7961baf4 (patch) | |
tree | 35944d27904d831ba5d78370c59d633d19c4fe13 /gcc/c-common.c | |
parent | 44269c4093f881d5321ee09d40490e1989345bae (diff) | |
download | gcc-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.c | 84 |
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; |