public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "jimfr06 at gmail dot com" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c/54544] New: Option -Wuninitialized does not work as documented with volatile
Date: Mon, 10 Sep 2012 21:19:00 -0000	[thread overview]
Message-ID: <bug-54544-4@http.gcc.gnu.org/bugzilla/> (raw)

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54544

             Bug #: 54544
           Summary: Option -Wuninitialized does not work as documented
                    with volatile
    Classification: Unclassified
           Product: gcc
           Version: 4.6.3
            Status: UNCONFIRMED
          Severity: minor
          Priority: P3
         Component: c
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: jimfr06@gmail.com


I first filed this bug to Ubuntu Launchpad under the reference 1008090:
https://bugs.launchpad.net/ubuntu/+source/gcc-4.6/+bug/1008090

A the finding of the Ubuntu guys is that it is an upstream bug, I'll just
copy/paste it here (with additional findings).

I classified is as "minor" as we are talking "only" of warnings (but still it
is an annoyance) and/or a documentation bug.
==============================================================================

Versions of Ubuntu and gcc:
-------------------------------------

(Precise amd64, out-of-the-box gcc)

$ LANG=ENG && uname -a && echo && gcc -v
Linux zakhar-desktop 3.2.0-24-generic #39-Ubuntu SMP Mon May 21 16:52:17 UTC
2012 x86_64 x86_64 x86_64 GNU/Linux

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro
4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.6 --enable-shared --enable-linker-build-id
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object
--enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686
--with-tune=generic --enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

WHAT HAPPENS:
--------------------

Consider the source code below:

/*01*/ int fct(volatile int *p);
/*02*/
/*03*/ int
/*04*/ foo( p )
/*05*/ volatile int *p;
/*06*/ {
/*07*/   volatile int foobar,barfoo;
/*08*/   volatile int flag=0;
/*09*/   volatile int *bar;
/*10*/
/*11*/   do
/*12*/     {
/*13*/       if ( *p )
/*14*/         {
/*15*/           flag= fct( p );
/*16*/           bar = p;
/*17*/         }
/*18*/       if ( fct( p ) ) break;
/*19*/       if ( flag )
/*20*/         {
/*21*/           barfoo = *bar;
/*22*/           if ( bar == (int *)0 ) break;
/*23*/           foobar = *bar;
/*24*/           return foobar + barfoo;
/*25*/         }
/*26*/     }
/*27*/   while ( fct( p ) );
/*28*/
/*29*/   return 0;
/*30*/ }

Compile it and you get:

$ gcc -O3 -c uninit.c -o /dev/null -Wall

uninit.c: In function 'foo':
uninit.c:23:27: warning: 'bar' may be used uninitialized in this function
[-Wuninitialized]

WHAT SHOULD HAPPEN:
------------------------------

1) gcc makes a *VERY BAD* job at detecting uninitialized!
Per se, this is not a bug, because it is duly documented that in some
situations, gcc cannot guess.
Here, simple logic proves that the detection is bad:
- you cannot reach lines 21-24 unless flag is not zero.
- flag is initialized to zero, and the only place it can take another value is
line 15, where it gets the result of our external function.
- if we go to line 15, the next line in sequence would initialize 'bar'.
- thus when we go to lines 21-24 'bar' is definitely initialized.

Other strange things about this false detection:
- it warns on line 23, and not on lines 21 or 22 that already use the same
variable BEFORE line 23!
- it stops warning if you remove line 18! This is odd, because line 18 only
breaks out of the flow on certain condition, and as this is before we use the
allegedly uninitialized variable, it can do no harm. One could argue that gcc
can move line 18 up, but I hope it does not... as we don't know whether our
external function has side effect (and no way I know in C to instruct the
compiler it does not!), if it has side effects this would break the behaviour
of the code as fct is already called on line 15, prior to line 18.

2) Apart from that bad detection of uninitialized, the behaviour is *NOT
COMPLIANT with the documentation*.

If you look at the documentation page here:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

It says:
-Wuninitialized
    Warn if an automatic variable is used without first being initialized (...)

   (...)

   (...) They do not occur for *variables or elements declared volatile*.

As you see, in the code: 'bar' is an automatic variable, 'bar' has been
declared volatile (and as demonstrated in 1: it *IS* initialized!), and gcc
continues to spit out the warning.

CONCLUSION:
---------------

We do certainly have a bad detection of 'uninitialized'

Plus,
- either we have a bug in gcc that do not remove the warning in spite of the
volatile qualifier
- either we have a bug in the documentation, and 'volatile' is irrelevant to
that warning!.. but then gcc should provide a way so that the programmer can
make the warning disappear when he does perfectly know un-initialization can't
happen.


ADDITIONNAL FINDINGS
--------------------
I found that if we make the 'foo' function 'static' the bug disappears.
Does gcc think someone can jump inside the function (which has no label
whatsoever for that purpose)? If we could jump anywhere from "outside" to the
"inside" of any function with no label... there would surely be plenty of
uninitialized variables, wouldn't it?

Unfortunately for my use-case, 'static' is not an option as the function I am
writing is part of a (small) library, and meant to be called from other source
files. Thus the function has to be 'extern' for me.


             reply	other threads:[~2012-09-10 21:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-10 21:19 jimfr06 at gmail dot com [this message]
2012-09-10 21:23 ` [Bug middle-end/54544] " pinskia at gcc dot gnu.org
2012-09-10 21:33 ` jimfr06 at gmail dot com
2012-09-11 16:42 ` jimfr06 at gmail dot com
2012-09-11 21:09 ` jimfr06 at gmail dot com

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-54544-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).