summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
authorglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-09 13:03:13 +0000
committerglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-09 13:03:13 +0000
commitd7dcba40a5768c70c40d1b7109377c78010abea4 (patch)
treeca712605143da33b695da4c91076aa641b7f23d3 /gcc
parent11ad02c667d0c697c971e810fb30504de359371f (diff)
downloadppe42-gcc-d7dcba40a5768c70c40d1b7109377c78010abea4.tar.gz
ppe42-gcc-d7dcba40a5768c70c40d1b7109377c78010abea4.zip
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@203316 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-common.c20
-rw-r--r--gcc/doc/extend.texi17
-rw-r--r--gcc/fold-const.c4
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/c-c++-common/pr20318.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr20318.c19
-rw-r--r--gcc/tree-vrp.c11
9 files changed, 89 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f78642ae0ad..95c490bcd36 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index d468344c735..d94921b456d 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8ecb70cfa7c..5fe7cab0f8b 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 782c55e2fa6..9b641b2d0af 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 03d62f51721..c4c09b65eb1 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 4de71eb0f71..9143a956364 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/c-c++-common/pr20318.c b/gcc/testsuite/c-c++-common/pr20318.c
new file mode 100644
index 00000000000..c6e9639fc4e
--- /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 00000000000..1b302aedefa
--- /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 156a58ff5ca..4cd2f2a5123 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;
}
OpenPOWER on IntegriCloud