Failing to include the volatile keyword when declaring access to a volatile memory location or IO device is a bug in your code; even if the bug is only evident when your code gets optimized.
Your compiler will document any "unsafe" optimizations where it documents the command-line switches and pragmas that turn them on and off. Unsafe optimizations usually related to assumptions about floating point math (rounding, edge cases like NAN) or aliasing as others have already mentioned.
Constant folding can create aliasing making bugs in your code appear. So, for example, if you have code like:
static char *caBuffer = " ";
...
strcpy(caBuffer,...)
Your code is basically an error where you scribble over a constant (literal). Without constant folding, the error won't really effect anything. But much like the volatile bug you mentioned, when your compiler folds constants to save space, you might scribble over another literal like the spaces in:
printf("%s%s%s",cpName," ",cpDescription);
because the compiler might point the literal argument to the printf call at the last 4 characters of the literal used to initialize caBuffer.