N767 Some General C9X Issues N767 J11/97-131 ----------------------- J11/97-131 23 September 1997 Tom MacDonald tam@cray.com Introduction ------------ Some problems with C9XD11: ------------------------------------------------------------------------ QUESTION: Should we use // comments or /*...*/ comments or both? ------------------------------------------------------------------------ Since the C Standard will not forbid an implementation that uses infinite precision arithmetic, the following example is too strong. 5.1.2.3 Program execution Examples 5. Rearrangement for floating-point expressions is restricted because of limitations in precision as well ^ often as range. The implementation cannot generally apply the mathematical associative rules for addition or multiplication, nor the distributive rule, because of roundoff error, even in the absence of overflow and underflow. Likewise, the implementation cannot ^^^ ^ some s generally replace decimal constants in order to rearrange expressions. In the following fragment, rearrangements suggested by mathematical rules for real numbers are not valid. See Annex F.8. ^ often ------------------------------------------------------------------------ The following para. doesn't accomplish what was intended. A complex type should be just like an array of two elements (structures don't have elements). Structures can have padding in the middle and end, arrays cannot. Finally, there are no "structured" types. 6.1.2.5 Types [#11] Each complex type has the same representation and alignment requirements as a structured type containing ^^^^^^^^^^^^^ an array exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number. ------------------------------------------------------------------------ The following para. fails to mention restrict-qualified types. 6.1.2.5 Types [#25] Any type so far mentioned is an unqualified type. Each unqualified type has three corresponding qualified versions of its type:35 a const-qualified version, a volatile-qualified version, and a version having both qualifications. The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements.28 A derived type is not qualified by the qualifiers (if any) of the type from which it is derived. How about this: [#25] Any type so far mentioned is an unqualified type. Each unqualified type has seven qualified versions of its type,35 corresponding to the combinations of one, two, or all three of the const, volatile, and restrict qualifiers. The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements.28 A derived type is not qualified by the qualifiers (if any) of the type from which it is derived. ------------------------------------------------------------------------ Since all "pointers to structures" smell the same, and all "pointers to unions" smell the same, perhaps we should say something about that here. [#26] A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements.28 Pointers to other types need not ^ All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. have the same representation or alignment requirements. ------------------------------------------------------------------------ Use the term "completed" consistently throughout the Draft. For instance, the Draft says (in various places): | [#16] The void type comprises an empty set of values; it is | an incomplete type that cannot be completed. | ^^^^^^^^^^ | | [#22] An array type of unknown size is an incomplete type. | It is completed, for an identifier of that type, by | ^^^^^^^^^ | specifying the size in a later declaration (with internal or | external linkage). A structure or union type of unknown | content (as described in 6.5.2.3) is an incomplete type. It | is completed, for all declarations of that type, by | ^^^^^^^^^ | declaring the same structure or union tag with its defining | content later in the same scope. | | [#5] With one exception, if the value of a member of a union | | object is used when the most recent store to the object was | | to a different member, the behavior is implementation- | defined.68 One special guarantee is made in order to | simplify the use of unions: If a union contains several | structures that share a common initial sequence (see below), | and if the union object currently contains one of these | structures, it is permitted to inspect the common initial | part of any of them anywhere that a declaration of the | completed type of the union is visible. Two structures | ^^^^^^^^^ | share a common initial sequence if corresponding members | have compatible types (and, for bit-fields, the same widths) | for a sequence of one or more initial members. | | [#5] If the type name specifies an array of unknown size, | | the size is determined by the initializer list as specified | | in 6.5.7, and the type of the compound literal is that of | | the completed array type. Otherwise (when the type name | | ^^^^^^^^^ | | [#2] If a type specifier of the form | | struct-or-union identifier | | | occurs prior to the } following the struct-declaration-list | that defines the content, the structure or union is an | incomplete type.98 It declares a tag that specifies a type | that may be used only when the size of an object of the | specified type is not needed.99 If the type is to be | completed, another declaration of the tag in the same scope | ^^^^^^^^^ So, we have "incomplete" types and we have "completed" types. Change the following paragraph accordingly. 6.1.2.6 Compatible type and composite type [#1] Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.5.2 for type specifiers, | in 6.5.3 for type qualifiers, and in 6.5.5 for | declarators.36 Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements. If one is declared with a tag, the other shall be declared with the same tag. If both are complete ^^^^^^^^ completed types, then the following additional requirements apply. ------------------------------------------------------------------------ There's a conflict between the following section: 6.1.2.8 Representations of types [#1] The representations of all types are unspecified except as stated in this subclause. and: 6.1.2.5 Types [#19] The type char, the signed and unsigned integer types, and the enumerated types are collectively called integral types. The integral and real floating types are collectively called real types. The representations of integral types shall define values by use of a pure binary numeration system.33 The precision of an integral type is the number of bits it uses to represent values excluding any sign and padding bits. The representations of real floating types are unspecified. Something has to give. Perhaps: [#1] The representations of all types are unspecified except ^^^ Except where previously stated, the as stated in this subclause. ------------------------------------------------------------------------ There is a sentence indicating that an object is evaluated. Only expressions are evaluated in the Draft. Here are some excerpts: | Evaluation of an expression may produce side effects. | | [#3] An operator specifies an operation to be performed (an | evaluation) that yields a value, or yields a designator, or | | [#2] Between the previous and next sequence point an object | shall have its stored value modified at most once by the | evaluation of an expression. Furthermore, the prior value | | [#5] If an exception occurs during the evaluation of an | expression (that is, if the result is not mathematically | | [#8] The order of evaluation of the function designator, the | arguments, and subexpressions within the arguments is 6.1.2.8.1 General [#3] Certain object representations might not represent a value of that type. If such a representation is accessed due to evaluation of an object, or if such a representation ^^^^^^^^^^^^^^^^^^^^^^^ the evaluation of an lvalue that references an object is produced by a side effect that stores into all or any part of the object using an lvalue of that type, then the ^ effective [[... maybe you don't need to say "using an lvalue of that type" at all ... who cares how the trap rep. got there? ...]] behavior is undefined.39 Such representations are called trap representations. ***** add a forward reference for "effective type" (if needed) ------------------------------------------------------------------------ Duplicate footnotes: What is our policy on footnotes? Footnote 28 is referenced from multiple pages. Footnote 33 and 38 are duplicates (almost). ------------------------------------------------------------------------ Footnote 40 seems to indicate that there are only 2 possibilities. 40. Thus, structure assignment may be implemented element- ^ for example, at-a-time or via memcpy. ------------------------------------------------------------------------ 6.2.1.3 Real floating and integral [#3] An integer may be converted to any pointer type. The | result is implementation-defined, and might not be a pointer | to an object of that type. | What about "pointer to function" and "pointer to incomplete" types? Suggested wording change: An integer may be converted to any pointer type. The result is implementation-defined, and might be improperly aligned or an invalid operand for the unary *, [], (), or -> operators. ------------------------------------------------------------------------ There is no "incomplete object type" in C. There is no "complete type" in C. 6.2.1.3 Real floating and integral [#5] A pointer to a complete or incomplete object type may | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an object or incomplete type be converted to a pointer to a different complete or | ^^^^^^^^ object incomplete object type. if the resulting point is not | ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ incomplete type pointer correct aligned for the pointed to type, the behavior is | ^^^^^^^ correctly undefined. Otherwise, when converted back again, the result | shall compare equal to the original pointer.53 | ------------------------------------------------------------------------ 53. All pointers to character types are correctly aligned. In general, the concept correctly aligned is transitive: if a pointer to type A is correctly aligned for a pointer to type B, which in turn is correctly aligned ^^^^^^^^^^^^^^^^^^ use roman font for a pointer to type C, then a pointer to type A is correctly aligned for a pointer to type C. ------------------------------------------------------------------------ I have a major problem with this footnote. It seems to me this footnote forbids bit-addressable machines! If you read in a bit address from a file (for example), it might not be correctly aligned for a character type. Is this the intent????? 53. All pointers to character types are correctly aligned. In general, the concept correctly aligned is transitive: if a pointer to type A is correctly aligned for a pointer to type B, which in turn is correctly aligned for a pointer to type C, then a pointer to type A is correctly aligned for a pointer to type C. ------------------------------------------------------------------------ What about unnamed bit-fields? 6.5.2.1 Structure and union specifiers [#4] As discussed in 6.1.2.5, a structure is a type | consisting of a sequence of named members, whose storage is ^^^^^ delete this word? allocated in an ordered sequence, and a union is a type consisting of a sequence of named members, whose storage overlap. ------------------------------------------------------------------------ Need a lead in sentence. 6.5.5.2 Array declarators Examples 3. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following declarations demonstrate the compatibility rules for variably modified types. extern int n; extern int m; void fcompat() ^ void { int a[n][6][m]; int (*p)[4][n+1]; | int c[n][n][6][m]; int (*r)[n][n][n+1]; p = a; // Error - not compatible because 4 != 6. ^^^^^^ courier r = c; // Compatible, but defined behavior // only if n==6 and m==n+1. | } ------------------------------------------------------------------------ Get rid of the parenthetical remark, and corresponding phrase in subsequent sentence. 6.7.1 Function definitions Examples 1. In the following: extern int max(int a, int b) { return a > b ? a : b; } extern is the storage-class specifier and int is the type specifier (each of which may be omitted as those ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ are the defaults); max(int a, int b) is the function ^^^^^^^^^^^^^^^^^ declarator; and [[... snip ...]] extern int max(a, b) int a, b; { return a > b ? a : b; } Here int a, b; is the declaration list for the parameters, which may be omitted because those are the ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ defaults. The difference between these two ^^^^^^^^ ------------------------------------------------------------------------