User account creation filtered due to spam.

Bug 34772

Summary: [4.4/4.5/4.6 Regression] self-initialisation does not silence uninitialised warnings (-Winit-self ignored)
Product: gcc Reporter: olly
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: davi.arnaut, ext, fang, gcc-bugs, gerald, jason, julien.sagnard, manu, pinskia
Priority: P4 Keywords: diagnostic
Version: 4.2.1   
Target Milestone: 4.4.7   
Host: Target:
Build: Known to work: 3.3.6, 4.7.0
Known to fail: 3.4.4, 4.2.1, 4.3.0 Last reconfirmed: 2008-01-14 00:42:56
Bug Depends on:    
Bug Blocks: 24639, 18016    

Description olly 2008-01-13 18:01:40 UTC
The info manual says:

`-Winit-self (C, C++, Objective-C and Objective-C++ only)'
     Warn about uninitialized variables which are initialized with
     themselves.  Note this option can only be used with the
     `-Wuninitialized' option, which in turn only works with `-O1' and
     above.

     For example, GCC will warn about `i' being uninitialized in the
     following snippet only when `-Winit-self' has been specified:
          int f()
          {
            int i = i;
            return i;
          }

However, trying that exact example, I get:

$ g++-4.2 -O -Wuninitialized -c warnings.cc 
warnings.cc: In function ‘int f()’:
warnings.cc:3: warning: ‘i’ is used uninitialised in this function
$ g++-4.2 -O -Wuninitialized -Wno-init-self -c warnings.cc 
warnings.cc: In function ‘int f()’:
warnings.cc:3: warning: ‘i’ is used uninitialised in this function

Compiling the same code as C:

$ gcc-4.2 -x c -O -Wuninitialized -c warnings.cc 
$ gcc-4.2 -x c -O -Wuninitialized -Winit-self -c warnings.cc
warnings.cc: In function ‘f’:
warnings.cc:3: warning: ‘i’ is used uninitialised in this function
$

So it appears that g++ simply ignores the -Winit-self setting and always warns about such code, contrary to what the documentation states (and gcc works as documented).  ObjC seems to handle this as C does (as documented).  ObjC++ seems to handle it as C++ does (contrary to documentation).

This could be viewed as a documentation bug, though it seems more useful for this to work for C++ (and ObjC++) as is currently documented.

It looks like -Winit-self was new in GCC 3.4, and I can the same behaviour for C++ with g++ 3.4.4, so I don't think this is a regression.
Comment 1 olly 2008-01-13 18:23:35 UTC
I've just noticed that Debian have a packaged 4.3 snapshot:

g++-4.3 (Debian 4.3-20080104-1) 4.3.0 20080104 (experimental) [trunk revision 131316]

Testing with this shows the same behaviour for C++.
Comment 2 Manuel López-Ibáñez 2008-01-14 00:42:56 UTC
Good catch!

Well, there is something weird going on

$ cc1 -fdump-tree-original -O winit-self.c

{
  int i = i;

    int i = i;
  return i;
}

$ cc1plus -fdump-tree-original -O winit-self.c

{
  int i;

    int i;
  <<cleanup_point <<< Unknown tree: expr_stmt
  (void) (i = i) >>>
>>;
  return <retval> = i;
}


The first problem is that C++ FE does not generate a DECL_EXPR but a BIND_EXPR, so it does not trigger the conditional in c-gimplify.c (c_gimplify_expr). My guess is that this have never worked in C++. So we can just delete this option from the C++ FE and convert this to an enhancement request. If none disagrees, I will submit a patch in the next days.

Comment 3 olly 2008-01-14 00:58:33 UTC
If by "delete this option from the C++ FE" you mean that `g++ -Winit-self [...]' would give an error, I'm not sure that's the best approach if the option is likely to be sorted out for C++ in the future.  Removing it now will break existing makefiles which use -Winit-self for C++ compilations.  And once -Winit-self is sorted out for C++, it will be harder to write a makefile which gives a warning for self-initialised variables for any GCC version (if it's left as-is for now, then -Winit-self can just be specified all the time for any GCC version >= 3.4).

The situation here is slightly odd in that -Winit-self is effectively always on for C++, so in a way it does work - it's not specifying it (or -Wno-init-self) which doesn't!

I think it would be better to fix the documentation to reflect the current behaviour for C++/ObjC++, and mark this bug as an enhancement request.
Comment 4 Manuel López-Ibáñez 2008-01-14 01:27:41 UTC
(In reply to comment #3)
> I think it would be better to fix the documentation to reflect the current
> behaviour for C++/ObjC++, and mark this bug as an enhancement request.

It is a bit misleading providing -Winit-self when it has no effect and when it cannot be disabled. But your argument about breaking existing code is solid. So, of course, I will only update the documentation:

Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 130605)
+++ gcc/doc/invoke.texi (working copy)
@@ -2827,14 +2827,15 @@
 @option{-Wnonnull} is included in @option{-Wall} and @option{-Wformat}.  It
 can be disabled with the @option{-Wno-nonnull} option.

-@item -Winit-self @r{(C, C++, Objective-C and Objective-C++ only)}
+@item -Winit-self @r{(C and Objective-C only)}
 @opindex Winit-self
 Warn about uninitialized variables which are initialized with themselves.
 Note this option can only be used with the @option{-Wuninitialized} option,
 which in turn only works with @option{-O1} and above.

-For example, GCC will warn about @code{i} being uninitialized in the
-following snippet only when @option{-Winit-self} has been specified:
+For C and Objective-C, GCC will silence the warning about @code{i}
+being uninitialized in the following snippet unless
+@option{-Winit-self} has been specified:
 @smallexample
 @group
 int f()
@@ -3094,11 +3095,12 @@
 These warnings are possible only in optimizing compilation,
 because they require data flow information that is computed only
 when optimizing.  If you do not specify @option{-O}, you will not get
-these warnings. Instead, GCC will issue a warning about @option{-Wuninitialized}
-requiring @option{-O}.
+these warnings. Instead, GCC will issue a warning about
+@option{-Wuninitialized} requiring @option{-O}.

-If you want to warn about code which uses the uninitialized value of the
-variable in its own initializer, use the @option{-Winit-self} option.
+For C and Objective-C, using the uninitialized value of the variable in its
+own initializer (e.g. @samp{int i = i;}) silences the warning. If you
+want to warn about such code use the @option{-Winit-self} option.

 These warnings occur for individual uninitialized or clobbered
 elements of structure, union or array variables as well as for
Comment 5 Manuel López-Ibáñez 2008-01-14 01:35:24 UTC
Actually. Winit-self was introduced in GCC 3.4 but the init-self trick was probably introduced earlier. So this may actually be a regression from much earlier. Anyway, documenting that it doesn't work seems the right thing to do.
Comment 6 Andrew Pinski 2008-01-14 01:45:59 UTC
This should work, if it does not then it is a bug.
Comment 7 Manuel López-Ibáñez 2008-01-14 02:08:44 UTC
So it seems this worked in 3.3, so it is a regression after all.
Comment 8 Richard Biener 2008-01-14 10:46:33 UTC
Regression for a GCC extension that silences a diagnostic.  P4.
Comment 9 Andrew Pinski 2008-01-20 05:39:28 UTC
Tomorrow after my extra checking build finishes, I will look into fixing this bug.
Comment 10 Joseph S. Myers 2008-07-04 22:28:06 UTC
Closing 4.1 branch.
Comment 11 Paolo Carlini 2008-10-16 16:16:45 UTC
*** Bug 37854 has been marked as a duplicate of this bug. ***
Comment 12 Joseph S. Myers 2009-03-31 20:17:04 UTC
Closing 4.2 branch.
Comment 13 Richard Biener 2009-08-04 12:28:41 UTC
GCC 4.3.4 is being released, adjusting target milestone.
Comment 14 Manuel López-Ibáñez 2009-12-30 11:29:31 UTC
*** Bug 42238 has been marked as a duplicate of this bug. ***
Comment 15 Richard Biener 2010-05-22 18:11:51 UTC
GCC 4.3.5 is being released, adjusting target milestone.
Comment 16 Jason Merrill 2011-05-09 17:34:48 UTC
Author: jason
Date: Mon May  9 17:34:44 2011
New Revision: 173582

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173582
Log:
	PR c++/34772
	* decl.c (initialize_local_var): Use DECL_INITIAL for simple
	initialization.

Added:
    trunk/gcc/testsuite/c-c++-common/uninit-D-O0.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-D-O0.c
    trunk/gcc/testsuite/c-c++-common/uninit-D.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-D.c
    trunk/gcc/testsuite/c-c++-common/uninit-E-O0.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-E-O0.c
    trunk/gcc/testsuite/c-c++-common/uninit-E.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-E.c
    trunk/gcc/testsuite/c-c++-common/uninit-F-O0.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-F-O0.c
    trunk/gcc/testsuite/c-c++-common/uninit-F.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-F.c
    trunk/gcc/testsuite/c-c++-common/uninit-G-O0.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-G-O0.c
    trunk/gcc/testsuite/c-c++-common/uninit-G.c
      - copied, changed from r173581, trunk/gcc/testsuite/gcc.dg/uninit-G.c
Removed:
    trunk/gcc/testsuite/gcc.dg/uninit-D-O0.c
    trunk/gcc/testsuite/gcc.dg/uninit-D.c
    trunk/gcc/testsuite/gcc.dg/uninit-E-O0.c
    trunk/gcc/testsuite/gcc.dg/uninit-E.c
    trunk/gcc/testsuite/gcc.dg/uninit-F-O0.c
    trunk/gcc/testsuite/gcc.dg/uninit-F.c
    trunk/gcc/testsuite/gcc.dg/uninit-G-O0.c
    trunk/gcc/testsuite/gcc.dg/uninit-G.c
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/decl.c
    trunk/gcc/testsuite/ChangeLog
Comment 17 Jason Merrill 2011-05-09 20:48:47 UTC
Fixed on trunk so far.
Comment 18 Richard Biener 2011-06-27 12:12:54 UTC
4.3 branch is being closed, moving to 4.4.7 target.
Comment 19 Manuel López-Ibáñez 2011-06-27 13:10:08 UTC
I think no one is going to backport this, specially because it produces new warnings, and users wouldn't like that in a minor version. Let's close it.
Comment 20 Davi Arnaut 2011-06-27 16:40:52 UTC
Actually, we would really like it. Currently, we have to disable it because most of the warnings are bogus. New _valid_ warnings are welcome.
Comment 21 Manuel López-Ibáñez 2011-06-27 18:01:40 UTC
(In reply to comment #20)
> Actually, we would really like it. Currently, we have to disable it because
> most of the warnings are bogus. New _valid_ warnings are welcome.

If you think most -Winit-self warnings are bogus, this fix cannot help you.
Comment 22 Davi Arnaut 2011-06-27 19:15:45 UTC
(In reply to comment #21)
>> Actually, we would really like it. Currently, we have to disable it because
>> most of the warnings are bogus. New _valid_ warnings are welcome.
>
> If you think most -Winit-self warnings are bogus, this fix cannot help you.

Sorry, I wasn't talking about -Winit-self warnings. I meant that most uninitialised warnings in C++ are bogus [1]. Hence, we have to work around this by actually initializing certain variables. By initializing the variable we lose coverage by tools such as valgrind,. The self-initialization trick allow us to avoid this problem.

Also, we even had a runtime "performance issue" associated with it in debug builds. A large structure (containing floats, etc) needed to be partially initialized to silence the warnings, but it caused a penalty since it was located in a hot function (ended up slowing our test suite).

Anyway, point is, it would be nice to have this fixed in the early 4.x branches.

1. I believe there is a bug report about this.