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
^^^^^^^^
------------------------------------------------------------------------