Discussion:
[Toybox] Warning: gcc can't tell this is never used uninitialized, but llvm can.
Rob Landley
2018-10-30 16:40:51 UTC
Permalink
I'm hammering on the release again. I flew back to Austin to vote and took the
whole week off, so I'm doing toybox and mkroot tidying and tackling some of
backlog of smaller todo items.

Promoting "watch.c" is currently held up by 2 things: 1) fixing crunch_str() now
that I know that combining characters are trailing rather than leading (so "this
is as many characters as will fit on this line" is only detectable when you find
the first that _won't_, not when you've found the last that _will_.)

And the three warnings gcc produces (but llvm doesn't), the larger todo item for
which is to figure out what to do about the "int x = x;" stuff, which is where
gcc produces "may be used uninitialized" warnings for variables that can never
be used uninitialized, and you can't switch it of without losing the "is used
uninitialized" warnings which _are_ reliably generated.

The workaround is to initialize it to itself, which doesn't produce any code
(and thus bloat the resulting binary with useless assignment that are always
overwritten), but some people complain it's not explicitly covered by the
standard. (It's clear what it _means_ in C, and Turbo C for DOS back in the
1980's was already optimizing it out, but gcc developers go out of their way to
break "signed integers have had two's complement behavior on every piece of
hardware manufactured since 1963 and posix requires two's complement be
available" and "I am comparing two pointers on the same stack to see how much
stack I've used, but I need to typecast them to long instead of char * because
gcc"...)

Meanwhile, when I build with the android NDK (which means llvm, I'm not testing
the NDK's vestigial gcc support that's going away next release anyway), it does
_NOT_ produce spurious warnings:

$ CROSS_COMPILE=llvm- LDFLAGS=--static make distclean defconfig watch
Compile toybox...................llvm-strip: Unknown command line argument
'-o'. Try: '/opt/android/x86_64/bin/llvm-strip -help'
llvm-strip: Did you mean '-O'?
strip failed, using unstripped
.

But of course Ubuntu's gcc still does:

$ make distclean defconfig watch
...
Compile toybox.................toys/pending/watch.c: In function 'watch_main':
toys/pending/watch.c:145:8: warning: 'active' may be used uninitialized in
this function [-Wmaybe-uninitialized]
if (active) {
^
toys/pending/watch.c:115:12: warning: 'yy' may be used uninitialized in this
function [-Wmaybe-uninitialized]
if (yy>=3) xprintf("\r\n");
^
toys/pending/watch.c:156:10: warning: 'xx' may be used uninitialized in this
function [-Wmaybe-uninitialized]
if (xx==width) {
^
...


You can search for the "x = x" assignments with the following (although there's
plenty of false positives):

grep '[^a-zA-Z0-9]\(..*\) = \1[,; ]' *.c lib/*.c toys/*/*.c

I made a

#define SHUTUP(x) x = x

And was replacing the assignments with the macro, and in theory you could switch
them _off_ with a config option if you wanted to debug the compiler, but... is
anybody likely to do that? It's been broken in gcc for a full decade now. If
everybody moves to llvm, then it could presumably just be removed.

No, I'm not turning them into initializations to 0. I've inspected them, they're
all already initialized, this is a BROKEN COMPILER WARNING. Which llvm is not
producing. The fundamental problem is gcc is doing single variable analysis but
the warnings are one variable depending on other:

int a, b;

a = fruitbasket();
if (a) b = potato();
...
if (a) printf("%d", b);

Where analysis of A has implications for B but gcc is only ever looking at
variables in isolation, and then giving wrong answers you can't disable.

Anyway, punting it for this release. I'll probably add the x = x initializations
to shut up gcc for watch.c when I promote it (llvm doesn't seem to _mind_), but
in future I think "gcc is crazy, you want llvm" is probably the go-to answer.

We need to add support for all the other architectures to llvm before that's a
real answer, though. :(

I've cc'd the ellcc maintainer because a reproducible up to date musl toolchain
with llvm would be kinda nice too.

Rob

P.S. This todo item is very, very old:

https://landley.net/notes-2006.html#31-12-2006
enh
2018-10-30 16:59:38 UTC
Permalink
Post by Rob Landley
I'm hammering on the release again. I flew back to Austin to vote and took the
whole week off, so I'm doing toybox and mkroot tidying and tackling some of
backlog of smaller todo items.
Promoting "watch.c" is currently held up by 2 things: 1) fixing crunch_str() now
that I know that combining characters are trailing rather than leading (so "this
is as many characters as will fit on this line" is only detectable when you find
the first that _won't_, not when you've found the last that _will_.)
And the three warnings gcc produces (but llvm doesn't), the larger todo item for
which is to figure out what to do about the "int x = x;" stuff, which is where
gcc produces "may be used uninitialized" warnings for variables that can never
be used uninitialized, and you can't switch it of without losing the "is used
uninitialized" warnings which _are_ reliably generated.
The workaround is to initialize it to itself, which doesn't produce any code
(and thus bloat the resulting binary with useless assignment that are always
overwritten), but some people complain it's not explicitly covered by the
standard. (It's clear what it _means_ in C, and Turbo C for DOS back in the
1980's was already optimizing it out, but gcc developers go out of their way to
break "signed integers have had two's complement behavior on every piece of
hardware manufactured since 1963 and posix requires two's complement be
available" and "I am comparing two pointers on the same stack to see how much
stack I've used, but I need to typecast them to long instead of char * because
gcc"...)
Meanwhile, when I build with the android NDK (which means llvm, I'm not testing
the NDK's vestigial gcc support that's going away next release anyway),
GCC was removed in r18 already. (there are gcc and g++ wrapper scripts
that just call clang, similar to what Apple did when they moved macOS
over a decade ago, plus GNU binutils is still there for now.)
Post by Rob Landley
it does
$ CROSS_COMPILE=llvm- LDFLAGS=--static make distclean defconfig watch
Compile toybox...................llvm-strip: Unknown command line argument
'-o'. Try: '/opt/android/x86_64/bin/llvm-strip -help'
llvm-strip: Did you mean '-O'?
strip failed, using unstripped
.
$ make distclean defconfig watch
...
toys/pending/watch.c:145:8: warning: 'active' may be used uninitialized in
this function [-Wmaybe-uninitialized]
if (active) {
^
toys/pending/watch.c:115:12: warning: 'yy' may be used uninitialized in this
function [-Wmaybe-uninitialized]
if (yy>=3) xprintf("\r\n");
^
toys/pending/watch.c:156:10: warning: 'xx' may be used uninitialized in this
function [-Wmaybe-uninitialized]
if (xx==width) {
^
...
You can search for the "x = x" assignments with the following (although there's
grep '[^a-zA-Z0-9]\(..*\) = \1[,; ]' *.c lib/*.c toys/*/*.c
I made a
#define SHUTUP(x) x = x
And was replacing the assignments with the macro, and in theory you could switch
them _off_ with a config option if you wanted to debug the compiler, but... is
anybody likely to do that? It's been broken in gcc for a full decade now. If
everybody moves to llvm, then it could presumably just be removed.
No, I'm not turning them into initializations to 0. I've inspected them, they're
all already initialized, this is a BROKEN COMPILER WARNING. Which llvm is not
producing. The fundamental problem is gcc is doing single variable analysis but
int a, b;
a = fruitbasket();
if (a) b = potato();
...
if (a) printf("%d", b);
Where analysis of A has implications for B but gcc is only ever looking at
variables in isolation, and then giving wrong answers you can't disable.
Anyway, punting it for this release. I'll probably add the x = x initializations
to shut up gcc for watch.c when I promote it (llvm doesn't seem to _mind_), but
in future I think "gcc is crazy, you want llvm" is probably the go-to answer.
We need to add support for all the other architectures to llvm before that's a
real answer, though. :(
I've cc'd the ellcc maintainer because a reproducible up to date musl toolchain
with llvm would be kinda nice too.
Rob
https://landley.net/notes-2006.html#31-12-2006
_______________________________________________
Toybox mailing list
http://lists.landley.net/listinfo.cgi/toybox-landley.net
Rob Landley
2018-10-30 17:05:49 UTC
Permalink
Post by Rob Landley
And the three warnings gcc produces (but llvm doesn't), the larger todo item for
which is to figure out what to do about the "int x = x;" stuff,
Ooh, spoke too soon. The gcc guys _did_ split it up so you can specifically
disable this warning without losing the "is used uninitialized" one.
Post by Rob Landley
https://landley.net/notes-2006.html#31-12-2006
The downside of that: I moved it up my todo list because I could now remove the
initializations because I can disable the warning (assuming current llvm doesn't
barf on the extra flag), but didn't edit the entry to add the extra _why_, and
then forgot about the changed context. :P

Rob
Josh Gao
2018-10-30 17:35:21 UTC
Permalink
Post by Rob Landley
Post by Rob Landley
And the three warnings gcc produces (but llvm doesn't), the larger todo
item for
Post by Rob Landley
which is to figure out what to do about the "int x = x;" stuff,
Ooh, spoke too soon. The gcc guys _did_ split it up so you can specifically
disable this warning without losing the "is used uninitialized" one.
(assuming current llvm doesn't barf on the extra flag)
I have bad news for you:
$ ./prebuilts/clang/host/linux-x86/clang-r339409b/bin/clang
-Wmaybe-initialized -x c++ -
warning: unknown warning option '-Wmaybe-initialized'; did you mean
'-Wuninitialized'? [-Wunknown-warning-option]
Rob Landley
2018-10-30 18:07:12 UTC
Permalink
Post by Rob Landley
(assuming current llvm doesn't barf on the extra flag)
$ ./prebuilts/clang/host/linux-x86/clang-r339409b/bin/clang -Wmaybe-initialized
-x c++ -
warning: unknown warning option '-Wmaybe-initialized'; did you mean
'-Wuninitialized'? [-Wunknown-warning-option] 
Which is why it was still on the todo list. Sigh. (Possibly llvm should
greenlight -Wno-* en masse if you're disabling something it doesn't _have_?
Dunno, not my area...)

The downside of leaving cryptic notes-to-self late at night that you don't see
again for months. And I said "current" because the last llvm I checked (2016?)
didn't have it. I remembered "missing" but forgot what specifically was missing
from where. I put it back on this release's todo list because somebody dinged me
on IRC about the x = x assignments on twitter being nonstandard. I want to say
"Rich Felker" since he tends to be the nitpickiest standards rules lawyer I hang
out with online, but it could be anybody at this point...

Rob

P.S. if you -x c++ toybox won't compile anyway. (C is not C++.)
enh
2018-10-30 18:17:37 UTC
Permalink
Post by Rob Landley
Post by Rob Landley
(assuming current llvm doesn't barf on the extra flag)
$ ./prebuilts/clang/host/linux-x86/clang-r339409b/bin/clang -Wmaybe-initialized
-x c++ -
warning: unknown warning option '-Wmaybe-initialized'; did you mean
'-Wuninitialized'? [-Wunknown-warning-option]
Which is why it was still on the todo list. Sigh. (Possibly llvm should
greenlight -Wno-* en masse if you're disabling something it doesn't _have_?
Dunno, not my area...)
i think the problem is: how would clang know whether it's an option
for a different compiler versus a simple typo?
Post by Rob Landley
The downside of leaving cryptic notes-to-self late at night that you don't see
again for months. And I said "current" because the last llvm I checked (2016?)
didn't have it. I remembered "missing" but forgot what specifically was missing
from where. I put it back on this release's todo list because somebody dinged me
on IRC about the x = x assignments on twitter being nonstandard. I want to say
"Rich Felker" since he tends to be the nitpickiest standards rules lawyer I hang
out with online, but it could be anybody at this point...
Rob
P.S. if you -x c++ toybox won't compile anyway. (C is not C++.)
_______________________________________________
Toybox mailing list
http://lists.landley.net/listinfo.cgi/toybox-landley.net
Loading...