Defect Report #013

Submission Date: 10 Dec 92
Submittor: WG14
Source: X3J11/90-047 (Sam Kendall)
Question 1
Compatible and composite function types
A fix to both problems Mr. Jones raises in X3J11 Document Number 90-006 is: In subclause on page 68, lines 23-25, change the two occurrences of ``its type for these comparisons'' to ``its type for compatibility comparisons, and for determining a composite type.'' This change makes the sentences pretty awkward, but I think they remain readable.
This change makes all three of Mr. Jones's declarations compatible:
int f(int a[4]);
int f(int a[5]);
int f(int *a);

This should be the case; it is consistent with the base document's idea of ``rewriting'' the parameter type from array to pointer.
In subclause, page 68, lines 22-25, change:
(For each parameter declared with function or array type, its type for these comparisons is the one that results from conversion to a pointer type, as in 6.7.1. For each parameter declared with qualified type, its type for these comparisons is the unqualified version of its declared type.)
(In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the type that results from conversion to a pointer type, as in 6.7.1, and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)
Question 2
``Compatible'' not defined for recursive types
The term ``compatible'' is not completely defined. Consider the following two file-scope declarations in separate translation units:
extern struct a { struct a *p; } x;
struct a { struct a *p; } x;
Are these two declarations of x compatible? Obviously they should be, but subclause does not say so.
Because subclause does not say how to terminate the recursion in testing for compatibility of two recursive types, either interpretation is possible. In other words, it is consistent with the rules in subclause to decide that the two declarations are compatible; but it is also consistent to decide that they are incompatible.
We can solve the problem roughly as follows: append the following draft sentence to the first paragraph of subclause (page 25, line 8):
If two types declared in separate translation units admit the possibility of being either compatible or incompatible, the two types shall be compatible.* [Footnote *: This case occurs with recursive types.]
This sentence is not satisfactory; perhaps another Committee member can state this rule better.
We agree that the C Standard can be read in a way that it ``loops.'' Our intent, and we feel the only reasonable solution, is that the recursion stops and the two types are regarded as compatible.
Question 3
Composite type of enum vs. integer not defined
There is one case where two types are compatible, but their composite type is not defined. To fix this problem, in subclause insert after page 25, line 17:
- If one type is an enumeration and the other is an integer type, the composite type is the enumeration.
There may be other cases where ``compatible'' is not defined. I made a cursory search and did not find any.
The issue is that in
enum {r,w,b} x;

some-int-type x;

where some-int-type happens to be the type that by subclause, page 61, line 40 is compatible with the type of the enum, what is the resultant composite type?
Subclause on page 25, lines 11-12 says ``a type that ... satisfies the following conditions'' (added emphasis on ``a''). The composite type of two compatible types is not necessarily unique. In this case both the enum type and the some-int-type satisfy the definition of ``composite'' type. This refutes the claim that the ``composite type is not defined;'' the point is that the standard does not guarantee a unique composite type.
As an example, in the following declarations:
enum {r, w, b} x;
some_int_type x;
provided the enumeration type is compatible with the type of some_int_typ e, it is unspecified whether the composite type of x is the enumeration type or some_int_type.
Question 4
When a structure is incomplete
Reference subclause, page 62, lines 25-28:
If a type specifier of the form
struct-or-union identifier
occurs prior to the declaration that defines the content, the structure or union is an incomplete type.
In the following example, neither the second nor the third occurrence of struct foo seem adequately covered by this sentence:
struct foo {
struct foo *p;
} a[sizeof(struct foo)];
In the second occurrence foo is incomplete, but since the occurr ence is within ``the declaration that defines the content,'' it cannot be said to be ``prior'' that declaration. In the third occurrence foo is complete, but again, the occurrence is within the declara tion.
To fix the problem, change the phrase ``prior to the declaration'' to ``prior to the end of the struct-declaration-list or enumerator-list.''
In subclause, page 62, line 27, change:
occurs prior to the declaration that defines the content
occurs prior to the } following the struct-declaration-li st that defines the content
Question 5
Enumeration tag anomaly
Consider the following (bizarre) example:
enum strange1 {
a = sizeof (enum strange1) /*
line [2] */
enum strange2 {
b = sizeof (enum strange2 *) /*
line [5] */

The respective tags are visible on lines [2] and [5] (according to subclause, page 20, lines 39-40, but there is no rule in subclause, Semantics (page 62) that governs their meaning on lines [2] and [5]. Footnote 62 on page 62 seems to be written without taking this case into account.
The first declaration must be illegal. The second declaration should be illegal for simplicity.
Perhaps these declarations are already illegal, since no rule gives them a meaning. To clarify matters, I suggest in subclause appending to page 62, line 35:
A type specifier of the form
enum identifier
shall not occur prior to the end of the enumerator-list that defines the content.
If this sentence is not appended, something like it should appear as a footnote.
Add to subclause, page 63, another Example:
An enumeration type is compatible with some integral type. An implementation may delay the choice of which integral type until all enumeration constants have been seen. Thus in:
enum f { c = sizeof(enum f) };
the behavior is undefined since the size of the respective enumeration type is not necessarily known when sizeof
Previous Defect Report < - > Next Defect Report