All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Malcolm <dmalcolm@redhat.com>
To: gcc-patches@gcc.gnu.org, linux-toolchains@vger.kernel.org
Cc: David Malcolm <dmalcolm@redhat.com>
Subject: [PATCH 2/6] Add returns_zero_on_success/failure attributes
Date: Sat, 13 Nov 2021 15:37:27 -0500	[thread overview]
Message-ID: <20211113203732.2098220-4-dmalcolm@redhat.com> (raw)
In-Reply-To: <20211113203732.2098220-1-dmalcolm@redhat.com>

This patch adds two new attributes.  The followup patch makes use of
the attributes in -fanalyzer.

gcc/c-family/ChangeLog:
	* c-attribs.c (attr_noreturn_exclusions): Add
	"returns_zero_on_failure" and "returns_zero_on_success".
	(attr_returns_twice_exclusions): Likewise.
	(attr_returns_zero_on_exclusions): New.
	(c_common_attribute_table): Add "returns_zero_on_failure" and
	"returns_zero_on_success".
	(handle_returns_zero_on_attributes): New.

gcc/ChangeLog:
	* doc/extend.texi (Common Function Attributes): Document
	"returns_zero_on_failure" and "returns_zero_on_success".

gcc/testsuite/ChangeLog:
	* c-c++-common/attr-returns-zero-on-1.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/c-family/c-attribs.c                      | 37 ++++++++++
 gcc/doc/extend.texi                           | 16 +++++
 .../c-c++-common/attr-returns-zero-on-1.c     | 68 +++++++++++++++++++
 3 files changed, 121 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/attr-returns-zero-on-1.c

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 100c2dabab2..9e03156de5e 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -153,6 +153,7 @@ static tree handle_argspec_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 tree handle_returns_zero_on_attributes (tree *, tree, tree, int, bool *);
 static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
 					       bool *);
 static tree handle_omp_declare_variant_attribute (tree *, tree, tree, int,
@@ -221,6 +222,8 @@ extern const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
   ATTR_EXCL ("pure", true, true, true),
   ATTR_EXCL ("returns_twice", true, true, true),
   ATTR_EXCL ("warn_unused_result", true, true, true),
+  ATTR_EXCL ("returns_zero_on_failure", true, true, true),
+  ATTR_EXCL ("returns_zero_on_success", true, true, true),
   ATTR_EXCL (NULL, false, false, false),
 };
 
@@ -235,6 +238,8 @@ attr_warn_unused_result_exclusions[] =
 static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
 {
   ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL ("returns_zero_on_failure", true, true, true),
+  ATTR_EXCL ("returns_zero_on_success", true, true, true),
   ATTR_EXCL (NULL, false, false, false),
 };
 
@@ -275,6 +280,16 @@ static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
   ATTR_EXCL (NULL, false, false, false),
 };
 
+/* Exclusions that apply to the returns_zero_on_* attributes.  */
+static const struct attribute_spec::exclusions
+  attr_returns_zero_on_exclusions[] =
+{
+  ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL ("returns_twice", true, true, true),
+  ATTR_EXCL ("returns_zero_on_failure", true, true, true),
+  ATTR_EXCL ("returns_zero_on_success", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
 
 /* Table of machine-independent attributes common to all C-like languages.
 
@@ -493,6 +508,12 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_warn_unused_attribute, NULL },
   { "returns_nonnull",        0, 0, false, true, true, false,
 			      handle_returns_nonnull_attribute, NULL },
+  { "returns_zero_on_failure",0, 0, false, true, true, false,
+			      handle_returns_zero_on_attributes,
+			      attr_returns_zero_on_exclusions },
+  { "returns_zero_on_success",0, 0, false, true, true, false,
+			      handle_returns_zero_on_attributes,
+			      attr_returns_zero_on_exclusions },
   { "omp declare simd",       0, -1, true,  false, false, false,
 			      handle_omp_declare_simd_attribute, NULL },
   { "omp declare variant base", 0, -1, true,  false, false, false,
@@ -5660,6 +5681,22 @@ handle_returns_nonnull_attribute (tree *node, tree name, tree, int,
   return NULL_TREE;
 }
 
+/* Handle "returns_zero_on_failure" and "returns_zero_on_success" attributes;
+   arguments as in struct attribute_spec.handler.  */
+
+static tree
+handle_returns_zero_on_attributes (tree *node, tree name, tree, int,
+				   bool *no_add_attrs)
+{
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (*node)))
+    {
+      error ("%qE attribute on a function not returning an integral type",
+	     name);
+      *no_add_attrs = true;
+    }
+  return NULL_TREE;
+}
+
 /* Handle a "designated_init" attribute; arguments as in
    struct attribute_spec.handler.  */
 
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e9f47519df2..5a6ef464779 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3784,6 +3784,22 @@ function.  Examples of such functions are @code{setjmp} and @code{vfork}.
 The @code{longjmp}-like counterpart of such function, if any, might need
 to be marked with the @code{noreturn} attribute.
 
+@item returns_zero_on_failure
+@cindex @code{returns_zero_on_failure} function attribute
+The @code{returns_zero_on_failure} attribute hints that the function
+can succeed or fail, returning non-zero on success and zero on failure.
+This is used by the @option{-fanalyzer} option to consider both outcomes
+separately, which may improve how it explores error-handling paths, and
+how such outcomes are labelled in diagnostics.  It is also a hint
+to the human reader of the source code.
+
+@item returns_zero_on_success
+@cindex @code{returns_zero_on_success} function attribute
+The @code{returns_zero_on_success} attribute is identical to the
+@code{returns_zero_on_failure} attribute, apart from having the
+opposite interpretation of the return value: zero on success, non-zero
+on failure.
+
 @item section ("@var{section-name}")
 @cindex @code{section} function attribute
 @cindex functions in arbitrary sections
diff --git a/gcc/testsuite/c-c++-common/attr-returns-zero-on-1.c b/gcc/testsuite/c-c++-common/attr-returns-zero-on-1.c
new file mode 100644
index 00000000000..5475dfe61db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-returns-zero-on-1.c
@@ -0,0 +1,68 @@
+/* Verify the parsing of the "returns_zero_on_{sucess|failure}" attributes.  */
+
+/* Correct usage.  */
+
+extern int test_int_return_s ()
+  __attribute__((returns_zero_on_success));
+extern long test_long_return_f ()
+  __attribute__((returns_zero_on_failure));
+
+/* Should complain if not a function.  */
+
+extern int not_a_function_s
+  __attribute__((returns_zero_on_success)); /* { dg-warning "'returns_zero_on_success' attribute only applies to function types" } */
+extern int not_a_function_f
+  __attribute__((returns_zero_on_failure)); /* { dg-warning "'returns_zero_on_failure' attribute only applies to function types" } */
+
+/* Should complain if return type is not integral.  */
+
+extern void test_void_return_s ()
+  __attribute__((returns_zero_on_success)); /* { dg-error "'returns_zero_on_success' attribute on a function not returning an integral type" } */
+extern void test_void_return_f ()
+  __attribute__((returns_zero_on_failure)); /* { dg-error "'returns_zero_on_failure' attribute on a function not returning an integral type" } */
+
+extern void *test_void_star_return_s ()
+  __attribute__((returns_zero_on_success)); /* { dg-error "'returns_zero_on_success' attribute on a function not returning an integral type" } */
+extern void *test_void_star_return_f ()
+  __attribute__((returns_zero_on_failure)); /* { dg-error "'returns_zero_on_failure' attribute on a function not returning an integral type" } */
+
+/* (and this prevents mixing with returns_non_null, which requires a pointer).  */
+
+/* Should complain if more than one returns_* attribute.  */
+
+extern int test_void_returns_s_f ()
+  __attribute__((returns_zero_on_success))
+  __attribute__((returns_zero_on_failure)); /* { dg-warning "ignoring attribute 'returns_zero_on_failure' because it conflicts with attribute 'returns_zero_on_success'" } */
+extern int test_void_returns_f_s ()
+  __attribute__((returns_zero_on_failure))
+  __attribute__((returns_zero_on_success)); /* { dg-warning "ignoring attribute 'returns_zero_on_success' because it conflicts with attribute 'returns_zero_on_failure'" } */
+
+/* Should complain if mixed with "noreturn".  */
+
+extern int test_noreturn_returns_s ()
+  __attribute__((noreturn))
+  __attribute__((returns_zero_on_success)); /* { dg-warning "ignoring attribute 'returns_zero_on_success' because it conflicts with attribute 'noreturn'" } */
+extern int test_returns_s_noreturn ()
+  __attribute__((returns_zero_on_success))
+  __attribute__((noreturn)); /* { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'returns_zero_on_success'" } */
+extern int test_noreturn_returns_f ()
+  __attribute__((noreturn))
+  __attribute__((returns_zero_on_failure)); /* { dg-warning "ignoring attribute 'returns_zero_on_failure' because it conflicts with attribute 'noreturn'" } */
+extern int test_returns_f_noreturn ()
+  __attribute__((returns_zero_on_failure))
+  __attribute__((noreturn)); /* { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'returns_zero_on_failure'" } */
+
+/* Should complain if mixed with "returns_twice".  */
+
+extern int test_returns_twice_returns_s ()
+  __attribute__((returns_twice))
+  __attribute__((returns_zero_on_success)); /* { dg-warning "ignoring attribute 'returns_zero_on_success' because it conflicts with attribute 'returns_twice'" } */
+extern int test_returns_s_returns_twice ()
+  __attribute__((returns_zero_on_success))
+  __attribute__((returns_twice)); /* { dg-warning "ignoring attribute 'returns_twice' because it conflicts with attribute 'returns_zero_on_success'" } */
+extern int test_returns_twice_returns_f ()
+  __attribute__((returns_twice))
+  __attribute__((returns_zero_on_failure)); /* { dg-warning "ignoring attribute 'returns_zero_on_failure' because it conflicts with attribute 'returns_twice'" } */
+extern int test_returns_f_returns_twice ()
+  __attribute__((returns_zero_on_failure))
+  __attribute__((returns_twice)); /* { dg-warning "ignoring attribute 'returns_twice' because it conflicts with attribute 'returns_zero_on_failure'" } */
-- 
2.26.3


  parent reply	other threads:[~2021-11-13 20:37 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-13 20:37 [PATCH 0/6] RFC: adding support to GCC for detecting trust boundaries David Malcolm
2021-11-13 20:37 ` [PATCH 1a/6] RFC: Implement "#pragma GCC custom_address_space" David Malcolm
2021-11-13 20:37 ` [PATCH 1b/6] Add __attribute__((untrusted)) David Malcolm
2021-12-09 22:54   ` Martin Sebor
2022-01-06 15:10     ` David Malcolm
2022-01-06 18:59       ` Martin Sebor
2021-11-13 20:37 ` David Malcolm [this message]
2021-11-15  7:03   ` [PATCH 2/6] Add returns_zero_on_success/failure attributes Prathamesh Kulkarni
2021-11-15 14:45     ` Peter Zijlstra
2021-11-15 22:30       ` David Malcolm
2021-11-15 22:12     ` David Malcolm
2021-11-17  9:23       ` Prathamesh Kulkarni
2021-11-17 22:43         ` Joseph Myers
2021-11-18 20:08           ` Segher Boessenkool
2021-11-18 23:45             ` David Malcolm
2021-11-19 21:52               ` Segher Boessenkool
2021-11-18 23:34           ` David Malcolm
2021-12-06 18:34             ` Martin Sebor
2021-11-18 23:15         ` David Malcolm
2021-11-13 20:37 ` [PATCH 4a/6] analyzer: implement region::untrusted_p in terms of custom address spaces David Malcolm
2021-11-13 20:37 ` [PATCH 4b/6] analyzer: implement region::untrusted_p in terms of __attribute__((untrusted)) David Malcolm
2021-11-13 20:37 ` [PATCH 5/6] analyzer: use region::untrusted_p in taint detection David Malcolm
2021-11-13 20:37 ` [PATCH 6/6] Add __attribute__ ((tainted)) David Malcolm
2022-01-06 14:08   ` PING (C/C++): " David Malcolm
2022-01-10 21:36     ` PING^2 " David Malcolm
2022-01-12  4:36       ` Jason Merrill
2022-01-12 15:33         ` David Malcolm
2022-01-13 19:08           ` Jason Merrill
2022-01-14  1:25             ` [committed] Add __attribute__ ((tainted_args)) David Malcolm
2021-11-13 23:20 ` [PATCH 0/6] RFC: adding support to GCC for detecting trust boundaries Peter Zijlstra
2021-11-14  2:54   ` David Malcolm
2021-11-14 13:54 ` Miguel Ojeda
2021-12-06 18:12 ` Martin Sebor
2021-12-06 19:40   ` Segher Boessenkool
2021-12-09  0:06     ` David Malcolm
2021-12-09  0:41       ` Segher Boessenkool
2021-12-09 16:42     ` Martin Sebor
2021-12-09 23:40       ` Segher Boessenkool
2021-12-08 23:11   ` David Malcolm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211113203732.2098220-4-dmalcolm@redhat.com \
    --to=dmalcolm@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=linux-toolchains@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.