Interpretation of peculiar declarators?

David Michaels david at lpi.liant.com
Thu May 9 09:46:21 AEST 1991


In article <679 at rosie.NeXT.COM> mself at next.com writes:

> I am trying to determine whether the following program is in error:
>
>	typedef int t;
>	void foo (void) {
>	  t t, x;
>	}
>
> I believe this ought to declare t and x to be of type int, since I don't
> believe that the fact that t is re-declared as a variable instead of a
> typedef  in the first declarator should affect the interpretation of the
> identifier t in the type-specifier for the second declarator (since the
> type-specifier is lexcically before the redefinition).

You're right, "t t, x;" is equivalent to "int t, x;".

> ANSI is quite specific that the scope of an identifier begins "just after
> the completion of its declarator" (3.1.2.1), and there is nothing to
> indicate that the identifiers in the type-specifier may be re-interpreted
> at each declarator.

Yep.

> An even more complicated case is this:
>
>	t t = 1, x = t;
>
> In this case I believe that this is exactly equivalent to
>
>	int t = 1, x = t;

Right again, they are equivalent.  This also might be of interest:

	const x;        /* ok -- same as const int x; */
	typedef int t;
	f () {
	     const t;   /* error -- no declarator name (i.e. const int;) */
	}
	g () {
	     const *t;  /* error -- technically, but ... */
	}

ANSI-C (3.5.6) says that if a typedef name is redeclared in an inner scope
(or as a struct/union member in the same or inner scope), the type specifiers
shall not be omitted.  This constitutes what someone coined as the "maximum
munch" rule (in C++ this rule is achieved by saying that the longest sequence
of declaration specifiers that could possibly be a type name is taken as the
declaration specifiers of a declaration).  The second error case is interesting
in that according to ANSI-C it is illegal, even though it is clear what is
meant, and the compiler has to go out of its way to generate a diagnostic.
Here's another one:

	typedef int t;
	f () {
	     const t (t (t (t (t))));
	}

This mess turns out to be a legal declaration equivalent to:

	const int t (int (int (int)));

I.e. a function "t" returning a "const int" and taking one parameter of
type [pointer to] function returning "int" and taking one parameter of type
[pointer to] function returning "int" and taking one parameter of type "int".

> If all of this speculation is true, then it puts some fairly strong 
> constraints on the implementation of compilers.  A compiler must look
> up any type name in the type-specifier only once (before processing
> any of the declarators), and it must enter the newly declared identifiers
> into the symbol table before processing subsequent declarators.

Exactly.  It turns out that it's not all that
difficult to get it straight; just a little tricky.

> Can anyone clear this up?

Sounds like you've got it all cleared up yourself.

				-- David Michaels (david at lpi.liant.com)
				   Language Processors, Inc.
				   Framingham, Massachusetts



More information about the Comp.std.c mailing list