I am curious about the liberties that a compiler has when optimizing. Let's limit this question to GCC and C/C++ (any version, any flavour of standard):
Is it possible to write code which behaves differently depending on which optimization level it was compiled with?
The example I have in mind is printing different bits of text in various constructors in C++ and getting a difference depending on whether copies are elided (though I've not been able to make such a thing work).
Counting clock cycles is not permitted. If you have an example for a non-GCC compiler, I'd be curious, too, but I can't check it. Bonus points for an example in C. :-)
Edit: The example code should be standard compliant and not contain undefined behaviour from the outset.
Edit 2: Got some great answers already! Let me up the stakes a bit: The code must constitute a well-formed program and be standards-compliant, and it must compile to correct, deterministic programs in every optimization level. (That excludes things like race-conditions in ill-formed multithreaded code.) Also I appreciate that floating point rounding may be affected, but let's discount that.
I just hit 800 reputation, so I think I shall blow 50 reputation as bounty on the first complete example to conform to (the spirit) of those conditions; 25 if it involves abusing strict aliasing. (Subject to someone showing me how to send bounty to someone else.)
man
to the rescue, yes you can, with-fno-elide-constructors
. Assuming that you permit such a fine-grained option as a "different optimization level", I think that fits your requirements. – Bothersomeset<double>
crash? I mean, I know that you cannot compare doubles by binary identity when you make computations, but when you just use them as a write-once-read-many key, what's the problem? – Ultimatelystd::set
implementation didn't anticipate. I'm not sure this is standard-compliant, mind, but PlasmaHH is talking about reality differing from the standard, i.e. a bug, so anything goes really :-) – Bothersome<
is not necessarily a strict weak order ondouble
, because0 < NaN
andNaN < 1
are both false, but1 < 0
is also false. Or to put it another way,!(X < Y) && !(Y < X)
is not an equivalence relation because it's not transitive for NaNs. Soset<double>
can crash if NaNs get involved even if it's bug-free. – Bothersome