Mark McIntyre said:
We can agree that the value is indeterminate from 6.2.4 (5) and 6.7.8
(10).
We can agree that indeterminate values include traps from 3.17.2(1)
We can agree that undefined behaviour is "behavior, upon use of a
nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements" from
3.4.3 (1)
I assert that the value of something indeterminate is nonportable,
since what is a trap on one implementation could be valid on another.
I therefore assert that using an indeterminate value is nonportable,
and since the standard places no requirements on this action, its
undefined.
QED?
Behaviour is only undefined if it's not defined, and defined includes
implementation-defined.
A conforming implementation can define any behaviour it likes, within areas
not defined by the standard.
Therefore, it's never possible to say that any code _always_ produces
undefined behaviour.
Therefore, when we say that code produces undefined behaviour, without
reference to platform, we can't mean "always". We can only mean that it
_may_ produce undefined behaviour, and is therefore non-portable and not
strictly conforming. However, that doesn't mean there's nothing more to be
said.
For example, it's implementation-defined whether plain char is signed or
unsigned. Either way, the requirements of the standard still apply. Maybe,
your code's behaviour is fully defined on an "unsigned" platform, but on a
"signed" platform, as a knock-on consequence, there are further
implementation-defined issues, and ultimately (and perhaps only for certain
inputs) you may run out of definitions of behaviour, and end up with UB.
In that case, the code is non-portable, and it would be true in a sense to
say that the code produces UB. But it's not really a relevant point unless
the portability of the code is the issue. There's still the question of how
the code behaves on the platforms that make saner choices, or on the inputs
where the behaviour is guaranteed anyway, and there the standard still
applies.
The compiler can't say "well I've documented this particular scheme (for
some issue where I'm required to), but some other compiler could have done
it differently, therefore I'm a free agent, call for the nasal demons."
(Otherwise, there wouldn't be any distinction between
"implementation-defined" and undefined)
Same here. Representations of integer types are implementation-defined, so
it's implementation-defined whether an int may contain a trap
representation, i.e a bit pattern that corresponds to no value. So code
which accesses an uninitialized int is strictly non-portable, even if we
suppress the variable outputs, in the sense that a conforming implementation
could be created which could document that certain bit patterns for an int
correspond to no value and that accessing such a bit pattern may have some
(defined or undefined) observable outcome (which therefore might be
different from what could happen on a different implementation).
But if the implementation says there are no int traps, then there's no UB --
until we get to the overflow issue, where similar considerations apply
again. An implementation could say that a trap representation is generated,
in which case the standard says UB, and then the implementation need say no
more, so UB it is. Or the implementation might say silent wrap-round to a
valid value, in which case the standard continues to impose requirements on
the subsequent behaviour.