Bug 136120

Summary: g++ generates incorrect code for aliased pointer assignments in c++
Product: [Fedora] Fedora Reporter: Dr Thomas Conway <drtomc>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 3CC: jason, oliva
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-10-18 08:44:16 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Dr Thomas Conway 2004-10-18 02:09:14 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3)
Gecko/20040929

Description of problem:
The following program should produce no output.

When compiled:
    g++ -O1 -o bug bug.cc
it behaves correctly.
When compiled:
    g++ -O1 -fstrict-aliasing -fschedule-insns -o bug bug.cc
or
    g++ -O2 -o bug bug.cc
it produces output.

See the comments in the text of the program for more detail.

$ cat bug.cc
#include <iostream>

struct Key
{
    long key;
    long ordering;

    Key() : key(0), ordering(0) {}
};

int
main(int argc, const char* argv[])
{
    long* ordering = new long[100];

    for (int i = 0; i < 100; ++i)
    {
        ordering[i] = i;
    }

    Key* keys = new Key[100];

    // We *reuse* the ordering array as an array of key pointers.
    Key** perm = reinterpret_cast<Key**>(ordering);

    int base = 0;
    for (int k = 0; k < 1; ++k)
    {
        int n = &ordering[100] - &ordering[0];
        for (int i = 0; i < 100; ++i)
        {
            // XXX When compiled with -O2 or
            // -O1 -fstrict-aliasing -fschedule-insns
            // these two statements appear to be reversed!

            // copy the ordering value into the key
            keys[i + base].ordering = ordering[i];
            // copy the address of the key over the ordering value
            perm[i] = &keys[i + base];
        }
        base += n;
    }

    // Check the ordering values.
    // If the compiler gets it right, there should be no output.
    for (int i = 0; i < 100; ++i)
    {
        if (keys[i].ordering != i)
        {
            std::cerr << "keys[" << i << "].ordering == " <<
keys[i].ordering
                      << std::endl;
        }
    }

    delete [] keys;
    delete [] ordering;

    return 0;
}



Version-Release number of selected component (if applicable):
gcc-3.4.2-2

How reproducible:
Always

Steps to Reproduce:
see above.

Additional info:

this bug, like all code generator bugs is worrying because it can
be hard to know if you're triggering it or not. Your program *might*
work. Fortunately it seems you can work around it by adding
-fno-strict-aliasing to the compiler arguments, though this does
result in the loss of some legitimate optimization of course.

Comment 1 Jakub Jelinek 2004-10-18 08:44:16 UTC
The reinterpret_cast is exactly what you shouldn't be doing, see
info gcc on -fstrict-aliasing, at least IMHO.

ISO C++, 3.10#15 says:
If a program attempts to access the stored value of an object through an
lvalue of other than one of the following types the behaviour is undefined:
- the dynamic type of the object,
- a cv-qualified version of the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to the dynamic
  type of the object,
- a type that is the signed or unsigned type corresponding to a cv-qualified
  version of the dynamic type of the object,
- an aggregate or union type that includes one of the aforementioned types
  among its members (including, recursively, a member of a subaggregate or
  contained union)
- a type that is a (possibly cv-qualified) base class type of the dynamic
  type of the object,
- a char or unsigned char type

The dynamic type of the object keys[i] is Key, and long certainly is not
one of the types mentioned above, so IMHO what you are seeing is perfectly
fine behaviour.