https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113028

            Bug ID: 113028
           Summary: GCC diagnostic pop changes errors to warnings
           Product: gcc
           Version: 10.1.0
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dustbingtb at verizon dot net
  Target Milestone: ---
            Target: x86_64-linux-gnu

While debugging compile errors in open-source code after upgrading gcc from
9.x, I ran into this problem with GCC diagnostic push/ignored/pop. It seems
similar to old/resolved Bug 66098/Bug 66711, except it doesn't involve any
-Werror command-line option; in fact, it can be reproduced with just "g++
testfile.cpp". This diagnostic error was added in gcc 10.x, so the specific
example isn't meaningful prior to that; however, the problem persists through
gcc 13.2 and trunk, as per godbolt.

The following code easily demonstrates all the investigative cases just by
modifying the value of TEST_CASE:
- TEST_CASE 0 shows two "error: narrowing conversion of '-2023406815' from
'int' to 'unsigned int' [-Wnarrowing]", which is apparently a correct error
diagnostic that should have been reported by earlier gcc but wasn't (at least,
earlier clang has reported this diagnostic error since at least 2012, and
handles the push/pop properly since then also, BTW).
- TEST_CASE 1 just demonstrates that, when the first error's code is removed
from compilation, the second error still fires as expected (contrast with
behavior of TEST_CASE 3).
- TEST_CASE 2 uses GCC diagnostic ignored "-Wnarrowing" to disable both errors,
which works.
- TEST_CASE 3: the bug. GCC diagnostic push/ignored suppress the first error,
but pop does NOT restore the second error; instead, the second error
mysteriously becomes a warning instead!

// 0: two errors; 1: one (2nd) error; 2: both ignored; 3: 1st ignored 2nd
warns!
#define TEST_CASE 3

int main(int argc, char *argv[])
{
    const int HEX_CONST = (int)0x87654321L;

  #if TEST_CASE == 3
    _Pragma("GCC diagnostic push")
  #endif
  #if TEST_CASE >= 2
    _Pragma("GCC diagnostic ignored \"-Wnarrowing\"")
  #endif
    unsigned uval = (unsigned)argc;
  #if TEST_CASE != 1
    switch (uval)
    {
        case HEX_CONST: ++uval;
        default: break;
    }
  #endif  // TEST_CASE != 1

  #if TEST_CASE == 3
    _Pragma("GCC diagnostic pop")
  #endif
    switch (--uval)
    {
        case HEX_CONST: return 0;
        default: return 1;
    }
}

Reply via email to