Bug 48087 - [4.7/4.8/4.9 Regression] -Wall -Werror adds warnings over and above those generated by -Wall
Summary: [4.7/4.8/4.9 Regression] -Wall -Werror adds warnings over and above those gen...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.6.0
: P2 normal
Target Milestone: 4.7.4
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2011-03-12 06:20 UTC by Chris Demetriou
Modified: 2014-01-23 07:21 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.4.4
Known to fail:
Last reconfirmed: 2012-02-06 00:00:00


Attachments
gcc48-pr48087.patch (1.98 KB, patch)
2013-01-15 15:11 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Demetriou 2011-03-12 06:20:55 UTC
was checking the status of the code in PR33752 against 4.6, and discovered that under GCC pre-4.6,

    -Wall -Werror

causes more errors/warnings to be generated than just -Wall.

See code an examples below.

This is a bit surprising; certainly, the manual just says:

       -Werror
           Make all warnings into errors.

the 4.4.x (and earlier) behaviour of stopping earlier (exiting after the first error, in this example) is not ideal, but IMO is less surprising than having -Werror *add* errors.


the test input file from PR33752, placed into x.cc:

class Alpha {
 public:
   Alpha() { }
   ~Alpha();
};

class Beta {
 public:
   Beta() { }
   ~Beta() __attribute__((noreturn));
   bool value() { return false; }
};

bool Gamma(bool b) {
 return b;
}

bool DeltaOne(bool b) {
 Alpha s;
 bool b2 = Beta().value();
 Gamma(b2);
}

bool DeltaTwo(bool b) {
 if (b) {
   return false;
 } else {
   bool b2 = Beta().value();
   Gamma(Beta().value());
 }
}

bool DeltaThree(bool b) {
 Alpha s;

 if (b) {
   return false;
 } else {
   bool b2 = Beta().value();
   Gamma(b2);
 }
}


GCC 4.4.5 (from ftp.gnu.org):

$ inst/bin/gcc --version | head -1
gcc (GCC) 4.4.5
$ 

$ inst/bin/gcc -c /tmp/x.cc -Wall
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:28: warning: unused variable 'b2'
/tmp/x.cc: In function 'bool DeltaThree(bool)':
/tmp/x.cc:42: warning: control reaches end of non-void function
$ 

-> 2 warnings.

$ inst/bin/gcc -c /tmp/x.cc -Wall -Werror
cc1plus: warnings being treated as errors
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:28: error: unused variable 'b2'
$ 

-> 1 error, stopping after the first.  not necessarily perfect, but OK.


GCC 4.5.2 (from ftp.gnu.org):

$ inst/bin/gcc --version | head -1
gcc (GCC) 4.5.2
$ 

$ inst/bin/gcc -c /tmp/x.cc -Wall
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:28:9: warning: unused variable 'b2'
/tmp/x.cc: In function 'bool DeltaThree(bool)':
/tmp/x.cc:42:1: warning: control reaches end of non-void function
$ 

-> 2 warnings

$ inst/bin/gcc -c /tmp/x.cc -Wall -Werror
cc1plus: warnings being treated as errors
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:28:9: error: unused variable 'b2'
/tmp/x.cc: In function 'bool DeltaThree(bool)':
/tmp/x.cc:42:1: error: control reaches end of non-void function
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:31:1: error: control reaches end of non-void function
/tmp/x.cc: In function 'bool DeltaOne(bool)':
/tmp/x.cc:22:1: error: control reaches end of non-void function
$ 

-> 4 errors.  Huh?


GCC pre-4.6 (svn trunk as of yesterday):

$ inst/bin/gcc --version | head -1
gcc (GCC) 4.6.0 20110311 (experimental)
$ 

$ inst/bin/gcc -c /tmp/x.cc -Wall
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:28:9: warning: unused variable 'b2' [-Wunused-variable]
/tmp/x.cc: In function 'bool DeltaThree(bool)':
/tmp/x.cc:42:1: warning: control reaches end of non-void function [-Wreturn-type]
$ 

-> 2 warnings.

$ inst/bin/gcc -c /tmp/x.cc -Wall -Werror
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:28:9: error: unused variable 'b2' [-Werror=unused-variable]
/tmp/x.cc: In function 'bool DeltaThree(bool)':
/tmp/x.cc:42:1: error: control reaches end of non-void function [-Werror=return-type]
/tmp/x.cc: In function 'bool DeltaTwo(bool)':
/tmp/x.cc:31:1: error: control reaches end of non-void function [-Werror=return-type]
/tmp/x.cc: In function 'bool DeltaOne(bool)':
/tmp/x.cc:22:1: error: control reaches end of non-void function [-Werror=return-type]
cc1plus: all warnings being treated as errors

$ 

-> 4 errors.  Same as 4.6, but still "huh?"
Comment 1 Paolo Carlini 2011-10-18 00:53:48 UTC
Chris, did you ever see something similar for other warnings besides 'control reaches end of non-void function'?

Because the latter is "special" in that isn't produced by the C++ front-end by itself, and is also known to be affected by at least another annoying issue, see PR49508. Humm, are we talking about the same issue actually?

In case, would it be hard to implement what Jakub suggested in PR49508?
Comment 2 Paolo Carlini 2011-10-18 01:18:24 UTC
Well, this does, it (fixes both) but I don't know if we are aiming for something better, no good including the whole "diagnostic.h"?!?

Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 180119)
+++ tree-cfg.c	(working copy)
@@ -37,7 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "tree-dump.h"
 #include "tree-pass.h"
-#include "diagnostic-core.h"
+#include "diagnostic.h"
 #include "except.h"
 #include "cfgloop.h"
 #include "cfglayout.h"
@@ -7380,7 +7380,8 @@ execute_warn_function_return (void)
   else if (warn_return_type
 	   && !TREE_NO_WARNING (cfun->decl)
 	   && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0
-	   && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
+	   && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl)))
+	   && !errorcount)
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
 	{
Comment 3 Paolo Carlini 2011-10-18 01:22:07 UTC
*** Bug 49508 has been marked as a duplicate of this bug. ***
Comment 4 Paolo Carlini 2011-10-18 01:30:26 UTC
This should be middle-end, and strictly speaking a regression.
Comment 5 rguenther@suse.de 2011-10-18 08:26:04 UTC
On Tue, 18 Oct 2011, paolo.carlini at oracle dot com wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48087
> 
> Paolo Carlini <paolo.carlini at oracle dot com> changed:
> 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>              Status|UNCONFIRMED                 |NEW
>    Last reconfirmed|                            |2011-10-18
>                  CC|                            |paolo.carlini at oracle dot
>                    |                            |com
>      Ever Confirmed|0                           |1
> 
> --- Comment #2 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-10-18 01:18:24 UTC ---
> Well, this does, it (fixes both) but I don't know if we are aiming for
> something better, no good including the whole "diagnostic.h"?!?
> 
> Index: tree-cfg.c
> ===================================================================
> --- tree-cfg.c    (revision 180119)
> +++ tree-cfg.c    (working copy)
> @@ -37,7 +37,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "timevar.h"
>  #include "tree-dump.h"
>  #include "tree-pass.h"
> -#include "diagnostic-core.h"
> +#include "diagnostic.h"
>  #include "except.h"
>  #include "cfgloop.h"
>  #include "cfglayout.h"
> @@ -7380,7 +7380,8 @@ execute_warn_function_return (void)
>    else if (warn_return_type
>         && !TREE_NO_WARNING (cfun->decl)
>         && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0
> -       && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
> +       && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl)))
> +       && !errorcount)
>      {
>        FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
>      {

I don't think that's good.  You'll miss the warning for subsequent
functions that do not have errors for example.

Either we want to generally supress all warnings once we emitted
an error (then this should be done in generic diagnostic machinery),
or we shouldn't bother with this.  We can make the generic machinery
track errors per function if we like to.
Comment 6 Paolo Carlini 2011-10-18 09:41:11 UTC
Indeed, after a day of work I should not even try sending drafts. Anyway, the substantive point I was missing is *per function*.

Is there a simple explanation for why the problem didn't show up in 4.4.x?
Comment 7 Manuel López-Ibáñez 2011-10-18 15:42:42 UTC
> Is there a simple explanation for why the problem didn't show up in 4.4.x?

The question is why control does not reach the warning() when -Werror is not given. Are the warnings appropriate or bogus?

If the warnings are bogus (because they refer to the same function), then I guess that the code path for warnings_as_error does not set TREE_NO_WARNING() at some point.
Comment 8 Paolo Carlini 2011-10-18 16:02:26 UTC
Thanks Manuel: if I understand correctly, this way we could not only avoid the regression but even do better than 4.4, and again, the fix could be very simple (is only hiding itself very well ;) I'll see what I can do.
Comment 9 Paolo Carlini 2011-10-18 16:08:02 UTC
Note however that the bug I closed as duplicate of this one shows that in some cases the problem manifests itself as *bogus* warning.. But I'm pretty sure the issue ultimately  is one and only.
Comment 10 Manuel López-Ibáñez 2011-10-18 20:22:52 UTC
The gimple generated with -Wreturn-type and with -Werror=return-type is even different. At least at revision 164549.

*** pr48087.cc.004t.gimple-Wreturn-type 2011-10-18 22:17:16.000000000 +0200
--- pr48087.cc.004t.gimple-Werror-return-type   2011-10-18 22:17:56.000000000 +0200
***************
*** 91,127 ****
        [/home/manuel/pr48087.cc : 28:28] # USE = anything 
        # CLB = anything 
        _ZN4BetaC1EvD.2093 ([/home/manuel/pr48087.cc : 28] &D.2139);
!       [/home/manuel/pr48087.cc : 28:28] try
!         {
!           [/home/manuel/pr48087.cc : 28:28] # USE = anything 
!           # CLB = anything 
!           b2D.2138 = _ZN4Beta5valueEvD.2091 ([/home/manuel/pr48087.cc : 28] &D.2139);
!         }
!       finally
!         {
!           [/home/manuel/pr48087.cc : 28:20] # USE = anything 
!           # CLB = anything 
!           __comp_dtor D.2097 ([/home/manuel/pr48087.cc : 28] &D.2139);
!         }
        [/home/manuel/pr48087.cc : 29:24] # USE = anything 
        # CLB = anything 
        _ZN4BetaC1EvD.2093 ([/home/manuel/pr48087.cc : 29] &D.2140);
!       [/home/manuel/pr48087.cc : 29:26] try
!         {
!           [/home/manuel/pr48087.cc : 29:24] # USE = anything 
!           # CLB = anything 
!           D.2168 = _ZN4Beta5valueEvD.2091 ([/home/manuel/pr48087.cc : 29] &D.2140);
!           [/home/manuel/pr48087.cc : 29:25] D.2169 = (intD.2) D.2168;
!           [/home/manuel/pr48087.cc : 29:26] # USE = anything 
!           # CLB = anything 
!           _Z5GammabD.2109 (D.2169);
!         }
!       finally
!         {
!           [/home/manuel/pr48087.cc : 29:16] # USE = anything 
!           # CLB = anything 
!           __comp_dtor D.2097 ([/home/manuel/pr48087.cc : 29] &D.2140);
!         }
      }
    }
  }
--- 91,109 ----
        [/home/manuel/pr48087.cc : 28:28] # USE = anything 
        # CLB = anything 
        _ZN4BetaC1EvD.2093 ([/home/manuel/pr48087.cc : 28] &D.2139);
!       [/home/manuel/pr48087.cc : 28:28] # USE = anything 
!       # CLB = anything 
!       b2D.2138 = _ZN4Beta5valueEvD.2091 ([/home/manuel/pr48087.cc : 28] &D.2139);
        [/home/manuel/pr48087.cc : 29:24] # USE = anything 
        # CLB = anything 
        _ZN4BetaC1EvD.2093 ([/home/manuel/pr48087.cc : 29] &D.2140);
!       [/home/manuel/pr48087.cc : 29:24] # USE = anything 
!       # CLB = anything 
!       D.2168 = _ZN4Beta5valueEvD.2091 ([/home/manuel/pr48087.cc : 29] &D.2140);
!       [/home/manuel/pr48087.cc : 29:25] D.2169 = (intD.2) D.2168;
!       [/home/manuel/pr48087.cc : 29:26] # USE = anything 
!       # CLB = anything 
!       _Z5GammabD.2109 (D.2169);
      }
    }
  }
***************
*** 130,136 ****
  bool DeltaOne(bool) (boolD.2002 bD.2111)
  [/home/manuel/pr48087.cc : 21:12] {
    struct BetaD.2084 D.2134;
!   intD.2 D.2173;
    struct AlphaD.2063 sD.2114;
    boolD.2002 b2D.2124;
  
--- 112,118 ----
  bool DeltaOne(bool) (boolD.2002 bD.2111)
  [/home/manuel/pr48087.cc : 21:12] {
    struct BetaD.2084 D.2134;
!   intD.2 D.2171;
    struct AlphaD.2063 sD.2114;
    boolD.2002 b2D.2124;
  
***************
*** 142,163 ****
        [/home/manuel/pr48087.cc : 20:26] # USE = anything 
        # CLB = anything 
        _ZN4BetaC1EvD.2093 ([/home/manuel/pr48087.cc : 20] &D.2134);
!       [/home/manuel/pr48087.cc : 20:26] try
!         {
!           [/home/manuel/pr48087.cc : 20:26] # USE = anything 
!           # CLB = anything 
!           b2D.2124 = _ZN4Beta5valueEvD.2091 ([/home/manuel/pr48087.cc : 20] &D.2134);
!         }
!       finally
!         {
!           [/home/manuel/pr48087.cc : 20:18] # USE = anything 
!           # CLB = anything 
!           __comp_dtor D.2097 ([/home/manuel/pr48087.cc : 20] &D.2134);
!         }
!       [/home/manuel/pr48087.cc : 21:11] D.2173 = (intD.2) b2D.2124;
        [/home/manuel/pr48087.cc : 21:12] # USE = anything 
        # CLB = anything 
!       _Z5GammabD.2109 (D.2173);
      }
    finally
      {
--- 124,136 ----
        [/home/manuel/pr48087.cc : 20:26] # USE = anything 
        # CLB = anything 
        _ZN4BetaC1EvD.2093 ([/home/manuel/pr48087.cc : 20] &D.2134);
!       [/home/manuel/pr48087.cc : 20:26] # USE = anything 
!       # CLB = anything 
!       b2D.2124 = _ZN4Beta5valueEvD.2091 ([/home/manuel/pr48087.cc : 20] &D.2134);
!       [/home/manuel/pr48087.cc : 21:11] D.2171 = (intD.2) b2D.2124;
        [/home/manuel/pr48087.cc : 21:12] # USE = anything 
        # CLB = anything 
!       _Z5GammabD.2109 (D.2171);
      }
    finally
      {
Comment 11 Paolo Carlini 2011-10-18 23:42:43 UTC
Manuel, we need you help for some of these nasty diagnostic issues.
Comment 12 Manuel López-Ibáñez 2011-10-19 01:44:12 UTC
I think the problem is the seen_error() test in gimple_push_cleanup. I am guessing that it does some kind of "folding" that is skipped when an error has been issued. There are two issues here:

1) Warnings converted to errors are not real errors, that is, the program is still valid and we could in principle do whatever stuff we would do for a valid program. We could do s/seen_error/seen_any_error/, and then add seen_real_error (program_is_invalid). I bet most of the cases using seen_any_error, actually mean program_is_invalid.

2) Whether even with real errors, we can fix the gimple generated by C++ to not trigger the Wreturn-type warning. Or alternatively, make Wreturn-type more intelligent to not emit a bogus warning here. The point here is that it is perhaps possible to generate such a gimple from C++ that causes a bogus warning. Currently, gimplify_push_cleanup "fixes" the bad gimple to avoid the warning, but perhaps in other testcases, this "fix" doesn't trigger and we get a bogus warning.

The thing is that even if we fix 1, we could probably trigger a real error earlier and we end up with 2 (no inconsistency, but still bogus warning).
Comment 13 rguenther@suse.de 2011-10-19 07:48:30 UTC
On Wed, 19 Oct 2011, manu at gcc dot gnu.org wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48087
> 
> --- Comment #12 from Manuel López-Ibáñez <manu at gcc dot gnu.org> 2011-10-19 01:44:12 UTC ---
> I think the problem is the seen_error() test in gimple_push_cleanup. I am
> guessing that it does some kind of "folding" that is skipped when an error has
> been issued. There are two issues here:
> 
> 1) Warnings converted to errors are not real errors, that is, the program is
> still valid and we could in principle do whatever stuff we would do for a valid
> program. We could do s/seen_error/seen_any_error/, and then add seen_real_error
> (program_is_invalid). I bet most of the cases using seen_any_error, actually
> mean program_is_invalid.

I suppose that's reasonable.
Comment 14 Paolo Carlini 2011-10-19 15:39:08 UTC
Thanks for explaining the seen_error mechanism, which I didn't know, but there is something I still don't understand here. Consider PR49508 (I'm interested because I opened it ;) : in that case we have only real errors, and then a bugus warning. I don't see how fiddling with something at beginning of gimple_push_cleanup could deal with such cases, and indeed if I hack it to remove the early return, the warning triggers exactly in the same way. Or maybe all this just indicated that  PR49508 really is a different issue, but I'm not convinced...
Comment 15 Paolo Carlini 2011-10-19 15:53:01 UTC
On this PR, removing the early return *works*, we have two non-bogus warnings with -Wall and two errors with -Werror. Maybe we should really proceed one PR at a time, re-open PR49508.

Now, in detail: do I understand correctly that you are proposing we would use the new seen_real_errors *only* in gimple_push_cleanup? (at the moment I also honestly don't know how to tell errors from warnings from real errors, but of course can figure out myself)
Comment 16 Manuel López-Ibáñez 2011-10-19 17:21:51 UTC
(In reply to comment #15)
> On this PR, removing the early return *works*, we have two non-bogus warnings
> with -Wall and two errors with -Werror. Maybe we should really proceed one PR
> at a time, re-open PR49508.

I agree. This is what I meant by (2) above. That the bogus warnings are somehow hidden by gimple_push_cleanup, but it would be better to figure what  gimple_push_clenaup is fixing and see whether it is possible to avoid generating it in the first place. If it is the same issue as PR49508, then fixing (1) is not enough.

> Now, in detail: do I understand correctly that you are proposing we would use
> the new seen_real_errors *only* in gimple_push_cleanup? (at the moment I also
> honestly don't know how to tell errors from warnings from real errors, but of
> course can figure out myself)

I would search where the counters are defined and add a new one for real_errors. Then, for warnings converted to errors, do not increase the new one. This should be a one-liner in diagnostic_report_diagnostic. Search for diagnostic_kind_count. This would maintain seen_error working as it is now, but one can define program_is_valid_p (or seen_real_error).
Comment 17 Paolo Carlini 2011-10-19 17:27:36 UTC
Yeah, I was driving and it occurred to me too that we gonna need one more counter... First, let's reopen the other bug. Thanks again for now.
Comment 18 Paolo Carlini 2011-10-27 10:20:29 UTC
Richard, the idea of adding another counter (per Comment #16) sounds good to you? If we do that, the fix should be rather straightforward.
Comment 19 rguenther@suse.de 2011-10-27 10:26:02 UTC
On Thu, 27 Oct 2011, paolo.carlini at oracle dot com wrote:

> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48087
> 
> --- Comment #18 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-10-27 10:20:29 UTC ---
> Richard, the idea of adding another counter (per Comment #16) sounds good to
> you? If we do that, the fix should be rather straightforward.

I didn't investigate thorougly enough to give good advise here.
Comment 20 Richard Biener 2011-12-06 10:09:20 UTC
Looking again, I think that for warnings promoted to errors we should _not_
increase errorcount, but we should instead have a new global flag that
tells us whether there were any "real" errors, and check that in the
place that terminates compilation without producing assembler output.
Comment 21 Richard Biener 2012-07-02 12:21:47 UTC
The 4.5 branch is being closed, adjusting target milestone.
Comment 22 Jakub Jelinek 2013-01-15 15:11:40 UTC
Created attachment 29170 [details]
gcc48-pr48087.patch

Untested fix.  That said, it seems that on the provided testcase g++ already generates the same set of warnings/errors for -Wreturn-type vs. -Werror=return-type, starting with
http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=186687
so supposedly you'd need to find a different testcase for this to still claim 4.8 Regression status.

Not sure if this can be stage4 material, I think it is more stage1-ish material.
Comment 23 Manuel López-Ibáñez 2013-01-15 16:39:22 UTC
(In reply to comment #22)
> Created attachment 29170 [details]
> gcc48-pr48087.patch
> 
> Untested fix.  That said, it seems that on the provided testcase g++ already
> generates the same set of warnings/errors for -Wreturn-type vs.
> -Werror=return-type, starting with
> http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=186687
> so supposedly you'd need to find a different testcase for this to still claim
> 4.8 Regression status.
> 
> Not sure if this can be stage4 material, I think it is more stage1-ish
> material.

I think this hunk is not correct: 

--- gcc/cp/typeck.c.jj	2013-01-11 09:02:46.000000000 +0100
+++ gcc/cp/typeck.c	2013-01-15 15:35:47.216641020 +0100
@@ -7967,11 +7967,11 @@ convert_for_initialization (tree exp, tr
       int savew = 0, savee = 0;
 
       if (fndecl)
-	savew = warningcount, savee = errorcount;
+	savew = warningcount + werrorcount, savee = errorcount;
       rhs = initialize_reference (type, rhs, flags, complain);
       if (fndecl)
 	{
-	  if (warningcount > savew)
+	  if (warningcount + werrorcount > savew)
 	    warning (0, "in passing argument %P of %q+D", parmnum, fndecl);
 	  else if (errorcount > savee)
 	    error ("in passing argument %P of %q+D", parmnum, fndecl);

since it will print:

error: something
warning: in passing argument

I think this should simply be an inform note like it is done in other cases (in your own patch in gcc/cp/pt.c). 

This hunk also seems suspicious:

--- gcc/cp/call.c.jj	2013-01-11 09:02:46.000000000 +0100
+++ gcc/cp/call.c	2013-01-15 15:34:21.267155075 +0100
@@ -5709,12 +5709,12 @@ build_temp (tree expr, tree type, int fl
   int savew, savee;
   vec<tree, va_gc> *args;
 
-  savew = warningcount, savee = errorcount;
+  savew = warningcount + werrorcount, savee = errorcount;
   args = make_tree_vector_single (expr);
   expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 				    &args, type, flags, complain);
   release_tree_vector (args);
-  if (warningcount > savew)
+  if (warningcount + werrorcount > savew)
     *diagnostic_kind = DK_WARNING;
   else if (errorcount > savee)
     *diagnostic_kind = DK_ERROR;

I am not sure what for *diagnostic_kind is used, but it seems to change the current behaviour (since a Werror will result in  *diagnostic_kind = DK_ERROR before your patch).
Comment 24 Jakub Jelinek 2013-03-21 20:02:55 UTC
Author: jakub
Date: Thu Mar 21 17:36:47 2013
New Revision: 196887

URL: http://gcc.gnu.org/viewcvs?rev=196887&root=gcc&view=rev
Log:
	PR middle-end/48087
	* diagnostic.def (DK_WERROR): New kind.
	* diagnostic.h (werrorcount): Define.
	* diagnostic.c (diagnostic_report_diagnostic): For DK_WARNING
	promoted to DK_ERROR, increment DK_WERROR counter instead of
	DK_ERROR counter.
	* toplev.c (toplev_main): Call print_ignored_options even if
	just werrorcount is non-zero.  Exit with FATAL_EXIT_CODE
	even if just werrorcount is non-zero.

	* pt.c (convert_nontype_argument): Count werrorcount as warnings.
	* call.c (build_temp): Likewise.
	* method.c (synthesize_method): Likewise.
	* typeck.c (convert_for_initialization): Likewise.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/method.c
    trunk/gcc/cp/pt.c
    trunk/gcc/cp/typeck.c
    trunk/gcc/diagnostic.c
    trunk/gcc/diagnostic.def
    trunk/gcc/diagnostic.h
    trunk/gcc/toplev.c
Comment 25 Jakub Jelinek 2013-04-12 15:17:13 UTC
GCC 4.6.4 has been released and the branch has been closed.
Comment 26 Jeffrey A. Law 2014-01-23 07:21:26 UTC
Fixed long ago on the trunk.