X3J11 Pleasanton meeting summary

Lars Henrik Mathiesen thorinn at skinfaxe.diku.dk
Fri Oct 19 08:20:53 AEST 1990


ok at goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>> >>	struct foo x;
>> >>	struct foo { int i; };
>> >>	/* the above is strictly conforming; incomplete-type objects can
>> >>	   be defined, so long as by the end of the translation unit the
>> >>	   type becomes complete so that storage can then be allocated */

>I have some difficulty with the interpretation, though.
>Surely it is possible to produce a fragment of C code where you need
>to know the size *before* the end of the translation unit?

>	struct Erewhon a, b;

>	void do_we_have_to_wait_until_the_end_of_the_unit_for_this_too()
>	    {
>		a = b;
>	    }

>	/* megabytes of source code follow ... */

>I can see how to handle this; plant calls to a static void __assign_Erewhon()
>function, and generate it as soon as you know the size.  Or call a generic
>function, picking up the size from a static const, and plant code at the end
>to initialise that.  But that could mean the difference between using a
>single instruction (movc3, if size < 64k) or calling a procedure (size >).

If your compiler uses a two-pass assembler for backend, it can
allocate a symbol for the size and set it when the size becomes known.
If it emits finished code a function at a time, it could refer to an
absolute linker symbol for the size and define it later. If you have
emitted code for ``small'' objects and they turn out to be ``large'',
couldn't you just give an error (if your limit is 32K or greater)?

Anyway, a modifiable lvalue designates an object that does not have an
incomplete type (3.2.2.1), so the assignment is non-conforming.

>It isn't quite so clear how to handle

>	void surely_this_cannot_wait_so_long()
>	    {
>		struct Erewhon butler[20];
>		...
>		samuel(&butler[18]);
>	    }

>without some sort of runtime support that comes pretty close to being
>alloca().

I don't think you have to handle that either. A clue was given in
another posting. As the draft I have says (3.5 Semantics):
  "If an identifier for an object is declared with no linkage, the type
  for the object shall be complete by the end of its declarator, or by
  the end of its init-declarator if it has an initializer."
and (3.1.2.2)
  "The following identifiers have no linkage: an identifier declared to
  be anything other than an object or function; an identifier declared
  to be a function parameter; an identifier declared to be an object
  inside a block without the storage-specifier _extern_."

My conclusion: the only objects that can be declared with an
incomplete type are statics with file scope and externs (with any
scope). (I don't know if structure members are objects, but they're
constrained (3.5.2.1) to have a complete type anyway. Likewise, array
elements are described as having an object type (3.1.2.5).)

So far as I can see, you can't do anything interesting with objects of
incomplete type. Possibly the rule about ``not needing the size'' is
unnecessary because other constraints prevent that need from arising
at all; any examples to the contrary? (Note that I'm arguing from a
draft --- I hope my reasoning's still valid by the ANS.)

--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark      [uunet!]mcsun!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.      thorinn at diku.dk



More information about the Comp.std.c mailing list