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 <jer...@rifkin.dev>
---
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 00000000000..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