[PATCH] c, c++: Fix unused result for empty types [PR82134]

2025-06-09 Thread Jeremy Rifkin
Hi,
This fixes PR c/82134 which concerns gcc emitting an incorrect unused
result diagnostic for empty types. This diagnostic is emitted from
tree-cfg.cc because of a couple code paths which attempt to avoid
copying empty types, resulting in GIMPLE that isn't using the returned
value of a call. To fix this I've added suppress_warning in three locations
and a corresponding check in do_warn_unused_result.

Cheers,
Jeremy


PR c/82134

gcc/cp/ChangeLog:

* call.cc (build_call_a): Add suppress_warning
* cp-gimplify.cc (cp_gimplify_expr): Add suppress_warning

gcc/ChangeLog:

* gimplify.cc (gimplify_modify_expr): Add suppress_warning
* tree-cfg.cc (do_warn_unused_result): Check warning_suppressed_p

gcc/testsuite/ChangeLog:

* c-c++-common/attr-warn-unused-result-2.c: New test.

Signed-off-by: Jeremy Rifkin 
---
 gcc/cp/call.cc|  1 +
 gcc/cp/cp-gimplify.cc |  1 +
 gcc/gimplify.cc   |  1 +
 .../c-c++-common/attr-warn-unused-result-2.c  | 15 +++
 gcc/tree-cfg.cc   |  2 ++
 5 files changed, 20 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 2c3ef3dfc35..a70fc13c6a4 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -412,6 +412,7 @@ build_call_a (tree function, int n, tree *argarray)
   /* We're disconnecting the initializer from its target,
  don't create a temporary.  */
   arg = TARGET_EXPR_INITIAL (arg);
+suppress_warning (arg, OPT_Wunused_result);
 tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
 arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
 CALL_EXPR_ARG (function, i) = arg;
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 0fcfa16d2c5..2a21e960994 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -690,6 +690,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
gimple_seq *post_p)
 && (REFERENCE_CLASS_P (op1) || DECL_P (op1)))
   op1 = build_fold_addr_expr (op1);
 
+suppress_warning (op1, OPT_Wunused_result);
 gimplify_and_add (op1, pre_p);
   }
 gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 9f9ff92d064..fa9890e7cea 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -7305,6 +7305,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq
*pre_p, gimple_seq *post_p,
   && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
&& TREE_CODE (*from_p) == CALL_EXPR))
 {
+  suppress_warning (*from_p, OPT_Wunused_result);
   gimplify_stmt (from_p, pre_p);
   gimplify_stmt (to_p, pre_p);
   *expr_p = NULL_TREE;
diff --git a/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c 
b/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
new file mode 100644
index 000..09be1a933c9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
@@ -0,0 +1,15 @@
+// PR c/82134
+/* { dg-do compile } */
+
+struct S {};
+
+__attribute__((warn_unused_result)) struct S foo();
+
+void use_s(struct S);
+
+void
+test (void)
+{
+  struct S s = foo(); /* { dg-bogus "ignoring return value of" } */
+  use_s(foo()); /* { dg-bogus "ignoring return value of" } */
+}
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index fad308e7f7b..5cd72ed1b3e 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -9961,6 +9961,8 @@ do_warn_unused_result (gimple_seq seq)
 break;
   if (gimple_call_internal_p (g))
 break;
+  if (warning_suppressed_p (g, OPT_Wunused_result))
+break;
 
   /* This is a naked call, as opposed to a GIMPLE_CALL with an
  LHS.  All calls whose value is ignored should be
-- 
2.43.0



Re: [PATCH] c, c++: Fix unused result for empty types [PR82134]

2025-07-14 Thread Jeremy Rifkin
Hi Jason,
Thank you so much for taking a look!

> This is OK, but I wonder about making do_warn_unused_result ignore empty
> types in general; if there's no data in the type, what does it matter if
> we ignore the empty box?

I'm not strongly opinionated and I think there are good arguments both
ways. Looking at other implementations, I see clang and msvc both warn
on warn_unused_result/nodiscard for empty types. I think the primary
time this would really matter is generic programming, if I'm working
with `template [[nodiscard]] T foo();` I would probably want a
warning if I discarded the result, even if it's being instantiated
with T = empty type.

Cheers,
Jeremy

On Tue, Jul 8, 2025 at 11:23 AM Jason Merrill  wrote:
>
> On 6/9/25 9:00 PM, Jeremy Rifkin wrote:
> > Hi,
> > This fixes PR c/82134 which concerns gcc emitting an incorrect unused
> > result diagnostic for empty types. This diagnostic is emitted from
> > tree-cfg.cc because of a couple code paths which attempt to avoid
> > copying empty types, resulting in GIMPLE that isn't using the returned
> > value of a call. To fix this I've added suppress_warning in three locations
> > and a corresponding check in do_warn_unused_result.
>
> This is OK, but I wonder about making do_warn_unused_result ignore empty
> types in general; if there's no data in the type, what does it matter if
> we ignore the empty box?
>
> > Cheers,
> > Jeremy
> >
> >
> >  PR c/82134
> >
> > gcc/cp/ChangeLog:
> >
> >  * call.cc (build_call_a): Add suppress_warning
> >  * cp-gimplify.cc (cp_gimplify_expr): Add suppress_warning
> >
> > gcc/ChangeLog:
> >
> >  * gimplify.cc (gimplify_modify_expr): Add suppress_warning
> >  * tree-cfg.cc (do_warn_unused_result): Check warning_suppressed_p
> >
> > gcc/testsuite/ChangeLog:
> >
> >  * c-c++-common/attr-warn-unused-result-2.c: New test.
> >
> > Signed-off-by: Jeremy Rifkin 
> > ---
> >   gcc/cp/call.cc|  1 +
> >   gcc/cp/cp-gimplify.cc |  1 +
> >   gcc/gimplify.cc   |  1 +
> >   .../c-c++-common/attr-warn-unused-result-2.c  | 15 +++
> >   gcc/tree-cfg.cc   |  2 ++
> >   5 files changed, 20 insertions(+)
> >   create mode 100644 gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
> >
> > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > index 2c3ef3dfc35..a70fc13c6a4 100644
> > --- a/gcc/cp/call.cc
> > +++ b/gcc/cp/call.cc
> > @@ -412,6 +412,7 @@ build_call_a (tree function, int n, tree *argarray)
> > /* We're disconnecting the initializer from its target,
> >don't create a temporary.  */
> > arg = TARGET_EXPR_INITIAL (arg);
> > +suppress_warning (arg, OPT_Wunused_result);
> >   tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
> >   arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
> >   CALL_EXPR_ARG (function, i) = arg;
> > diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
> > index 0fcfa16d2c5..2a21e960994 100644
> > --- a/gcc/cp/cp-gimplify.cc
> > +++ b/gcc/cp/cp-gimplify.cc
> > @@ -690,6 +690,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
> > gimple_seq *post_p)
> >   && (REFERENCE_CLASS_P (op1) || DECL_P (op1)))
> > op1 = build_fold_addr_expr (op1);
> >
> > +suppress_warning (op1, OPT_Wunused_result);
> >   gimplify_and_add (op1, pre_p);
> > }
> >   gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
> > diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
> > index 9f9ff92d064..fa9890e7cea 100644
> > --- a/gcc/gimplify.cc
> > +++ b/gcc/gimplify.cc
> > @@ -7305,6 +7305,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq
> > *pre_p, gimple_seq *post_p,
> > && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
> >  && TREE_CODE (*from_p) == CALL_EXPR))
> >   {
> > +  suppress_warning (*from_p, OPT_Wunused_result);
> > gimplify_stmt (from_p, pre_p);
> > gimplify_stmt (to_p, pre_p);
> > *expr_p = NULL_TREE;
> > diff --git a/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c 
> > b/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
> > new file mode 100644
> > index 000..09be1a933c9
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
> > @@ -0,

Re: [PATCH] c, c++: Fix unused result for empty types [PR82134]

2025-06-26 Thread Jeremy Rifkin
Hi,
I'm bumping this patch.

Jeremy

On Mon, Jun 9, 2025 at 8:00 PM Jeremy Rifkin  wrote:
>
> Hi,
> This fixes PR c/82134 which concerns gcc emitting an incorrect unused
> result diagnostic for empty types. This diagnostic is emitted from
> tree-cfg.cc because of a couple code paths which attempt to avoid
> copying empty types, resulting in GIMPLE that isn't using the returned
> value of a call. To fix this I've added suppress_warning in three locations
> and a corresponding check in do_warn_unused_result.
>
> Cheers,
> Jeremy
>
>
> PR c/82134
>
> gcc/cp/ChangeLog:
>
> * call.cc (build_call_a): Add suppress_warning
> * cp-gimplify.cc (cp_gimplify_expr): Add suppress_warning
>
> gcc/ChangeLog:
>
> * gimplify.cc (gimplify_modify_expr): Add suppress_warning
> * tree-cfg.cc (do_warn_unused_result): Check warning_suppressed_p
>
> gcc/testsuite/ChangeLog:
>
> * c-c++-common/attr-warn-unused-result-2.c: New test.
>
> Signed-off-by: Jeremy Rifkin 
> ---
>  gcc/cp/call.cc|  1 +
>  gcc/cp/cp-gimplify.cc |  1 +
>  gcc/gimplify.cc   |  1 +
>  .../c-c++-common/attr-warn-unused-result-2.c  | 15 +++
>  gcc/tree-cfg.cc   |  2 ++
>  5 files changed, 20 insertions(+)
>  create mode 100644 gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
>
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 2c3ef3dfc35..a70fc13c6a4 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -412,6 +412,7 @@ build_call_a (tree function, int n, tree *argarray)
>/* We're disconnecting the initializer from its target,
>   don't create a temporary.  */
>arg = TARGET_EXPR_INITIAL (arg);
> +suppress_warning (arg, OPT_Wunused_result);
>  tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
>  arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
>  CALL_EXPR_ARG (function, i) = arg;
> diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
> index 0fcfa16d2c5..2a21e960994 100644
> --- a/gcc/cp/cp-gimplify.cc
> +++ b/gcc/cp/cp-gimplify.cc
> @@ -690,6 +690,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
> gimple_seq *post_p)
>  && (REFERENCE_CLASS_P (op1) || DECL_P (op1)))
>op1 = build_fold_addr_expr (op1);
>
> +suppress_warning (op1, OPT_Wunused_result);
>  gimplify_and_add (op1, pre_p);
>}
>  gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
> diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
> index 9f9ff92d064..fa9890e7cea 100644
> --- a/gcc/gimplify.cc
> +++ b/gcc/gimplify.cc
> @@ -7305,6 +7305,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq
> *pre_p, gimple_seq *post_p,
>&& !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
> && TREE_CODE (*from_p) == CALL_EXPR))
>  {
> +  suppress_warning (*from_p, OPT_Wunused_result);
>gimplify_stmt (from_p, pre_p);
>gimplify_stmt (to_p, pre_p);
>*expr_p = NULL_TREE;
> diff --git a/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c 
> b/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
> new file mode 100644
> index 000..09be1a933c9
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/attr-warn-unused-result-2.c
> @@ -0,0 +1,15 @@
> +// PR c/82134
> +/* { dg-do compile } */
> +
> +struct S {};
> +
> +__attribute__((warn_unused_result)) struct S foo();
> +
> +void use_s(struct S);
> +
> +void
> +test (void)
> +{
> +  struct S s = foo(); /* { dg-bogus "ignoring return value of" } */
> +  use_s(foo()); /* { dg-bogus "ignoring return value of" } */
> +}
> diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
> index fad308e7f7b..5cd72ed1b3e 100644
> --- a/gcc/tree-cfg.cc
> +++ b/gcc/tree-cfg.cc
> @@ -9961,6 +9961,8 @@ do_warn_unused_result (gimple_seq seq)
>  break;
>if (gimple_call_internal_p (g))
>  break;
> +  if (warning_suppressed_p (g, OPT_Wunused_result))
> +break;
>
>/* This is a naked call, as opposed to a GIMPLE_CALL with an
>   LHS.  All calls whose value is ignored should be
> --
> 2.43.0
>