Is the following example a valid complete translation unit in C?
struct foo;
struct foo *bar(struct foo *j)
{
return &*j;
}
struct foo is an incomplete type, but I cannot find an explicit prohibition of dereferencing an incomplete type in the C standard. In particular, §6.5.3.2 says:
The unary
&operator yields the address of its operand. If the
operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If
the operand is the result of a unary*operator, neither that
operator nor the&operator is evaluated and the result is as if
both were omitted, except that the constraints on the operators still
apply and the result is not an lvalue.
The fact that the result is not an lvalue is not germane – return values need not be. The constraints on the * operator are simply:
The operand of the unary * operator shall have pointer type.
and on the & operator are:
The operand of the unary
&operator shall be either a function
designator, the result of a[]or unary*operator, or an lvalue
that designates an object that is not a bit-field and is not declared
with theregisterstorage-class specifier.
Both of which are trivially satisfied here, so the result should be equivalent to just return j;.
However, gcc 4.4.5 does not compile this code. It instead gives the following error:
y.c:5: error: dereferencing pointer to incomplete type
Is this a defect in gcc?
Yes, I think it is a bug. Even lvalues of incomplete types, so
*j, seem to be allowed depending on the context:Basically this should work as long as you don’t do anything with such an lvalue that needs to know about the structure of the
struct. So if you don’t access the object or ask about its size, this is legal.