[cfe-dev] Semantics for dereferencing incomplete types?

Eli Friedman eli.friedman at gmail.com
Sat Jan 12 23:14:21 PST 2008


Take the following two testcases:

void
foo (void)
{
  struct b;
  struct b* x = 0;
  struct b* y = &*x;
}

void foo2 (void)
{
  typedef int (*arrayptr)[];
  arrayptr x = 0;
  arrayptr y = &*x;
}

Currently, clang rejects both of these.  Checking with some of the
other c compilers I have access to, the online comeau compiler,
tinycc, and lcc-win32 accept both, while gcc accepts the second but
not the first (which seems really strange, but according to some
diving into svn revision history, gcc's been doing that for at least
15 years...).

The place in the source where clang outputs the error,
Sema::CheckIndirectionOperand, justifies the error by pointing to C99
6.5.3.2p4, "If the operand points to a function, the result is a
function designator; if it points to an object, the result is an
lvalue designating the object.", and the comment concludes that this
means dereferencing an incomplete type is illegal.

My interpretation of the text in the C99 standard is that saying that
x "points to an object" doesn't actually mean that x has an object
type.  Per the standard, an object is "region of data storage in the
execution environment, the contents of which can represent values,"
which is much different from an object type.  Besides that, there is a
footnote stating that "&*E is equivalent to E", and the standard
earlier explicitly states that an lvalue can have an incomplete type.

Granted, the phrasing in the standard isn't especially well-chosen.
(It gets even worse with the definition of array subscripting, which
is defined to take a "pointer to object /type/", where /type/ is
italicized).  That said, I can't see any good reason why either of the
above functions should be disallowed by the standard, since the
meaning is well-defined.

Here is another test:
void foo3 (void)
{
  void* x = 0;
  void* y = &*x;
}

I think this testcase is equivalent according to the standard, because
void is just another incomplete type which is defined to have no
members and is always incomplete.  gcc, clang, and llc-win32 warn on
this construct, but all the compilers I tested accept it, which makes
it kind of weird to reject incomplete array or struct types.

-Eli



More information about the cfe-dev mailing list