Defect Report #106

Submission Date: 03 Dec 93
Submittor: WG14
Source: Ron Guilmette
Question
ANSI/ISO C Defect report #rfg13:
Subclause 6.2.2.2 says:
The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, ...
There are two separate (but related) problems with this rule.
First, it is not entirely clear what constitutes a ``use'' of a value (or of an expression). In which lines of the following code is a type void value actually ``used?''
void example(void *pv, int i)
{
&*pv; /*
? */
*pv; /*
? */
i ? *pv : *pv; /*
? */
*pv, *pv; /*
? */
}

(The answer to this question will determine which of the above lines cause undefined behavior, and which cause well defined behavior.)
If one or more of the (questionable) lines from the above example are judged by the Committee to result in well defined behavior, then a second (separate) issue arises. This second issue requires some explaining.
Subclause 6.2.2.1 contains the following rules:
An lvalue is an expression (with an object type or an incomplete type other than void) ...
Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)... If the lvalue has an incomplete type and does not have array type, the behavior is undefined.
Note that the final rule (specifying a condition under which undefined behavior arises) seems, based upon the context, to only apply to those cases in which ``...an lvalue that does not have an array type is converted to the value...'' More specifically, it appears that undefined behavior is not necessarily produced for non-lvalue expressions (appearing in the indicated contexts).
Furthermore, it should be noted that the definition of an lvalue (quoted above) does not include all void types. Rather, it only includes the void type.
The result is that the indicated lines in following example would seem to yield well defined behavior (or at least they will yield well defined behavior if the Committee decides that their unqualified counterparts do), however I suspect that this may not have been what the Committee intended.
void example(const void *pcv, volatile void *pvv, int i)
{
&*pcv; /*
? */
*pcv; /*
? */
i ? *pcv : *pcv; /*
? */
*pcv, *pcv; /*
? */

&*pvv; /*
? */
*pvv; /*
? */
i ? *pvv : *pvv; /*
? */
*pvv, *pvv; /*
? */
}

In summary, I would ask that the Committee comment upon and/or clarify the behavior produced by each of the examples shown herein. Separately, I would request that the Committee make changes in the existing C Standard in order to make the rules applicable to such cases more readily apparent.
Response
In the first function called example, the expression statement &*pv is dealt with in Defect Report #012. The remaining three statements are well formed. See the last sentence of the cited reference and also subclause 6.6.3.
In the second function called example, the expression statements &*pcv and &*pvv are dealt with in Defect Report #012. The remaining six statements are well formed. The restrictions given in subclause 6.5.3 apply to object types, not incomplete types.
Previous Defect Report < - > Next Defect Report