It is well known that in each of the C and C++ standards there were "blind spots" that did not describe certain cases in well-formed programs. It is obvious that in non-formal descriptions of such complex formal systems it is impossible to notice everything in advance.
Because of this, there is an established procedure for correcting and interpreting a standard until a new revision ("edition") is issued. Let's consider this using the simplest and chronologically first example - the C90 standard (ISO/IEC 9899:1990), which has now been officially withdrawn.
The following types of documents were issued for it, in order of decreasing importance:
ISO Technical Corrigendum (TC)
In fact, these are a kind of "patches" that are applied directly to the existing standard and have retroactive effect. In reality, this means that all previously compliant implementations that had interpreted vague parts of the standard in their own way become non-compliant if these places turn out to be clarified in some other way by new documents.
For C90, two such documents were released: TC-1:1994 and TC-2:1996.
ISO Amendment (Amd), aka ISO Normative Addendum (NA)
Quite similar in effect to TC and has effectively the same impact, but may limit their retroactive effect through some mechanism - e.g. by introducing a new value of __STDC_VERSION__
.
Typically, ISO Amendments are significant and large, so they are issued pretty rarely. But for the C90 one was released anyway - Amd-1:1995.
WG14 Defect Report (DR), aka Clarification Request
These are letters to the Standardization Committee with a request to clarify certain controversial passages in the standard, as well as to draw attention to various kinds of shortcomings in it. Committee addresses them, publicly expressing its collective opinion, which may end up in officially approved document (TC, NA or even the Standard itself).
However, Defect Reports themselves are not official documents and therefore do not have mandatory retroactive effect. Nevertheless, implementers and ordinary developers can rely on them to avoid the fate of non-conformance in the future or at least reduce the likelihood of its occurrence.
For the C90 standard, including all the above-mentioned additions, 178 reports were processed, the lists of which are available on the official website of the committee:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr.htm
https://www.open-std.org/jtc1/sc22/wg14/www/docs/c90_drs.html
Since the standards do not provide reference (model) implementations neither for the compiler nor for the standard library, this creates a need for their constant clarification and editing. Not all implementers may be interested in supporting new standards in their entirety and not all developers want to rewrite the old code they maintain - this is a fact of life and business. But it is also clear that TC and DR cannot be issued for older standards infinitely.
Thus, the following questions arise:
How to treat underspecified behaviour that is not explicitly stated as either implementation-defined, unspecified or even undefined?
Should newer standards be referred to in such cases?
Should a Defect Report be filed for a withdrawn standard?
Please note that I'm not just talking about compiler and standard library programmers, but also regular code writers.
See also:
How do the C and C++ standards tell you to deal with situations that are not covered by them?
The language specifications explain how conforming implementations of their respective languages behave. They say nothing about how you should behave.
- How to treat underspecified behaviour that is not explicitly stated as either implementation-defined, unspecified or even undefined?
The spec does not have to explicitly say that behavior is undefined. C in particular defines "undefined behavior" this way:
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
(C17 3.4.3/1).
All versions of the C language specification have this or very similar wording, and I'm pretty sure the same goes for C++.
As for how to treat it, you are safest avoiding it. Or for "unspecified" or "implementation defined" behavior, you may be able to ignore it safely if all of the alternatives allowed by the spec are acceptable to you.
Alternatively, if you are specifically targeting an implementation that does define the behavior in question (whether or not the applicable spec makes it "implementation defined"), and you are not concerned about portability to other implementations, then you can rely on your implementation's documentation.
- Should newer standards be used in such cases?
It does not make sense to rely on documentation that does not apply to the implementation you are actually using. It is not safe or reasonable to assume that behavior defined only by a later version of the spec will be manifested by implementations of (only) an earlier version of the spec.
You could, however, consider switching to an implementation of a more recent specification. See also above.
- Should a Defect Report be filed for a withdrawn standard?
That seems unlikely to be useful. You should understand withdrawl of (a version of) a standard to imply that it will not be further maintained.
In the case of the C and C++ language specifications, if your issue is resolved in a more recent version of the spec then the committee will surely consider that to have adequately addressed it. If not, then you could consider filing a DR against the current version, with the understanding that any fix will be targeted at that or a future version of the spec.