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

            Bug ID: 85091
           Summary: Compiler generates different code depending on whether
                    -Wnonnull -Woverloaded-virtual given or not
           Product: gcc
           Version: 7.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vz-gcc at zeitlins dot org
  Target Milestone: ---

Created attachment 43767
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43767&action=edit
Minimal test case reduced by delta

This is a completely impossible bug which is nevertheless observed when using
i686-w64-mingw32-c++ from Debian Buster (gcc version 7.2-win32 20180123): the
compiler produces different (and wrong) object code/assembly when using -O2
depending on whether *both* of "-Wnonnull -Woverloaded-virtual" options are
used or not (i.e. the same code is produced if none of them is given, if only
-Wnonnull is used or if only -Woverloaded-virtual is used, but the generated
code changes if both of them are used at once). Moreover, the generated code
may even change depending on the name of the input file on the command line:
the attached test case was produced by delta program and was originally called
tmp1/16795.cpp and running

i686-w64-mingw32-g++ -c -std=c++17 -Wnonnull -Woverloaded-virtual -O2
tmp1/16795.cpp

produced correct code (i.e. the same as without the warning options), while
simply moving it to the current directory and running

i686-w64-mingw32-g++ -c -std=c++17 -Wnonnull -Woverloaded-virtual -O2 16795.cpp

produces wrong code.

To reproduce the problem, the same test script as used with delta can be used:

#!/bin/sh
i686-w64-mingw32-g++ -c -std=c++17 -Wnonnull -Woverloaded-virtual -O2 $1 -o  
warn.o 2>/dev/null & pid1=$!
i686-w64-mingw32-g++ -c -std=c++17                                -O2 $1 -o
nowarn.o 2>/dev/null & pid2=$!

if ! wait $pid1 || ! wait $pid2 ; then
    exit 1
fi

if [ $(wc -c < warn.o) -eq $(wc -c < nowarn.o) ]; then
    exit 2
fi

exit 0

(also attached). Running it on 16795.cpp shows that, without the warning
options, compiler generates the (expected, as everything is optimized out)
trivial body of test_main:

    xor %eax, %eax
    ret

while with the warning options it generates the following nonsensical
instructions:

    lock addl $0x1,0x4c
    ret

Also notice that this is really the minimal test case, removing any lines, even
clearly unused ones such as declarations of never called functions, makes the
problem disappear. For the same reason, this file can be only compiled, not
linked: adding definitions of various functions used in it makes the problem
disappear as well. However the original program, before the reduction, can, of
course, be linked, and running it after compiling this file with and without
the warning options produces different results at run-time.

Please see this thread for more context:
https://gcc.gnu.org/ml/gcc-help/2018-03/msg00077.html

Reply via email to