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 { public: virtual size_t one() const = 0; virtual ~B() {} }; class A : public B { public: 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); else 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; } -- Summary: g++ -O2 produces wrong code Product: gcc Version: 4.2.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: michael at jarvis dot net http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36742