[net.lang.c] Redeclaration of typedef names

kendall@wjh12.UUCP (Kendall) (08/26/83)

Once a name has been defined as a typedef type, it is very difficult
to redeclare it in an inner block.  The manual states (section 8.8),

	Within the scope of a declaration, each identifier appearing
	as part of any declarator therein become [sic] syntactically
	equivalent to the type keyword naming the type associated with
	the identifier ....

This statement has a couple of exceptions.
(1) struct/union/enum tags are in a seperate namespace and do not
    conflict with typedef names.  It is common practice, and
    reasonable, to depend on this.  struct/union member names seem to
    work the same way in the Ritchie and Portable compilers.
(2) In both compilers, one can redeclare a typedef name in the normal
    namespace, and in an inner scope, (only) by redeclaring the name
    as either a formal parameter or an enum member.  I guess one is
    allowed to redeclare a typedef name in those contexts because it
    is syntactically unambiguous to do so.

The way I see it, exception (1) is a reasonable exception, and should
be viewed as an omission in the manual.  Exception (2), however,
strikes me as a compiler bug, even in both compilers.  It is a strange
thing to depend on, particularly since lint will complain.  If
exception (2) wasn't there, one could rest secure in the knowledge
that typedef names cannot be redeclared.

Questions:  does any program depend on exception (2)?  Should it be
stricken from the language, since the manual implicitly prohibits it
and since the language would be cleaner without it?  Does anyone care?

	Sam Kendall			{allegra,ihnp4}!wjh12!kendall
	Delft Consulting Corporation	  decvax!genrad!wjh12!kendall

ldg@druny.UUCP (08/27/83)

In my opinion, the problem of typedef redefinition stems from two
sources: 1) lack of specification, and, 2) compiler complexity.

Section 11.1 of the C Reference Manual (Ritchie) describes a scenario
in which a typedef identifier is redefined as a simple ordinary
identifier: 
	typedef float distance;
	...
	{
		auto int distance;
		...
The point made is that "int" must be present, otherwise we would have
a declaration with no declarator and type "distance. Clearly, the
physical position of "distance" also plays a role here. Should we
change the ordering of "int" and "distance" we would have an illegal
declaration with no declarator. If we had

		auto int a,b,c,distance,e,f;

should we expect a syntax error or a redeclaration to occur? It seems
the manual is lacking in this area. There should be no problem with using
"distance" as a structure or union tag, since these are kept in a logically
separate list, as the manual says. However, enumeration tags and enumerators
are like ordinary identifiers and would conflict with an identical typedef
name declared in the same scope. Incidentally, I couldn't get the above
example from the manual to compile on any compiler.

I think it's fairly clear why the compiler can't correctly resolve a
valid redeclaration of a typedef. The C parser is generated from a YACC
grammar, and expects the lexical analyzer to distinguish between a
simple identifier and a declared typedef name. If instead this were not
done and typedef names were treated lexically like any other identifier,
then the grammar must dramatically increase in size in order to handle
parsing problems like "in a declaration, where does the type part end
and the declarator begin?". Things could even get more ambiguous:

	x;		/*  declaration or statement?		*/
	a = (f)(x);	/* function call or cast expression?	*/

So, because a typedef name is lexically distinct from an identifier
(which is the root of any declarator) it cannot syntactically assume
the role of a declarator in a declaration. In order to implement typedef
redeclaration in a way consistent with the current manual, I would think
the compiler maintainers would have to modify the semantic actions
performed in the production(s) allowing a declaration without a declarator
so that a new definition is associated with the typedef identifier.