Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!sdd.hp.com!spool.mu.edu!uunet!lpi.liant.com!david From: david@lpi.liant.com (David Michaels) Newsgroups: comp.std.c Subject: Re: Interpretation of peculiar declarators? Message-ID: <1991May8.234621.14067@lpi.liant.com> Date: 8 May 91 23:46:21 GMT References: <679@rosie.NeXT.COM> Organization: Language Processors Inc., Framingham MA Lines: 82 In article <679@rosie.NeXT.COM> mself@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@lpi.liant.com) Language Processors, Inc. Framingham, Massachusetts