PoC: add -Wunused-result=strict

Message ID 6444e3c7.16516@msgid.achurch.org
State Unresolved
Headers
Series PoC: add -Wunused-result=strict |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Andrew Church April 23, 2023, 7:52 a.m. UTC
  As requested in <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c41>,
this is a proof-of-concept patch to change -Wunused-result to not warn
about return values explicitly discarded by casting to void, and add
-Wunused-result=strict for the current behavior (warn even on void casts).
The core behavior change is based on an earlier patch at
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509#c10>; it appears to
do the correct thing based on the tests added by the patch, but it also
breaks a number of other attribute- and analyzer-related tests, so some
fine-tuning is probably needed (and I don't have the GCC internals
knowledge to know where to start).

I haven't touched [[nodiscard]] behavior, since GCC already ignores
explicit discards in that case; for consistency's sake, it might make
sense to also warn for explicitly discarded [[nodiscard]] values with
-Wunused-result=strict.

Please CC me on any replies, as I am not subscribed to the list.

  --Andrew Church
    https://achurch.org/
  

Patch

diff -urN gcc-12.2.0-orig/gcc/c-family/c.opt gcc-12.2.0/gcc/c-family/c.opt
--- gcc-12.2.0-orig/gcc/c-family/c.opt	2022-08-19 17:09:52 +0900
+++ gcc-12.2.0/gcc/c-family/c.opt	2023-04-23 03:39:58 +0900
@@ -1361,6 +1361,10 @@ 
 C ObjC C++ ObjC++ Var(warn_unused_result) Init(1) Warning
 Warn if a caller of a function, marked with attribute warn_unused_result, does not use its return value.
 
+Wunused-result=strict
+C ObjC C++ ObjC++ RejectNegative Var(warn_unused_result,2) Init(1) Warning
+Warn if a caller of a function, marked with attribute warn_unused_result, does not use its return value.
+
 Wunused-variable
 C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wunused)
 ; documented in common.opt
diff -urN gcc-12.2.0-orig/gcc/doc/invoke.texi gcc-12.2.0/gcc/doc/invoke.texi
--- gcc-12.2.0-orig/gcc/doc/invoke.texi	2022-08-19 17:09:52 +0900
+++ gcc-12.2.0/gcc/doc/invoke.texi	2023-04-23 03:32:36 +0900
@@ -406,7 +406,7 @@ 
 -Wunused-const-variable  -Wunused-const-variable=@var{n} @gol
 -Wunused-function  -Wunused-label  -Wunused-local-typedefs @gol
 -Wunused-macros @gol
--Wunused-parameter  -Wno-unused-result @gol
+-Wunused-parameter  -Wunused-result  -Wunused-result=strict @gol
 -Wunused-value  -Wunused-variable @gol
 -Wno-varargs  -Wvariadic-macros @gol
 -Wvector-operation-performance @gol
@@ -7037,12 +7037,20 @@ 
 To suppress this warning use the @code{unused} attribute
 (@pxref{Variable Attributes}).
 
-@item -Wno-unused-result
+@item -Wunused-result
 @opindex Wunused-result
 @opindex Wno-unused-result
-Do not warn if a caller of a function marked with attribute
+Warn if a caller of a function marked with attribute
 @code{warn_unused_result} (@pxref{Function Attributes}) does not use
-its return value. The default is @option{-Wunused-result}.
+its return value, unless the return value is explicitly discarded with a
+cast to @code{void}. This warning is enabled by default.
+
+@item -Wunused-result=strict
+@opindex Wunused-result=strict
+Warn if a caller of a function marked with attribute
+@code{warn_unused_result} (@pxref{Function Attributes}) does not use
+its return value, even if the return value is explicitly discarded with
+a cast to @code{void}.
 
 @item -Wunused-variable
 @opindex Wunused-variable
diff -urN gcc-12.2.0-orig/gcc/gimplify.cc gcc-12.2.0/gcc/gimplify.cc
--- gcc-12.2.0-orig/gcc/gimplify.cc	2022-08-19 17:09:52 +0900
+++ gcc-12.2.0/gcc/gimplify.cc	2023-04-23 03:34:02 +0900
@@ -15183,10 +15183,18 @@ 
 	      || fallback == fb_none)
 	    {
 	      /* Just strip a conversion to void (or in void context) and
-		 try again.  */
-	      *expr_p = TREE_OPERAND (*expr_p, 0);
-	      ret = GS_OK;
-	      break;
+	         try again.  But if this is a function call cast to void
+	         and strict unused-result warnings are not enabled,
+	         preserve the cast so that do_warn_unused_result() knows
+	         not to emit a warning.  */
+	      if (!(warn_unused_result == 1
+	            && TREE_CODE (TREE_OPERAND (*expr_p, 0)) == CALL_EXPR
+	            && VOID_TYPE_P (TREE_TYPE (*expr_p))))
+	        {
+	            *expr_p = TREE_OPERAND (*expr_p, 0);
+	            ret = GS_OK;
+	            break;
+	        }
 	    }
 
 	  ret = gimplify_conversion (expr_p);
diff -urN gcc-12.2.0-orig/gcc/testsuite/c-c++-common/attr-warn-unused-result.c gcc-12.2.0/gcc/testsuite/c-c++-common/attr-warn-unused-result.c
--- gcc-12.2.0-orig/gcc/testsuite/c-c++-common/attr-warn-unused-result.c	2022-08-19 17:09:53 +0900
+++ gcc-12.2.0/gcc/testsuite/c-c++-common/attr-warn-unused-result.c	2023-04-22 20:01:42 +0900
@@ -1,6 +1,6 @@ 
 /* warn_unused_result attribute tests.  */
 /* { dg-do compile } */
-/* { dg-options "-O -ftrack-macro-expansion=0" } */
+/* { dg-options "-O -ftrack-macro-expansion=0 -Wunused-result=strict" } */
 
 #define WUR __attribute__((warn_unused_result))
 #define WURAI __attribute__((warn_unused_result, always_inline)) inline
diff -urN gcc-12.2.0-orig/gcc/testsuite/gcc.dg/Wunused-result-2.c gcc-12.2.0/gcc/testsuite/gcc.dg/Wunused-result-2.c
--- gcc-12.2.0-orig/gcc/testsuite/gcc.dg/Wunused-result-2.c	1970-01-01 09:00:00 +0900
+++ gcc-12.2.0/gcc/testsuite/gcc.dg/Wunused-result-2.c	2023-04-23 04:17:01 +0900
@@ -0,0 +1,11 @@ 
+/* Test for -Wno-unused-result inhibiting all unused-result warnings.
+   { dg-do compile }
+   { dg-options "-Wno-unused-result" } */
+
+__attribute__ ((warn_unused_result)) int fwur (void);
+
+void wur (void)
+{
+  fwur ();          // no warning
+  (void) fwur ();   // no warning
+}
diff -urN gcc-12.2.0-orig/gcc/testsuite/gcc.dg/Wunused-result-3.c gcc-12.2.0/gcc/testsuite/gcc.dg/Wunused-result-3.c
--- gcc-12.2.0-orig/gcc/testsuite/gcc.dg/Wunused-result-3.c	1970-01-01 09:00:00 +0900
+++ gcc-12.2.0/gcc/testsuite/gcc.dg/Wunused-result-3.c	2023-04-23 03:29:19 +0900
@@ -0,0 +1,12 @@ 
+/* Test for -Wunused-result inhibiting unused-result warnings when the
+   value is explicitly cast to void.
+   { dg-do compile }
+   { dg-options "-Wunused-result" } */
+
+__attribute__ ((warn_unused_result)) int fwur (void);
+
+void wur (void)
+{
+  fwur ();          // { dg-warning "\\\[-Wunused-result" }
+  (void) fwur ();   // no warning
+}
diff -urN gcc-12.2.0-orig/gcc/testsuite/gcc.dg/Wunused-result-4.c gcc-12.2.0/gcc/testsuite/gcc.dg/Wunused-result-4.c
--- gcc-12.2.0-orig/gcc/testsuite/gcc.dg/Wunused-result-4.c	1970-01-01 09:00:00 +0900
+++ gcc-12.2.0/gcc/testsuite/gcc.dg/Wunused-result-4.c	2023-04-23 03:29:35 +0900
@@ -0,0 +1,12 @@ 
+/* Test for -Wunused-result=strict emitting unused-result warnings even
+   when the value is explicitly cast to void.
+   { dg-do compile }
+   { dg-options "-Wunused-result=strict" } */
+
+__attribute__ ((warn_unused_result)) int fwur (void);
+
+void wur (void)
+{
+  fwur ();          // { dg-warning "\\\[-Wunused-result" }
+  (void) fwur ();   // { dg-warning "\\\[-Wunused-result" }
+}