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 6.5.4.3 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.
Correction
In subclause 6.5.4.3, 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.)
to:
(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 6.1.2.6 does not say
so.
Because subclause 6.1.2.6 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 6.1.2.6 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 6.1.2.6 (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.
Response
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 6.1.2.6
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.
Response
The issue is that in
enum {r,w,b} x;
and
some-int-type x;
where some-int-type happens to be the type that
by subclause 6.5.2.2, page 61, line 40 is compatible with the type of
the enum, what is the resultant composite type?
Subclause 6.1.2.6 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 6.5.2.3, 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.''
Correction
In subclause 6.5.2.3, page 62, line 27, change:
occurs prior to the declaration that defines the content
to:
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 6.1.2.1, page 20, lines 39-40, but there is no
rule in subclause 6.5.2.3, 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 6.5.2.3
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.
Correction
Add to subclause 6.5.2.3, 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