[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-09-06 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

--- Comment #61 from Andrew Church  ---
For the record, I'll maintain a copy of my (unaccepted) patch to add
-Wunused-result=strict at: https://achurch.org/patch-pile/#gcc
(wur-strict.diff)

This flag obviously shouldn't be relied on in released packages, but it may be
helpful for individual users trying to work around this issue.

[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-04-24 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

--- Comment #53 from Andrew Church  ---
(In reply to Segher Boessenkool from comment #51)
> And that is the core of why this issue reinflames once in a while: some
> people
> abuse the attribute, and the compiler cannot read minds.

Ah, for a mindread() API...

But ultimately, this is why I suggest that the compiler should leave as many
decisions as possible to the end user (in this case, the API user as opposed to
the API developer) - if the user has decided a particular result is safe to
ignore, then anything the compiler tries to do to stop that is just an
annoyance to be worked around or outright disabled.

> Completely useless casts to void cluttered programs decades ago already,
> we do not fear cargo cult, instead we observed it already existed.

At the risk of starting a linguistic discussion, the phrase you're looking for
is not "cargo cult", but "idiomatic".  Using "(void)" to mean "I am explicitly
discarding this value" is idiomatic, much the same way as "goodbye" is an
idiomatic greeting and not a literal wish for God to be with the listener.  I'm
probably not as old as some developers here, but I'm certainly old enough to
remember some compilers which gleefully spit out warnings on practically every
non-void expression, and liberal use of (void) was needed if you wanted any
chance at seeing the useful warnings.

"Cargo cult" programming is when people start using (void) without even knowing
what it does:  "Hey, so what does this 'void' thing do?"  "Uh, I dunno, it's
all over the code so I just copied it."  I wouldn't be surprised to find cases
of that as well, but I don't think that's the specific thing we're worried
about here.

> Changing the behaviour of this attribute after all that time will not make
> things better.  But perhaps we can say a bit more in the documentation,
> maybe at one of the three very concise quotes above?  Say half a line worth?

If glibc changes from _wur to [[nodiscard]], as Florian suggested may happen,
that would resolve the immediate case that brought me here (a "best-effort"
system() call, where the success or failure of the call or the program executed
is irrelevant to the caller).  I do fear leaving the current behavior as is
could just be kicking the can down the road, so to speak, but perhaps a slight
edit here might help:

> 'warn_unused_result'
>  The 'warn_unused_result' attribute causes a warning to be emitted
>  if a caller of the function with this attribute does not use its
>  return value.  This is useful for functions where not checking the
>  result is either a security problem or always a bug, such as
>  'realloc'.

I would suggest removing "either a security problem or", and adding something
along the lines of:

"For cases in which not checking the result carries risks but is not
necessarily an error, use the [[nodiscard]] attribute, which allows the caller
to suppress the warning by explicitly casting the result to void."

Writing user documentation isn't (remotely!) my specialty, but I think
something like this could both help clarify that the two behave differently and
let people know that yes, the fact that you can't silence _wur calls is
intentional.

[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-04-24 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

--- Comment #48 from Andrew Church  ---
(In reply to rusty from comment #47)
> Civility please.

I have no intention of trying to start a fight :)  Like you, I'm just trying to
improve the situation, and knowing that in my own open-source work I'm always
happier when a user offers a patch instead of just a "please fix this", I've
done the same here.  That said, since I _am_ trying to improve the situation, I
won't step back from debating the utility of the change if the developer
disagrees.  (And I freely admit that I can be tempted into a bit of snark from
time to time...)

> But accept that the
> conversation on this issue is only a weak indication of consensus.

I agree, which is why I gave other examples such as Clang's behavior and
especially the C++/C2x standards.  While I grant that even standards committees
are small subsets of the total user community and are not immune to poor
decision-making, I'd consider the facts that (1) the C++17 description of
[[nodiscard]] called out void casts as a case which should not be diagnosed,
(2) C++20 expanded on that with an explicit example of a cast-to-void call not
being diagnosed, and (3) C2x, as of the current draft, also includes the
call-out of void casts from C++17 (though not the explicit example from C++20),
to collectively be a much stronger indicator of that consensus.

> As Andrew Pinski says "people are mis-using this attribute", and Jakub
> Jelinek makes a similar point.  The use of _wur has changed from "ignoring
> the result is criminally wrong" to "possibly wrong".

I think "mis-using" is a bit harsh; the core concept (warning about a discarded
return value) is a useful one, as evidenced by the feature's adoption into C++
and subsequently C2x.  I grant that it's being used for a wider variety of
purposes than originally intended, but since there was no other option until
the relatively recent addition of [[nodiscard]], that's what people went with.

I was thinking about adding a suggestion for multiple levels of warning, such
as "ignoring this is almost certainly wrong" (e.g. realloc()) vs "ignoring this
could be dangerous, you might want to doublecheck" (e.g. system()); in fact,
[[nodiscard]] is effectively that since void casts do silence [[nodiscard]]
warnings in GCC, though I don't know if the difference in behavior from _wur is
intentional.  But that ultimately wouldn't do anything about the present
problem, which is API developers and users disagreeing on whether a return
value is safe to discard - it might morph into something like "why is this
function marked with the stricter _wur when it should just be [[nodiscard]]",
and we're back to wanting to selectively silence _wur warnings again.

[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-04-23 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

--- Comment #46 from Andrew Church  ---
(In reply to Andrew Pinski from comment #45)
> But there is no general agreement at all. If clang behavior agreed with gcc,
> then there would be consensus here. In fact gcc behavior is older than clang
> behavior makes this even more difficult and even points out that if clang
> said it implemented a compatible extension, it did not.

First, a single disagreement does not invalidate a consensus, at least in the
general meaning which I quoted ("the judgment arrived at by most of those
concerned" - note "most" and not "all").  As I discussed earlier, I still see
significantly wider support for the view that void casts should silence
discarded-value warnings, to the extent that I consider it fair to call that
view a consensus.

Second, an equally valid view of the meaning of Clang's behavior differing from
GCC's - barring any deeper knowledge of the LLVM team's decision-making, which
I do not have - is that the LLVM team merged the observed intent behind the
original extension (warn about values which should not be discarded) with its
knowledge of existing practice (use of a void cast to indicate a deliberately
discarded value) to arrive at their choice of behavior.  If anything, I'd
suggest that https://bugs.llvm.org/show_bug.cgi?id=51228 being marked WONTFIX
because the developers consider it to be "working as intended" argues for this
view.

> You are basically saying all warnings will be ignored which is true.

That's not what I said, and I disagree at least with that particular phrasing. 
I would, however, accept "warnings will be ignored if the user feels the effort
to fix the warning is not worth the benefit".  By corollary, users in general
will take the path of least resistance to resolving a warning, and if allowing
void casts to silence specific instances of the warning encourages them to
leave the warning enabled in general, it will result in better code than if the
user gets so frustrated with the warning that they just turn it off completely.

> Using a void cast makes life too easy to ignore this behavior.

It still requires action on the part of the programmer.  A programmer who
writes

   system("foo");

may want to be warned that the return code from system() is discarded, whereas
a programmer who writes

   (void) system("foo");

has clearly stated an intent to discard that return value, and warning about it
anyway is unnecessary noise.  (Though an argument could be certainly be made
for a better word than "void", perhaps a construction like "[[discard]]
foo()".)

Is there a risk of cargo-cult syndrome?  (A: "Hey B, how do I call this
external foo program?"  B: "Just write '(void) system("foo")'.")  Certainly. 
But the same argument can be made for _any_ workaround, and I suspect that more
complex workarounds would increase, rather than decrease, that risk - the more
complex the code, the less likely the user is to read it and understand what
it's doing.

> If the api user wants to ignore the return
> values while the api developer tells you should not, then really the api
> user will have bugs. This is why the warning is there.

Demonstrably false (see above, and even your own caveat below).

> Now api developers
> have known to place this attribute on things that should not be placed on
> but that is not a compiler issue and the api user should talk with the api
> developer rather than try to change the compiler for their workaround.

Suppose the API developer's response is, "I don't care about your use case, I
want you to do things my way."  What is the (non-compiler developer) user to do
then?  Look for an alternative library, which may not even exist?  Spend the
time to write their own?  Disable the warning and accept the risk of bugs in
unrelated code?  Look up the workaround du jour and throw it all over their
code base, cargo-cult style?

If I were faced with that choice, I would probably just switch to Clang.

[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-04-23 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

--- Comment #44 from Andrew Church  ---
(In reply to Segher Boessenkool from comment #43)
> That is not the consensus, no.  "Consensus" does not mean doing what the
> unthinking masses shout.

Merriam-Webster disagrees:
con.sen.sus
1 a: general agreement : UNANIMITY
  b: the judgment arrived at by most of those concerned

I specifically clarified that with "wider" to indicate the larger group of "C
compiler users", as opposed to what you seem to mean, "C compiler developers". 
And in whatever sense you choose to regard them, the judgment arrived at by
most C compiler users does seem to be "cast to void should suppress a warning
about a discarded value", as I described above.

> So allowing casts to void
> to suppress this warning means the warning becomes less useful, and people
> will write worse code.  That is not something GCC should encourage IMO.

You seem to think that making the warning harder to work around will encourage
programmers to change their code to fix the warning.  In reality, they are more
likely to either (1) disable the warning entirely or (2) disregard warnings in
general, both of which result in considerably worse code - the situation you
say you are trying to avoid.  Thus my suggestion to follow the principle of
least surprise and allow a void cast to disable the warning by default.

[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-04-23 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

--- Comment #42 from Andrew Church  ---
(In reply to Sam James from comment #41)
> Could you send it to the gcc-patches mailing list please? (Even if it is a
> PoC).

Sent as requested.

[Bug c/66425] (void) cast doesn't suppress __attribute__((warn_unused_result))

2023-04-22 Thread achurch+gcc at achurch dot org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425

Andrew Church  changed:

   What|Removed |Added

 CC||achurch+gcc at achurch dot org

--- Comment #40 from Andrew Church  ---
Created attachment 54906
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54906=edit
POC patch to add -Wunused-result=strict

In hopes of moving this along (after having run into it for the third or fourth
time myself), here's a proof-of-concept patch against GCC 12.2.0 which adds
"-Wunused-result=strict" for the current behavior and changes "-Wunused-result"
to ignore cases in which the result is discarded by casting to void.

My rationale for changing the default behavior is that the wider community
consensus, as evidenced by things like the C++ (and C2x) [[nodiscard]]
specification, the behavior of Clang, and the balance of comments on this bug,
seems to be that casting a discarded return value to void should suppress any
warning about the discarded value; and under the principle of least surprise,
GCC should follow that consensus by default even if it also provides
alternative behaviors.