The UK votes NO on CD2/FCD1.
To change the UK vote to YES:
|Column 1||Column 2||Column 3|
|Changes that must be applied||Comments that must be addressed||Other comments|
|1||We do not believe that WG14 addressed the issue actually raised.|
|2||The UK does not consider this to be a a new feature, but a minor though useful enhancement to an existing one.|
|3||Previous objection to this item was based on problems with realloc. Now that the latter has been redefined to create a new object, this item should be reconsidered.|
|4||The UK considers that code affected by this item is almost certain to be erroneous, and feels that it is important that it is addressed.|
|5||This item would clarify the meaning of bit-fields, and in particular that they cannot be wider than specified.|
This response also assumes that the following items of SC22/WG14/N847 have been accepted as is or with editorial changes: 4, 8, 10, 19, 20, 21, 33, 36, 43. Otherwise these items should be added to column 1 of the above table.
WG14 failed to provide comprehensible responses to a number of matters raised in the UK comments to CD1. To the extent that those comments are not subsumed by other parts of this response, they are required to be addressed in a way that allows the UK to determine whether the WG14 responses are acceptable, and therefore form a part of this submission. The UK comments in question are:
|PC-UK0079 PC-UK0082 PC-UK0083 PC-UK0085 PC-UK0086 PC-UK0088 PC-UK0089 PC-UK0090 PC-UK0091 PC-UK0092 PC-UK0093 PC-UK0094 PC-UK0095 PC-UK0096 PC-UK0097 PC-UK0098 PC-UK0102 PC-UK0106 PC-UK0108 PC-UK0112 PC-UK0114 PC-UK0117 PC-UK0118 PC-UK0120 PC-UK0122 PC-UK0126 PC-UK0129 PC-UK0130 PC-UK0133 PC-UK0134 PC-UK0135 PC-UK0137 PC-UK0138 PC-UK0141 PC-UK0142 PC-UK0143 PC-UK0144 PC-UK0147 PC-UK0150 PC-UK0151 PC-UK0152 PC-UK0153 PC-UK0154 PC-UK0155 PC-UK0156 PC-UK0158 PC-UK0159 PC-UK0161 PC-UK0162 PC-UK0163 PC-UK0164 PC-UK0165 PC-UK0171|
The UK requires the issue of side effects in variably-modified type declarations and type names to be addressed. A number of proposals have previously been produced to this end, such as those in PC-UK0226 and PC-UK0250.
The minimum requirement is that, for any given piece of code, the code either violates a constraint, or else all implementations produce the same result (in the absence of any unspecified behaviour in the code not related to the use of variably-modified types). In particular, it is not acceptable for side effects to be optional.
The UK preference is to have side effects work normally in variably-modified types. It would be acceptable for a constraint to forbid certain operators (such as ++ and function call) within array sizes within a sizeof expression.
There are four basic issues to be addressed:
The following changes would address these, though it is accepted that further discussion may be able to improve them. In these changes, new text is in bold and removed text in italics.
In 18.104.22.168, amend paragraph 1 to read:
Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to objects of type T.
Change paragraph 4 to:
During each execution of B, let A be the array object that is determined dynamically by all references through pointer expressions based on P. Then all references to values of A shall be through pointer expressions based on P. Let L(X,B) denote the set of all lvalues that are used to access object X during a particular execution of B. If T is const-qualified, and the address of one lvalue in L(X,B) is based on P, then X shall not be modified during the execution of B. If T is not const-qualified, the address of one lvalue in L(X,B) is based on P, and X is modified during the execution of B, then the addresses of all lvalues in L(X,B) shall be based on P. The requirement in the previous sentence applies recursively, with P in place of X, with each access of X through an lvalue in L(X,B) treated as if it modified the value of P, and with other restricted pointers, associated with B or with other blocks, in place of P. Furthermore, if P is assigned the value of a pointer expression E that is based on another restricted pointer object P2, associated with block B2, then either the execution of B2 shall begin before the execution of B, or the execution of B2 shall end prior to the assignment. If these requirements are not met, then the behavior is undefined.
Alternative wording for the last new sentence ("The requirement ...") is:
If X is modified, the requirement in the previous sentence applies recursively: P is treated as if it were itself modified and replaces X in L(X,B), then the same condition shall apply to other restricted pointers, associated with B or with other blocks, in place of P in the previous sentence.
Finally, WG14 may wish to consider the following additional change (rationale is available separately). In 22.214.171.124 paragraph 6, change:
A declaration of a parameter as "array of type" shall be adjusted to "pointer to type",
A declaration of a parameter as "array of type" shall be adjusted to "restrict-qualified pointer to type",
and add a new paragraph after paragraph 6:
As far as the constraints of restrict-qualification are concerned (126.96.36.199), a parameter that is a complete array type shall be regarded as a pointer to an object of the complete array size; for all other purposes, its type shall be as described above.
The UK comments on CD1 included a large number of comments on CD1 that have not been addressed in the FCD. Discusssions on the reflector indicate that many of the new features in the language are intended to make sense only if Annex F or Annex H are in force. This is not reasonable, not least because it makes the main body of the standard meaningful only in the context of an informative annex.
It is not reasonable to claim that such problems do not matter because they cannot be shown in strictly conforming programs. The same applies to the new features in their entirety, because they are defined only in certain implementation defined cases. And the same applies to almost all error and exception handling, even in C89.
The list of architectures which will have major trouble with the new proposals includes the IBM 360/370/390 (including the Hitachi S-3600 and others), the NEC SX-4, the DEC VAX, the Cray C90 and T90, the Hitachi SR2201, the DEC Alpha (to a certain extent) and almost certainly many others. Implementors on these will interpret the standard in many, varied and incompatible ways, because they CANNOT implement the current wording in any way that makes sense.
For similar reasons, these new features are impossible to use in a portable program, because it is not possible to determine what they mean, unless __STD_IEC_559__ is set. This is not reasonable for features defined in the main body of the standard.
The standard must be improved so that all such arithmetic-dependent features are shielded in some suitable way: by a predefined preprocessor macro, moved to an optional annex, defined so that all reasonable implementations can support them, or defined to permit an implementation to indicate that they are not supported. It does not really matter which approach is adopted.
The following suggestions should remove the worst of the problems, mostly using the last approach. In most cases, they are trivial extensions that merely permit the implementor to return an error indication if the feature cannot be provided, or wording to change ill-defined behaviour into implementation-defined behaviour.
The C standard should not place constraints on a program that are not determinable by the programmer, and the second and third items of paragraph 2 do. Many systems use floating-point for some integer operations or handle some integer exceptions as floating-point - e.g. dividing by zero may raise SIGFPE, and integer multiplication or division may actually be done by converting to floating-point and back again.
Either the clause "or unless the function is known not to use floating point" should be dropped in both cases, or a determinable condition should be imposed, such as by adding the extra item:
- any function call defined in the headers <complex.h> or <math.h> or defined elsewhere to access a floating-point object is assumed to have the potential for raising floating-point exceptions, unless the documentation states otherwise.
This requires most of the functions in <stdlib.h> to handle exceptions themselves, if they use floating-point, but that is assumed by much existing code. It has the merit of at least being determinable, which the existing wording isn't.
There is another serious problem, even on systems with IEEE arithmetic, in that the interaction of the flag settings with setjmp/longjmp is not well-defined. Should they have the value when setjmp was invoked, when longjmp was called, or what? Worse still, the current wording does not forbid setjmp to be invoked with non-standard modes and longjmp called with default ones, which won't work in general.
Another item of paragraph 2 should be added:
- if the setjmp macro is invoked with non-default modes, the behaviour is undefined. The values of the exception flags on return from a setjmp macro invocation are unspecified.
A related one concerns the case where a function with FENV_ACCESS set on calls one with FENV_ACCESS set off - the current wording implies that the latter must set the flags precisely for the benefit of the former, which is a major restriction on implementors and makes a complete mockery of footnote 163.
The second last sentence of paragraph 2 should be changed to:
If part of a program sets or tests flags or runs under non-default mode settings, ....
These specifications do not allow the implementation any way to indicate failure. This is (just) adequate for strict IEEE arithmetic, but is a hostage to fortune and prevents their use for several IEEE-like arithmetics. All such implementations can do is to not define the macros, thus implying that they cannot support the functions, whereas they may be able to support all reasonable use of the functions and merely fail in some perverse circumstances.
All of these functions (excluding fetestexcept) should be defined with a return type of int, and to return zero if and only if the call succeeded.
What happens if the rounding mode is none of the ones defined above, or is not determinable (as can occur)? The following should be added to the end of paragraph 3:
If the rounding mode does not match a rounding direction macro or is not determinable, a negative value is returned.
Many existing C <math.h> implementations and even more numerical libraries have the property that they rely on the rounding mode they are called with being the one they were built for. To use a different rounding mode, the user must link with a separate library. The standard should permit an implementation to reject a change if the change is impossible, as distinct from when it does not support that mode at all. Paragraph 3 be simplified to:
The fsetround function returns a nonzero value if and only if the requested rounding direction has been established.
Note that this enables the example to make sense, which it doesn't at present.
Exactly the same points apply as for 7.6.2 Exceptions above for all the functions (excluding feholdexcept), and exactly the same solution should be adopted.
A major flaw in paragraphs 4 and 5 is that there is no way of specifying an infinity or a NaN for double or long double, unless float supports them. While this is the common case, C9X does not require it and it is not reasonable to do so. In particular, the NEC SX-4 supports IEEE, Cray and IBM arithmetics, and there are a lot of IEEE systems around which have non-IEEE long double, and this case cannot be fully supported, either.
'float' should be changed to to 'double' in paragraph 4 and the following should be added to it:
are respectively float and long double analogs of INFINITY.
'float' should be changed to to 'double' in paragraph 5 and the following should be added to it:
are respectively float and long double analogs of NAN.
The classification macros are inadequate to classify all numbers on many architectures - for example, the IBM 370 has unnormalised numbers and the DEC VAX has invalid ones (i.e. not NaNs.) 188.8.131.52.2 and 7.6 permit other implementation-defined values, but this section does not.
The following should be appended to paragraph 6:
Additional floating-point classifications, with macro definitions beginning with FP_ and an uppercase letter, may also be specified by the implementation.
I have no idea what "without extraordinary roundoff error" means, and I have been involved in the implementation and validation of mathematical functions over 3 decades. My dictionary contains 5 definitions of "extraordinary", most of which might be applicable, and I know at least 3 separate meanings of the term "roundoff error" in the context of mathematical functions.
The following paragraph should be added:
If a function produces a range error to avoid extraordinary roundoff error, the implementation shall define the conditions when this may occur.
As mentioned above, the current wording forbids an implementation from correctly classifying certain IEEE, IBM 370 and DEC VAX numbers. The first sentence of paragraph 2 should have appended:
..., or into another implementation-defined category.
The wording of this is seriously flawed. It says that it returns the sign of a number, but is clearly intended to test the sign bit, and these are NOT equivalent. IEE 754 states explicitly that it does not interpret the sign of NaNs (see section 6.3), and the VAX distinguishes zeroes from reserved operands (not NaNs, but something much more illegal) by the sign bit.
And there is nowhere else in C9X that requires the sign of a floating-point number to be held as a bit - surely people have not yet forgotten ones' and twos' complement floating point?
Paragraphs 1 and 2 should be replaced by:
For valid non-zero values (including infinities but not NaNs), the signbit macro returns nonzero if and only if the sign of its argument is negative.
For zeroes and NaNs when __STD_IEC_559__ is defined, the signbit macro returns nonzero if and only the sign bit of the value is set.
For zeroes and NaNs when __STD_IEC_559__ is not defined, the signbit macro returns nonzero for an implementation-defined set of values and zero otherwise.
What does "treat negative zero consistently" mean? Does IBM 370 arithmetic do it? Does VAX? Does Intel? Does Cray? Does IEEE?
The sentence "On implementations ... the sign of zero as positive." should be replaced by one or the other of the following:
Unless __STD_IEC_559__ is defined (see Annex F), it is implementation-defined whether any representations of zero are regarded as negative by this function and, if so, which.
The copysign functions shall interpret the sign of zeroes in the same way that the signbit macro (184.108.40.206) does.
The UK comments on CD1 included a large number of comments on CD1 that have not been addressed in the FCD with regard to compatibility with IEC 60559 (IEEE 754) and ISO/IEC 10967-1 (LIA-1). It is not reasonable to claim that such problems do not matter because they cannot be shown in strictly conforming programs. The same applies to almost all of the trickier aspects of C89 and C9X floating-point support.
The responses stated that the intention is compatibility only with a subset of those standards, but those standards do not always allow the subsetting requires by C9X. Furthermore, the statement is not true in all cases, and it is impossible for an implementation to conform to both standards simultaneously.
The standard must be improved so that an implementation can reasonably satisfy both standards simultaneously, in all aspects where C9X claims that it is compatible with the other standards. Where this is not possible, C9X should admit the fact in so many words or provide a mechanism for alternate implementation.
There is also the major point that C9X can and should specify syntax for such support, in case where this would avoid implementations providing it incompatibly. This will then reduce problems if C wishes to support the feature properly at a later revision. A precedence for this is the signal handling, which effectively defines syntax but leaves the semantics almost completely undefined.
Furthermore, there are many places where C9X makes it unnecessarily difficult to satisfy the other standards, and where minor changes would have major benefits. These should be improved, and the forthcoming ISO/IEC 10967-2 (LIA-2) should also be considered in this respect.
The following suggestions should remove the worst of the problems, but are by no means a complete solution.
Paragraph 5 doesn't define precisely what the rounding mode terms mean, and there are many possible interpretations (especially of nearest rounding for numbers that fall precisely between two values.) Note that this is specified by IEC 60559 but explicitly not by ISO/IEC 10967-1. However, the latter requires the rounding method to be documented in full (see section 8, paragraph f.)
The following should be added to the end of the last sentence:
Unless __STD_IEC_559__ is defined (see Annex F), the precise definition of these rounding modes is implementation-defined.
This comment is not strictly an incompatibility, but is about wording likely to cause such problems. The current description of errno handling is so confusing that it could be interpreted that errno is unpredictable on return from a complex function. This cannot be the intention. The second sentence should be replaced by:
An implementation may define domain and range errors, when it will set errno to EDOM and ERANGE and the result to an implementation defined value, but is not required to.
One of the assumptions in the IEC 60559 model is that exception flags will eventually be either cleared or diagnosed, and this is required by ISO/IEC 10967-1. Fortran does not specify what may be written to 'standard error', but C does, and many vendors regard the standard as forbidding them from issuing diagnostics in this case. H.3.1.1 states that C permits an implementation to do this, but provides no hint as to how. Furthermore, there is no implication in the standard that floating-point exception flags must have any particularvalues at any time.
The following should be added to 7.6:
If any of the exception flags are set on normal termination after all calls to functions registered by the atexit function have been made (see 220.127.116.11), and stderr is still open, the implementation may write some diagnostics indicating the fact to stderr.
If this is not done, then Annex H must be corrected, or clarified to explain how such a diagnostic can be produced by a conforming implementation.
Section 7.12 paragraphs 5 and 6 and F.3 are seriously incompatible with the spirit of IEC 60559, and are in breach of IEEE 754 section 6.2, by not providing any way to define a signalling NaN or test for whether a NaN is signalling or quiet. In particular, an implementation cannot extend the fpclassify function to conform to both standards, because C9X requires it to classify both signalling and quiet NaNs as FP_NAN, and IEC 60559 requires it to distinguish them.
Furthermore, the current C9X situation does not allow a programmer to initialise his data to signalling NaNs (as recommended by IEEE 754). It is perfectly reasonable not to define the behaviour of signalling NaNs in general, but it is not reasonable to be unnecessarily hostile to IEC 60559. At the very least, there should be a macro NANSIG for creating one, which can be used in initialisers, and a macro FP_NANSIG for flagging one.
There are also implementation difficulties with the wording of fpclassify as it stands, especially since it may need to copy its argument, and this is not always possible for signalling NaNs.
7.12 should have the extra paragraph:
is defined if and only if the implementation supports signalling NaNs for the double type. It expands to a constant expression of type double representing an implementation-defined signalling NaN. If defined, NANSIG may be used as an initializer (6.7.8) for an object of semantic type double; no other semantics for NANSIG values are defined by this standard.
are respectively float and long double analogs of NANSIG.
Note that it is not possible to have solely a float value of NANSIG, because of the constraints on copying signalling NaN values.
7.12 paragraph 6 should define the extra symbol:
and add the extra sentence:
This standard does not specify whether the argument of fpclassify is copied or not, in the sense used by IEC 60559.
F.2.1 paragraph 1 needs replacing by::
The NAN, NAN_F, NAN_L, NANSIG, NANSIG_F, NANSIG_L, INFINITY, INFINITY_F and INFINITY_L macros in <math.h> provide designations for IEC 60559 NaNs and infinities.
F.3 last paragraph (starting "The signbit macro") should be simplified by the omission of the exclusion in brackets - i.e. "(except that fpclassify does not distinguish signalling from quiet NaNs)".
Paragraph 2 is in clear conflict with the stated intention of IEC 60559 and ISO/IEC 10967-1, and actually prevents an implementation from conforming to both C9X and the whole of ISO/IEC 10967-1 simultaneously. Despite this, H.3.1.2 Paragraph 1 claims that the C standard allows "hard to ignore" trapping and diagnostics as an alternative form of notification (as required by ISO/IEC 10967-1), but it specifically FORBIDS this in many routines of the library that provide the ISO/IEC 10967-1 functionality (as described in H.2.3.2).
This is unacceptable. While there are many possible solutions, this problem is extremely pervasive, and most of them would involve extensive changes to C9X. However, SOMETHING needs to be done, and the following are possibilities:
Alternatively, people might prefer to use SIGFPE for both classes of error; there are arguments both ways, and either choice is reasonable.
An implementation shall provide a mechanism for programs to be executed as described above. It may also provide a mechanism by which programs are executed in a mode in which some or all domain and range errors raise signals in an implementation-defined fashion.
If domain errors raise a signal, the signal should be SIGILL. If range errors raise a signal, the signal should be SIGFPE. It should be possible for the program to run in a mode where domain errors and range errors that correspond to overflow raise signals, but range errors that correspond to underflow do not.
Paragraph 4 is seriously incompatible with the spirit of IEC 60559 and the wording of ISO/IEC 10967-1. Note that 7.12.1 paragraphs 2 and 3 permits an implementation to define additional domain and range error conditions, but this section does not. Paragraph 4 should be changed to:
The invalid exception will be raised whenever errno is set to EDOM. Subsequent subclauses of this annex specify other circumstances when the invalid or divide-by-zero exceptions are raised.
There is also a possible ambiguity in paragraphs 5 and 6, and a problem caused by cases where the implementation may define extra range errors as permitted by 7.12.1. It should be closed by adding the following:
Whenever errno is set to ERANGE, at least one of the divide-by-zero, overflow or underflow exceptions shall be raised.
ISO/IEC 10967-1 6.1.1 point (c) requires the ability to permit the programmer to specify code to compensate for exceptions if trap-and-resume exception handling is used. C does not permit such code, but H.3.1 paragraph 4 claims that it does. In particular, there is no way to return a corrected value after a numeric (SIGFPE) signal. Paragraphs 4 of H.3.1 and H.3.1.2 must be corrected, so that they do not claim that C9X supports ISO/IEC 10967-1 trap-and-resume exception handling.
H.3.1.2 paragraph 4 claims that the C standard allows trap-and-terminate as well as trap-and-resume. This is not true, either, as C9X stands. In particular, it does not permit it with exponentF and scaleF implemented using logb and scalbn etc. Either such termination must be permitted, or paragraphs 4 of H.3.1 and H.3.1.2 must be corrected; a suggestion is made for the former elsewhere in this proposal..
Back to the Public Comments page. Back to the C page. Back to Clive's home page.