@@ -1,3 +1,8 @@
+2015-05-09 Martin Uecker <uecker@eecs.berkeley.edu>
+
+ * gcc/gimple.c (infer_nonnull_range): Process nonzero attribute.
+ * doc/invoki.texi
+
2015-05-08 Jim Wilson <jim.wilson@linaro.org>
* doc/install.texi (--enable-languages): Add missing jit and lto info.
@@ -1,3 +1,9 @@
+2015-05-09 Martin Uecker <uecker@eecs.berkeley.edu>
+
+ * c-common.c (handle_nonzero_attribute): New.
+ (check_function_nonzero): New.
+ (check_nonzero_arg): New.
+
2015-05-08 Marek Polacek <polacek@redhat.com>
PR c/64918
@@ -380,6 +380,7 @@ static tree handle_deprecated_attribute (tree *, tree, tree, int,
static tree handle_vector_size_attribute (tree *, tree, tree, int,
bool *);
static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nonzero_attribute (tree *, tree, tree, int, bool *);
static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
@@ -407,6 +408,7 @@ static tree handle_bnd_instrument (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
+static void check_nonzero_arg (void *, tree, unsigned HOST_WIDE_INT);
static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
static int resort_field_decl_cmp (const void *, const void *);
@@ -751,6 +753,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_tls_model_attribute, false },
{ "nonnull", 0, -1, false, true, true,
handle_nonnull_attribute, false },
+ { "nonzero", 0, -1, false, true, false,
+ handle_nonzero_attribute, false },
{ "nothrow", 0, 0, true, false, false,
handle_nothrow_attribute, false },
{ "may_alias", 0, 0, false, true, false, NULL, false },
@@ -8940,6 +8944,26 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
return NULL_TREE;
}
+
+/* Handle the "nonzero" attribute. */
+static tree
+handle_nonzero_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree n = *node;
+
+ if ((TREE_CODE (n) != POINTER_TYPE)
+ && (TREE_CODE (n) != INTEGER_TYPE))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+
/* Handle the "nonnull" attribute. */
static tree
handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
@@ -9016,6 +9040,34 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
+
+static void
+check_function_nonzero (const_tree fntype, int nargs, tree *argarray)
+{
+ if (TREE_CODE (fntype) != FUNCTION_TYPE) // C++ lambdas
+ return;
+
+ function_args_iterator iter;
+ tree type;
+ int i = 0;
+
+ FOREACH_FUNCTION_ARGS (fntype, type, iter)
+ {
+ if (i == nargs)
+ break;
+
+ tree a = lookup_attribute ("nonzero", TYPE_ATTRIBUTES (type));
+
+ if (a != NULL_TREE)
+ check_function_arguments_recurse (check_nonzero_arg, NULL,
+ argarray[i], i + 1);
+
+ i++;
+ }
+}
+
+
+
/* Check the argument list of a function call for null in argument slots
that are marked as requiring a non-null pointer argument. The NARGS
arguments are passed in the array ARGARRAY.
@@ -9139,6 +9191,21 @@ nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
return false;
}
+
+/* Check that the function argument PARAM (which is operand number
+ PARAM_NUM) is non-null. This is called by check_function_nonzero
+ via check_function_arguments_recurse. */
+
+static void
+check_nonzero_arg (void * ARG_UNUSED (ctx), tree param,
+ unsigned HOST_WIDE_INT param_num)
+{
+ if (integer_zerop (param))
+ warning (OPT_Wnonnull, "zero argument where non-zero required "
+ "(argument %lu)", (unsigned long) param_num);
+}
+
+
/* Check that the function argument PARAM (which is operand number
PARAM_NUM) is non-null. This is called by check_function_nonnull
via check_function_arguments_recurse. */
@@ -9573,8 +9640,11 @@ check_function_arguments (const_tree fntype, int nargs, tree *argarray)
/* Check for null being passed in a pointer argument that must be
non-null. We also need to do this if format checking is enabled. */
- if (warn_nonnull)
+ if (warn_nonnull) {
+
check_function_nonnull (TYPE_ATTRIBUTES (fntype), nargs, argarray);
+ check_function_nonzero (fntype, nargs, argarray);
+ }
/* Check for errors in format strings. */
@@ -1,3 +1,8 @@
+2015-05-09 Martin Uecker <uecker@eecs.berkeley.edu>
+
+ * c-decl.c (grokdeclarator): Allow attributes for pointers
+ declared as arrays. Add nonzero attribute for static.
+
2015-05-08 Marek Polacek <polacek@redhat.com>
PR c/64918
@@ -6437,10 +6437,12 @@ grokdeclarator (const struct c_declarator *declarator,
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- /* We don't yet implement attributes in this context. */
- if (array_ptr_attrs != NULL_TREE)
- warning_at (loc, OPT_Wattributes,
- "attributes in parameter array declarator ignored");
+ if (array_parm_static)
+ array_ptr_attrs = tree_cons (get_identifier ("nonzero"), NULL_TREE, array_ptr_attrs);
+
+ if (array_ptr_attrs != NULL_TREE)
+ type = build_type_attribute_variant (type, array_ptr_attrs);
+
size_varies = false;
array_parameter_p = true;
@@ -3698,7 +3698,8 @@ formats that may yield only a two-digit year.
@opindex Wnonnull
@opindex Wno-nonnull
Warn about passing a null pointer for arguments marked as
-requiring a non-null value by the @code{nonnull} function attribute.
+requiring a non-null value by the @code{nonnull} function attribute
+or by the @code{nonzero} type attribute.
@option{-Wnonnull} is included in @option{-Wall} and @option{-Wformat}. It
can be disabled with the @option{-Wno-nonnull} option.
@@ -5791,13 +5792,14 @@ This option does not work well with @code{FE_INVALID} exceptions enabled.
This option enables instrumentation of calls, checking whether null values
are not passed to arguments marked as requiring a non-null value by the
-@code{nonnull} function attribute.
+@code{nonnull} function attribute or by the @code{nonzero} type attribute.
@item -fsanitize=returns-nonnull-attribute
@opindex fsanitize=returns-nonnull-attribute
This option enables instrumentation of return statements in functions
-marked with @code{returns_nonnull} function attribute, to detect returning
+marked with @code{returns_nonnull} function attribute or with a return
+type marked with the @code{nonzero} attribute, to detect returning
of null values from such functions.
@item -fsanitize=bool
@@ -2679,6 +2679,10 @@ infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
return true;
if (attribute
+ && lookup_attribute ("nonzero", TYPE_ATTRIBUTES (TREE_TYPE (op))))
+ return true;
+
+ if (attribute
&& is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
{
tree fntype = gimple_call_fntype (stmt);
@@ -1,3 +1,11 @@
+2015-05-09 Martin Uecker <uecker@eecs.berkeley.edu>
+
+ * c-c++-common/attr-nonzero.c: New test.
+ * c-c++-common/ubsan/nonzero-1.c: New test.
+ * c-c++-common/ubsan/nonzero-2.c: New test.
+ * gcc.dg/array-parm.c: New test.
+ * gcc.dg/ubsan/array-parm.c: New test.
+
2015-05-08 Richard Biener <rguenther@suse.de>
PR tree-optimization/66036
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+void foo(__attribute__((nonzero)) int x);
+
+void bar(void)
+{
+ foo(0); /* { dg-warning "zero argument" } */
+}
+
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined" } */
+
+typedef __attribute__((nonzero)) int* nonzero_ptr;
+
+void foo(nonzero_ptr a)
+{
+}
+
+int main(void)
+{
+ foo(0);
+}
+
+/* { dg-output "runtime error: null pointer passed as argument 1" } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined" } */
+
+typedef __attribute__((nonzero)) int* nonzero_ptr;
+
+nonzero_ptr foo(void)
+{
+ return 0;
+}
+
+int main(void)
+{
+ foo();
+}
+
+/* { dg-output "runtime error: null pointer returned from function declared to never return null" } */
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+void foo0(int x[static 0]);
+void foo1(int x[__attribute__((nonzero))]);
+
+void bar(void)
+{
+ foo0(0); /* { dg-warning "zero argument" } */
+ foo1(0); /* { dg-warning "zero argument" } */
+}
+
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined" } */
+
+void foo(int a[static 0])
+{
+}
+
+int main(void)
+{
+ foo(0);
+}
+
+/* { dg-output "runtime error: null pointer passed as argument 1" } */