Bug 36742 - [4.2 Regression] g++ -O2 produces wrong code
Summary: [4.2 Regression] g++ -O2 produces wrong code
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.2.2
: P3 normal
Target Milestone: 4.3.0
Assignee: Not yet assigned to anyone
Keywords: alias, wrong-code
Depends on:
Reported: 2008-07-06 11:19 UTC by Mike Jarvis
Modified: 2009-03-31 15:44 UTC (History)
3 users (show)

See Also:
Target: i686-apple-darwin9
Known to work: 4.1.2 4.0.2 4.0.1 3.4.6 4.3.0
Known to fail: 4.2.2 4.2.4 4.2.5
Last reconfirmed: 2008-07-11 21:21:42

preprocessed source code (91.93 KB, text/plain)
2008-07-06 11:31 UTC, Mike Jarvis

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Jarvis 2008-07-06 11:19:37 UTC
The following code produces correct output with g++ -O, but wrong output with g++ -O2:
The basic calculation should be just a product of two complex numbers, each equal to (1,1), so the output should be (and is with g++ -O):

a = (0,2)

However, on my system, the output with the -O2 flag is:

a = (-1.22015e-313,1.22015e-313)

Furthermore, any one of the following changes "fixes" the problem:

Any one of the following changes "fix" the problem:

- Removing either Assert statement in foo
- Removing the imag(b.val) branch in foo
- Removing the trigraph in foo
- Removing s2 from Error
- Removing base class of A
- Removing junk from A

Here is the code:

#include <iostream>
#include <complex>
#include <string>

class B
    virtual size_t one() const = 0;
    virtual ~B() {}

class A : public B

    A(std::complex<double> _val) : itsval(_val), junk(1) {}
    ~A() {}

    std::complex<double>& val() { return itsval; }
    size_t one() const { return 1; }

  protected :

    std::complex<double> itsval;
    const size_t junk;

class Error
  public :
    std::string s1, s2;
    inline Error(std::string _s1, std::string _s2="") throw() :
      s1(_s1), s2(_s2) {}
    virtual inline ~Error() throw() {}

#define Assert(x) do { if(!(x)) { throw Error(#x); } } while(false)

void foo(A& a, std::complex<double> b)
  Assert(a.one() == 1);
  Assert(a.one() == 1);

  if (std::imag(b) == double(0))
    a.val() *= std::real(b);
    a.val() *= (true ? b : std::conj(b));

int main()
  A a(std::complex<double>(1,1));
  std::complex<double> b(1,1);

  foo(a, b);
  std::cout<<"a = "<<a.val()<<std::endl;
  //std::cout<<"Should be (0,2)\n";

  return 0;
Comment 1 Mike Jarvis 2008-07-06 11:31:29 UTC
Created attachment 15863 [details]
preprocessed source code
Comment 2 Mike Jarvis 2008-07-06 11:40:29 UTC
Comment on attachment 15863 [details]
preprocessed source code

g++ -v outputs:

Using built-in specs.
Target: i686-apple-darwin9
Configured with: ../gcc-4.2.2/configure --prefix=/sw --prefix=/sw/lib/gcc4.2 --mandir=/sw/share/man --infodir=/sw/share/info --enable-languages=c,c++,fortran,objc,java --with-arch=nocona --with-tune=generic --host=i686-apple-darwin9 --with-gmp=/sw --with-libiconv-prefix=/sw --with-system-zlib --x-includes=/usr/X11R6/include --x-libraries=/usr/X11R6/lib
Thread model: posix
gcc version 4.2.2

My system is a MacBook 2.2 GHz Intel Core 2 Duo running MaxOsX 10.5.4

I am using the fink installation of gcc.
Comment 3 Richard Biener 2008-07-06 13:40:43 UTC
Confirmed.  Works with gcc 4.3.  Aliasing problem, -O2 -fno-strict-aliasing works.
So eventually a libstdc++ issue?
Comment 4 Paolo Carlini 2008-07-06 14:14:42 UTC
You can categorize as libstdc++, but I'm afraid nobody is going to do much, for many reasons: nothing substantive changed, possibly affecting the aliasing, in <complex> and <string>; the but cannot be reproduced with current 4_3-branch and mainline. At least please provide a reduced testcase pointing to the libstdc++ lines at fault.
Comment 5 Benjamin Kosnik 2008-07-11 20:56:00 UTC
Isn't this the kind of thing that -Wstrict-aliasing or -Wstrict-aliasing=n should warn about?

I will start to experiment with this, in the thought that we should not actually have stuff in the library with aliasing problems.

Not expecting to fix this on the 4.2.x branch though, but if we find issues that can be fixed on trunk/4.3.x, may consider doing so. 
Comment 6 Paolo Carlini 2008-07-11 21:21:42 UTC
(In reply to comment #5)
> Isn't this the kind of thing that -Wstrict-aliasing or -Wstrict-aliasing=n
> should warn about?

Hi Benjamin. My guess is that any possible problem can only have to do with some long standing weaknesses that we have in basic_string and we have big troubles changing without breaking the ABI. Back when #pragma system header didn't work with templates we suppressed a "may" aliasing warning in _S_empty_rep (see comment), and there are chances it may have created actual problems in 4_2-branch, per this PR. Currently, AFAIK, isn't possible to reproduce such problems (Ian committed in 4_3 and mainline very important aliasing-related fixes). 

Anyway, for the record, this patch of mine:


fixes this problem in 4_2-branch, passes abi-check. I think it's safe, I don't think code linking vs the amended library can tell that the exported _S_empty_rep_storage array changed type, because it's the same size and the same alignment. If you can double-check may analysis we could imagine committing it, somewhere.
Comment 7 Joseph S. Myers 2009-03-31 15:44:46 UTC
Closing 4.2 branch, fixed in 4.3.