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:
parent
378f8976f2
commit
826cacfe24
@ -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>
|
||||
|
||||
PR middle-end/58570
|
||||
|
@ -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>
|
||||
|
||||
PR c++/19476
|
||||
|
@ -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. */
|
||||
|
@ -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},
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
||||
* gcc.c-torture/execute/pr58570.c: New test.
|
||||
|
3
gcc/testsuite/c-c++-common/pr20318.c
Normal file
3
gcc/testsuite/c-c++-common/pr20318.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
extern int f() __attribute__((returns_nonnull)); /* { dg-error "not returning a pointer" } */
|
19
gcc/testsuite/gcc.dg/tree-ssa/pr20318.c
Normal file
19
gcc/testsuite/gcc.dg/tree-ssa/pr20318.c
Normal 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" } } */
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user