qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 06/19] block/stream: fix -Werror=maybe-uninitialized false-po


From: Vladimir Sementsov-Ogievskiy
Subject: Re: [PATCH 06/19] block/stream: fix -Werror=maybe-uninitialized false-positives
Date: Thu, 4 Apr 2024 00:28:30 +0300
User-agent: Mozilla Thunderbird

On 03.04.24 20:50, Eric Blake wrote:
On Wed, Apr 03, 2024 at 01:24:11PM +0400, Marc-André Lureau wrote:
Unfortunately, it doesn't work in all cases. It seems to have issues
with some guards:
../block/stream.c: In function ‘stream_run’:
../block/stream.c:216:12: error: ‘ret’ may be used uninitialized
[-Werror=maybe-uninitialized]
    216 |         if (ret < 0) {


That one looks like:

int ret;
WITH_GRAPH_RDLOCK_GUARD() {
   ret = ...;
}
if (copy) {
   ret = ...;
}
if (ret < 0)

I suspect the compiler is seeing the uncertainty possible from the
second conditional, and letting it take priority over the certainty
that the tweaked macro provided for the first conditional.



So, updated macro helps in some cases, but doesn't help here? Intersting, why.

What should we do? change the macros + cherry-pick the missing
false-positives, or keep this series as is?

An uglier macro, with sufficient comments as to why it is ugly (in
order to let us have fewer false positives where we have to add
initializers) may be less churn in the code base, but I'm not
necessarily sold on the ugly macro.  Let's see if anyone else
expresses an opinion.





I think marco + missing is better. No reason to add dead-initializations in 
cases where new macros helps.

Ok

Still, would be good to understand, what's the difference, why it help on some 
cases and not help in another.

I don't know, it's like if the analyzer was lazy for this particular
case, although there is nothing much different from other usages.

If I replace:
for (... *var2 = (void *)true; var2;
with:
for (... *var2 = (void *)true; var2 || true;

then it doesn't warn..

but it also doesn't work.  We want the body to execute exactly once,
not infloop.



Interestingly as well, if I change:
     for (... *var2 = (void *)true; var2; var2 = NULL)
for:
     for (... *var2 = GML_OBJ_(); var2; var2 = NULL)

GML_OBJ_() simply being &(GraphLockable) { }), an empty compound
literal, then it doesn't work, in all usages.

So the compiler is not figuring out that the compound literal is
sufficient for an unconditional one time through the for loop body.

What's worse, different compiler versions will change behavior over
time.  Making the code ugly to pacify a particular compiler, when that
compiler might improve in the future, is a form of chasing windmills.


All in all, I am not sure the trick of using var2 is really reliable either.

And that's my biggest argument for not making the macro not more
complex than it already is.


All sounds reasonable, I'm not sure now.

I still don't like an idea to satisfy compiler false-positive warnings by extra 
initializations.. Interesting that older versions do have unitialized-use 
warnings, but don't fail here (or nobody check?). Is it necessary to fix them 
at all? Older versions of compiler don't produce these warnings?  Is it 
possible that some optimizations in new GCC version somehow breaks our WITH_ 
hack, so that it really lead to uninitialized behavior? And we just mask real 
problem with these patches?

Wouldn't it more correct to just drop WITH_ hack, and move to a bit uglier but 
more gcc-native and fair

{
   QEMU_LOCK_GUARD(lock);
   ...
}

?

--
Best regards,
Vladimir




reply via email to

[Prev in Thread] Current Thread [Next in Thread]