From: glisse Date: Wed, 9 Oct 2013 13:03:13 +0000 (+0000) Subject: 2013-10-09 Marc Glisse X-Git-Tag: upstream/4.9.2~3846 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d7dcba40a5768c70c40d1b7109377c78010abea4;p=platform%2Fupstream%2Flinaro-gcc.git 2013-10-09 Marc Glisse 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@203316 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f78642a..95c490b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-10-09 Marc Glisse + + 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 PR middle-end/58570 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d468344..d94921b 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2013-10-09 Marc Glisse + + 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 PR c++/19476 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 8ecb70c..5fe7cab 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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_fnspec_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_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -747,6 +748,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_fnspec_attribute, false }, { "warn_unused", 0, 0, false, false, 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 } }; @@ -9048,6 +9051,23 @@ handle_no_split_stack_attribute (tree *node, tree name, 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. There are NARGS arguments in the array ARGARRAY. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 782c55e..9b641b2 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2133,7 +2133,8 @@ attributes are currently defined for functions on all targets: @code{section}, @code{constructor}, @code{destructor}, @code{used}, @code{unused}, @code{deprecated}, @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{no_sanitize_address}, @code{no_address_safety_analysis}, @code{no_sanitize_undefined}, @@ -3309,6 +3310,20 @@ my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull)); @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 @cindex @code{noreturn} function attribute A few standard library functions, such as @code{abort} and @code{exit}, diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 03d62f5..c4c09b6 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -16229,6 +16229,10 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p) && DECL_IS_OPERATOR_NEW (fndecl) && !TREE_NOTHROW (fndecl)) return true; + if (flag_delete_null_pointer_checks + && lookup_attribute ("returns_nonnull", + TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + return true; return alloca_call_p (t); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4de71eb..9143a95 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-10-09 Marc Glisse + + PR tree-optimization/20318 + * c-c++-common/pr20318.c: New file. + * gcc.dg/tree-ssa/pr20318.c: New file. + 2013-10-09 Eric Botcazou * gcc.c-torture/execute/pr58570.c: New test. diff --git a/gcc/testsuite/c-c++-common/pr20318.c b/gcc/testsuite/c-c++-common/pr20318.c new file mode 100644 index 0000000..c6e9639 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr20318.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ + +extern int f() __attribute__((returns_nonnull)); /* { dg-error "not returning a pointer" } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20318.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20318.c new file mode 100644 index 0000000..1b302ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20318.c @@ -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" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 156a58f..4cd2f2a 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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 undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change *STRICT_OVERFLOW_P.*/ @@ -1058,6 +1058,10 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p) && DECL_IS_OPERATOR_NEW (fndecl) && !TREE_NOTHROW (fndecl)) 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); } default: @@ -6536,10 +6540,7 @@ stmt_interesting_for_vrp (gimple stmt) if (lhs && TREE_CODE (lhs) == SSA_NAME && (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) || POINTER_TYPE_P (TREE_TYPE (lhs))) - && ((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)))) + && (is_gimple_call (stmt) || !gimple_vuse (stmt))) return true; }