Defect Report #040
Submission Date: 10 Dec 92
Submittor: WG14
Source: X3J11/91-062 (Derek M. Jones)
Question 1
Composite type
Rule for function parameter compatibility, subclause 6.7,1, page 82, lines
24-25:
void f(const int);
void f(int a)
{
a = 4;
}
In the above case what is the composite type of f?
The legality of the assignment to a depends on the answer.
int f(int a[4]);
int f(int a[5]);
The parameters are compatible because they are converted to pointer
to ..., but what is the composite type?
Response
void f(const int);
void f(int a)
{
a = 4;
}
What is the composite type of f?
Answer: void f(int). Defect
Report #013, Question 1 describes the correct manner for constructing
the composite type.
Is the assignment valid?
Answer: Yes. The type of a parameter is independent of the composite type
of the function, so the assignment is valid (cf. subclause 6.7.1).
Another example:
int f(int a[4]);
int f(int a[5]);
The parameters are compatible because they are converted to pointer
to ..., but what is the composite type?
Answer: The response to the Defect Report mentioned above answers this
question as well.
Question 2
Is an implementation that fails to equal (or exceed) the value of an environmental
limit conforming? Subclause 5.2.4 says that those in that subclause must
be equalled in a conforming implementation. There is no such wording for
the environmental limits in the Library (subclauses 7.9.2, 7.9.3, 7.9.4.4,
7.9.6.1, 7.10.2.1).
Correction
Add to subclause G.2, page 203:
- A call to a library function exceeds an environmental limit (7.9.2,
7.9.3, 7.9.4.4, 7.9.6.1, 7.10.2.1).
Question 3
Is an ``environmental constraint'' a constraint?
In subclause 7.6.1.1, page 118, lines 22-30, we have a set of environmental
constraints on where setjmp may occur.
Does violating these rules require a constraint error to be flagged, or
is it undefined behavior?
Some examples:
i = setjmp(a);
if (setjmp(a) == i)
...
Response
Must an implementation diagnose violations of environmental constraints?
Answer: Diagnostics are not required for constraint violations in clause
7, since subclause 5.1.1.3 refers to a constraint as defined in clause
3, which applies to language elements only.
Question 4
For the fragment
if (a**b||c++d)
;
Defect Report #017 Question 39
states that this is lexed as:
-
{if} {(} {a} {<<}
{b} {||} {c} {>>}
{d} {)}
not as:
-
{if} {(} {a} {**b||c++}
{d} {)}
The rationale for this interpretation was that the constraint in subclause
6.1.7, page 32, lines 33-34 disallowed a header name preprocessing token
anywhere except within a #include. Since the header name
preprocessing token could not exist it was not lexed as such.
It was pointed out that the ``longest possible token'' rule was not influenced
by rules elsewhere in the C Standard, i.e. i+++++j is lexed
as:
-
{i} {++} {++} {+}
{j}
not as:
-
{i} {++} {+} {++}
{j}
Now (c) is a constraint violation by subclause 6.3.2.4, page 42, lines
38-39, the operand of the second ++ is not a modifiable
lvalue. But this constraint does not require that the input be re-lexed
to form the preprocessing tokens given in (d), which is conforming code.
As the UK C Panel saw it, the first example should be lexed as given in
(b) and a diagnostic issued. Having violated a constraint, we are now into
undefined behavior. An implementation could define the behavior in this
circumstance to be a re-lex of the input to produce the preprocessing tokens
given in (a).
As far as the user was concerned, they would get the expected behavior
with the added value of a diagnostic being issued.
All those present felt that the interpretation was incorrect and recommended
that the UK ask the Committee to reconsider its decision.
To summarize, there is no ambiguity in the C Standard and the original
X3J11 interpretation is incorrect.
Response
Is a diagnostic required for an input such as
if (a**b||c++d)
because of a violation of the constraint specified in subclause
6.1.7, page 32, lines 33-34?
Answer: No. Our response to Defect Report
#017 Question 39 addresses this issue.
Question 5
In the constraint for subclause 6.5.2, page 59, lines 2-4: What does the
C Standard mean when it says ``set?''
Does it mean that the construct:
int int i;
violates a constraint?
It has been suggested that this wording was left vague to allow such constructs
as long long (which is supported by some compilers) to
fall into the undefined behavior category.
Would the Committee clarify the situation with regard to duplicate type
specifiers? Do such constructs result in a constraint error or undefined
behavior?
The related case static static is explicitly ruled out
by the constraints in the previous subclause.
Additionally, volatile volatile is ruled out by the constraint
in subclause 6.5.3.
Response
Example:
int int i;
Must this be diagnosed?
Answer: Yes. It is allowed to rearrange the order of type specifiers within
a set, but not to duplicate them (cf. subclause 6.5.2). Thus int
int is a constraint violation.
Question 6
The definition of the offsetof macro in subclause 7.1.6
does not cover all its possible occurrences:
-
There are no restrictions on the structure being a completed type.
struct t1 {
char c;
short s;
int i[offsetof(struct t1, s)];
}
When discussing the use of incomplete types, recourse usually
has to be made to the rules relating to where an object of unknown size
may appear.
Would the Committee agree that there are not any rules prohibiting the
above construction?
-
In this structure we are asked to find the offset of a field that has not
yet been encountered:
struct t2 {
char c;
union {
int i[offsetof(struct t2, s)];
short s;
} u;
};
Would the Committee agree that there do not appear to be any rules
that make this construct illegal?
-
The following structure has infinitely many ``solutions:''
struct t3 {
char a[offsetof(struct t3, i)];
int i;
}
since char has size 1, any size of array will
be the same as the offsetof the field i.
-
The following structure has no ``solutions:''
struct t4 {
int a[offsetof(struct t3, i)];
int i;
}
int is always larger than 1.
Response
- Example:
struct t1 {
char c;
short s;
int i[offsetof(struct t1, s)];
};
This is not a valid use of the offsetof macro. The
hypothetical static type t; declaration required
for offsetof (cf. subclause 7.1.6) could not have validly
appeared prior to the invocation of offsetof because the
type struct t1 is incomplete (cf. subclause 6.7.2); therefore
the offsetof invocation is not strictly conforming.
- The answer is the same as (a) above. In addition, the members mentioned
in these invocations are not in scope.
- The answer is the same as (a) above. In addition, the members mentioned
in these invocations are not in scope.
- The answer is the same as (a) above. In addition, the members mentioned
in these invocations are not in scope.
Question 7
sizeof various identifiers (subclause 7.1.6)
a)
void f(int c, char a[sizeof(c)]);
b)
int i;
struct {
int i;
char a[sizeof(i)];
};
Now the argument to sizeof must be an expression
or a type.
In (a) is c an expression? I think not because:
expression -> object -> has storage in execution envrionment
and c does not have storage allocated to it. So (a) violates
a semantic ``shall'' and is undefined behavior.
Now in (b) the field i is obviously not an expression.
But is it visible? Like the outer i, it has file scope.
However, it is in a different namespace. There are no rules for namespace
resolution in the sizeof subclause.
So is (b) legal or undefined behavior?
Response
-
Example:
void f(int c, char a[sizeof(c)]);
The reference to c is an expression because the previosly
declared identifier designates a function parameter (cf. subclause 6.5.4.3),
which is an object (subclause 3.15), thus meeting the requirement in subclause
6.3.1.
- Another example:
int i;
struct {
int i;
char a[sizeof(i)];
};
In C, this is okay. Subclause 6.1.2.3, Name spaces of identifiers,
requires that i in the sizeof expression
refers to the external i, not the member.
Question 8
Refer to subclause 6.1.2.5, page 22, lines 32-36:
- char c = 7; /* implementation defined behavior, since 7 need
not
be a member of the basic execution character set */
- c = 'a'; /* ok */
c++; /* implementation defined */
c)
c = '1'; /* ok */
c++; /* ok? */
It has been suggested that the above constructs are not implementation
defined.
Subclause 6.1.3.4, page 29, lines 30-33:
- c = '\07'; /* what is in the source/execution character set
is
given in subclause 5.2.1. Anything else is an extension. */
e)
c = '$';
It has been suggested that characters may be added to the basic
source/execution character set without implementation defined behavior
being invoked. (I guess my position on this item can be deduced from the
text.)
Response
- Subclause 6.1.2.5 says ``An object declared as type char
is large enough to store any member of the basic execution character set...
If other quantities are stored in a char object, the behavior
is implementation-defined: the values are treated as either signed or nonnegative
integers.'' Consider this example:
char c = 7;
The assignment c = 7 is not implementation-defined because,
from a reasonable reading of subclause 6.1.2.5, it is clear that the only
implementation-defined behavior here is the signedness of the value of
the char object.
- Another example:
c = 'a';
c++;
The increment of c after assigning an 'a'
to it is defined by the implementation because the numeric encoding of
'a' is defined by the implementation. If 'a'
were equal to CHAR_MAX, the increment could even cause
an overflow (cf. subclause 5.2.1).
- Another example:
c = '1';
c++;
The increment of c after assigning a '1'
to it is not implementation-defined because the characters '0'
through '9' are required to be a contiguous range (cf.
subclause 5.2.1). Thus, the result is '2'.
- Another example:
c = '\07';
The value of the character constant '\07' is defined by
the C Standard (cf. subclause 6.1.3.4, page 29, line 10-13). The implementation-defined
behavior of some escape sequences, described on page 29, lines 30-33, is
clarified in the example on page 30, lines 8-14.
-
Another example:
c = '$';
If $ is in the execution character set, the value of '$'
is locale-specific and so must be defined by the implementation (cf. subclause
5.2.1).
Question 9
re: UK request for interpretation cai027 (
Defect Report #017 Question 27)
X3J11 refs: 90-056, 90-083
It has been pointed out, and the UK C panel agreed at its last meeting,
that the request for interpretation was unnecessary. The C Standard was
clear and unambiguous as is.
To make matters worse, X3J11 appears to have given an interpretation that
is the opposite of what the C Standard says.
The UK would like to withrdaw this request for interpretation and ask the
Committee to reconsider its position.
Response
We reaffirm the previous interpretation.
Previous Defect Report
< - >
Next Defect Report