re PR c/20318 (RFE: add attribute to specify that a function never returns NULL)

2013-10-09  Marc Glisse  <marc.glisse@inria.fr>

	PR tree-optimization/20318
gcc/c-family/
	* c-common.c (handle_returns_nonnull_attribute): New function.
	(c_common_attribute_table): Add returns_nonnull.

gcc/
	* doc/extend.texi (returns_nonnull): New function attribute.
	* fold-const.c (tree_expr_nonzero_warnv_p): Look for returns_nonnull
	attribute.
	* tree-vrp.c (gimple_stmt_nonzero_warnv_p): Likewise.
	(stmt_interesting_for_vrp): Accept all GIMPLE_CALL.

gcc/testsuite/
	* c-c++-common/pr20318.c: New file.
	* gcc.dg/tree-ssa/pr20318.c: New file.

From-SVN: r203316
This commit is contained in:
Marc Glisse 2013-10-09 15:03:13 +02:00 committed by Marc Glisse
parent 378f8976f2
commit 826cacfe24
9 changed files with 89 additions and 6 deletions

View File

@ -1,3 +1,12 @@
2013-10-09 Marc Glisse <marc.glisse@inria.fr>
PR tree-optimization/20318
* doc/extend.texi (returns_nonnull): New function attribute.
* fold-const.c (tree_expr_nonzero_warnv_p): Look for returns_nonnull
attribute.
* tree-vrp.c (gimple_stmt_nonzero_warnv_p): Likewise.
(stmt_interesting_for_vrp): Accept all GIMPLE_CALL.
2013-10-09 Eric Botcazou <ebotcazou@adacore.com> 2013-10-09 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/58570 PR middle-end/58570

View File

@ -1,3 +1,9 @@
2013-10-09 Marc Glisse <marc.glisse@inria.fr>
PR tree-optimization/20318
* c-common.c (handle_returns_nonnull_attribute): New function.
(c_common_attribute_table): Add returns_nonnull.
2013-10-03 Marc Glisse <marc.glisse@inria.fr> 2013-10-03 Marc Glisse <marc.glisse@inria.fr>
PR c++/19476 PR c++/19476

View File

@ -371,6 +371,7 @@ static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *); static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, int, tree *); static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@ -747,6 +748,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_fnspec_attribute, false }, handle_fnspec_attribute, false },
{ "warn_unused", 0, 0, false, false, false, { "warn_unused", 0, 0, false, false, false,
handle_warn_unused_attribute, false }, handle_warn_unused_attribute, false },
{ "returns_nonnull", 0, 0, false, true, true,
handle_returns_nonnull_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false } { NULL, 0, 0, false, false, false, NULL, false }
}; };
@ -9048,6 +9051,23 @@ handle_no_split_stack_attribute (tree *node, tree name,
return NULL_TREE; return NULL_TREE;
} }
/* Handle a "returns_nonnull" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_returns_nonnull_attribute (tree *node, tree, tree, int,
bool *no_add_attrs)
{
// Even without a prototype we still have a return type we can check.
if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
{
error ("returns_nonnull attribute on a function not returning a pointer");
*no_add_attrs = true;
}
return NULL_TREE;
}
/* Check for valid arguments being passed to a function with FNTYPE. /* Check for valid arguments being passed to a function with FNTYPE.
There are NARGS arguments in the array ARGARRAY. */ There are NARGS arguments in the array ARGARRAY. */

View File

@ -2133,7 +2133,8 @@ attributes are currently defined for functions on all targets:
@code{section}, @code{constructor}, @code{section}, @code{constructor},
@code{destructor}, @code{used}, @code{unused}, @code{deprecated}, @code{destructor}, @code{used}, @code{unused}, @code{deprecated},
@code{weak}, @code{malloc}, @code{alias}, @code{ifunc}, @code{weak}, @code{malloc}, @code{alias}, @code{ifunc},
@code{warn_unused_result}, @code{nonnull}, @code{gnu_inline}, @code{warn_unused_result}, @code{nonnull},
@code{returns_nonnull}, @code{gnu_inline},
@code{externally_visible}, @code{hot}, @code{cold}, @code{artificial}, @code{externally_visible}, @code{hot}, @code{cold}, @code{artificial},
@code{no_sanitize_address}, @code{no_address_safety_analysis}, @code{no_sanitize_address}, @code{no_address_safety_analysis},
@code{no_sanitize_undefined}, @code{no_sanitize_undefined},
@ -3309,6 +3310,20 @@ my_memcpy (void *dest, const void *src, size_t len)
__attribute__((nonnull)); __attribute__((nonnull));
@end smallexample @end smallexample
@item returns_nonnull (@var{arg-index}, @dots{})
@cindex @code{returns_nonnull} function attribute
The @code{returns_nonnull} attribute specifies that the function
return value should be a non-null pointer. For instance, the declaration:
@smallexample
extern void *
mymalloc (size_t len) __attribute__((returns_nonnull));
@end smallexample
@noindent
lets the compiler optimize callers based on the knowledge
that the return value will never be null.
@item noreturn @item noreturn
@cindex @code{noreturn} function attribute @cindex @code{noreturn} function attribute
A few standard library functions, such as @code{abort} and @code{exit}, A few standard library functions, such as @code{abort} and @code{exit},

View File

@ -16229,6 +16229,10 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
&& DECL_IS_OPERATOR_NEW (fndecl) && DECL_IS_OPERATOR_NEW (fndecl)
&& !TREE_NOTHROW (fndecl)) && !TREE_NOTHROW (fndecl))
return true; return true;
if (flag_delete_null_pointer_checks
&& lookup_attribute ("returns_nonnull",
TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
return true;
return alloca_call_p (t); return alloca_call_p (t);
} }

View File

@ -1,3 +1,9 @@
2013-10-09 Marc Glisse <marc.glisse@inria.fr>
PR tree-optimization/20318
* c-c++-common/pr20318.c: New file.
* gcc.dg/tree-ssa/pr20318.c: New file.
2013-10-09 Eric Botcazou <ebotcazou@adacore.com> 2013-10-09 Eric Botcazou <ebotcazou@adacore.com>
* gcc.c-torture/execute/pr58570.c: New test. * gcc.c-torture/execute/pr58570.c: New test.

View File

@ -0,0 +1,3 @@
/* { dg-do compile } */
extern int f() __attribute__((returns_nonnull)); /* { dg-error "not returning a pointer" } */

View File

@ -0,0 +1,19 @@
/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
/* { dg-options "-O2 -fdump-tree-original -fdump-tree-vrp1" } */
extern int* f(int) __attribute__((returns_nonnull));
extern void eliminate ();
void g () {
if (f (2) == 0)
eliminate ();
}
void h () {
int *p = f (2);
if (p == 0)
eliminate ();
}
/* { dg-final { scan-tree-dump-times "== 0" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 1 "vrp1" } } */
/* { dg-final { cleanup-tree-dump "original" } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */

View File

@ -1038,7 +1038,7 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
} }
} }
/* Return true if STMT is know to to compute a non-zero value. /* Return true if STMT is known to compute a non-zero value.
If the return value is based on the assumption that signed overflow is If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P.*/ *STRICT_OVERFLOW_P.*/
@ -1058,6 +1058,10 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
&& DECL_IS_OPERATOR_NEW (fndecl) && DECL_IS_OPERATOR_NEW (fndecl)
&& !TREE_NOTHROW (fndecl)) && !TREE_NOTHROW (fndecl))
return true; return true;
if (flag_delete_null_pointer_checks &&
lookup_attribute ("returns_nonnull",
TYPE_ATTRIBUTES (gimple_call_fntype (stmt))))
return true;
return gimple_alloca_call_p (stmt); return gimple_alloca_call_p (stmt);
} }
default: default:
@ -6536,10 +6540,7 @@ stmt_interesting_for_vrp (gimple stmt)
if (lhs && TREE_CODE (lhs) == SSA_NAME if (lhs && TREE_CODE (lhs) == SSA_NAME
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| POINTER_TYPE_P (TREE_TYPE (lhs))) || POINTER_TYPE_P (TREE_TYPE (lhs)))
&& ((is_gimple_call (stmt) && (is_gimple_call (stmt)
&& gimple_call_fndecl (stmt) != NULL_TREE
&& (DECL_BUILT_IN (gimple_call_fndecl (stmt))
|| DECL_IS_OPERATOR_NEW (gimple_call_fndecl (stmt))))
|| !gimple_vuse (stmt))) || !gimple_vuse (stmt)))
return true; return true;
} }