aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 3c2c20a..af3a6a3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13571,4 +13571,67 @@ verify_type (const_tree t)
}
}
+
+/* Return true if ARG is marked with the nonnull attribute in the
+ current function signature. */
+
+bool
+nonnull_arg_p (const_tree arg)
+{
+ tree t, attrs, fntype;
+ unsigned HOST_WIDE_INT arg_num;
+
+ gcc_assert (TREE_CODE (arg) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (arg)));
+
+ /* The static chain decl is always non null. */
+ if (arg == cfun->static_chain_decl)
+ return true;
+
+ /* THIS argument of method is always non-NULL. */
+ if (TREE_CODE (TREE_TYPE (cfun->decl)) == METHOD_TYPE
+ && arg == DECL_ARGUMENTS (cfun->decl)
+ && flag_delete_null_pointer_checks)
+ return true;
+
+ /* Values passed by reference are always non-NULL. */
+ if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
+ && flag_delete_null_pointer_checks)
+ return true;
+
+ fntype = TREE_TYPE (cfun->decl);
+ for (attrs = TYPE_ATTRIBUTES (fntype); attrs; attrs = TREE_CHAIN (attrs))
+ {
+ attrs = lookup_attribute ("nonnull", attrs);
+
+ /* If "nonnull" wasn't specified, we know nothing about the argument. */
+ if (attrs == NULL_TREE)
+ return false;
+
+ /* If "nonnull" applies to all the arguments, then ARG is non-null. */
+ if (TREE_VALUE (attrs) == NULL_TREE)
+ return true;
+
+ /* Get the position number for ARG in the function signature. */
+ for (arg_num = 1, t = DECL_ARGUMENTS (cfun->decl);
+ t;
+ t = DECL_CHAIN (t), arg_num++)
+ {
+ if (t == arg)
+ break;
+ }
+
+ gcc_assert (t == arg);
+
+ /* Now see if ARG_NUM is mentioned in the nonnull list. */
+ for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
+ {
+ if (compare_tree_int (TREE_VALUE (t), arg_num) == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
#include "gt-tree.h"