[Toybox] Warning: gcc can't tell this is never used uninitialized, but llvm can.

Rob Landley rob at landley.net
Tue Oct 30 09:40:51 PDT 2018


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


More information about the Toybox mailing list