[comp.lang.c] What is the scope of "type-name" in a cast expression?

mikpe@majestix.ida.liu.se (Mikael Pettersson) (08/08/89)

I have a question for those who know the details about C declarations:

  What is the scope of the "type-name" in a cast expression?

My impression is that the scope should be the entire surrounding
expression (but not any further), but the compilers I've tried
[PCC and GCC on a Sun3] both in fact make the type visible from
the enclosing statement and downwards to the end of the {}-block.

Example of code I think should be rejected:
--huh.c--
/* accepted by PCC and GCC */
f() {
    int i;
    *(enum { foo, bar, bletch } *)&i = bar;
    i = foo;					/* ?? */
}
g() {
    int ia[2];
    ((struct foo { int i,j; } *)ia)->i = 99;
    ia[1] = sizeof (struct foo);		/* ?? */
}
--

AdvTHANX for any references to the appropriate "chapter and verse".

[RTFM? I have looked in both "The C Programming Language - Reference
Manual" (UNIX PS1 4.3BSD) (essentially a reprint from K&R1) and
"C: A Reference Manual, 2nd Ed." (Harbison&Steele) and found nil :-(]
-- 
Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden
email: mpe@ida.liu.se  or  ..!{mcvax,munnari,uunet}!enea!liuida!mpe

karl@haddock.ima.isc.com (Karl Heuer) (08/08/89)

In article <1324@majestix.ida.liu.se> mikpe@majestix.ida.liu.se (Mikael Pettersson) writes:
>What is the scope of the "type-name" in a cast expression?
>My impression is that the scope should be the entire surrounding
>expression (but not any further),

There is no such thing as "expression-scope" in C.  Except for labels (which
have function scope) and things declared within the parmlist of a non-defining
function prototype declaration (which have prototype scope, a very short
scope), each identifier has either block scope or file scope.  In your
examples, the identifiers have block scope.

(Some clarifications: externally-declared static objects have file scope but
internal linkage.  Externally-declared non-static objects have file scope and
external linkage, which used to be called "program scope".  Function
parameters have block scope, the block in question being the outermost block
of the function; this differs from function scope, since parameter identifiers
can be redeclared in an inner block, but label identifiers cannot.)

Reference: 3.1.2.1 pANS.  The same rules (except for prototypes) apply to
pre-ANSI C, but the pANS has the most precise description I've seen.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

dfp@cbnewsl.ATT.COM (david.f.prosser) (08/09/89)

In article <1324@majestix.ida.liu.se> mikpe@majestix.ida.liu.se (Mikael Pettersson) writes:
>I have a question for those who know the details about C declarations:
>
>  What is the scope of the "type-name" in a cast expression?
>
>My impression is that the scope should be the entire surrounding
>expression (but not any further), but the compilers I've tried
>[PCC and GCC on a Sun3] both in fact make the type visible from
>the enclosing statement and downwards to the end of the {}-block.

These compilers are correct w.r.t. the ANSI C draft.  Section 3.1.2.1:

	  Structure, union, and enumeration tags have scope that begins just
	after the appearance of the tag in a type specifier that declares
	the tag.  Each enumeration constant has scope that begins just after
	the appearance of its defining enumerator in an enumerator list.
	Any other identifier has scope that begins just after the completion
	of its declarator.

In this same section, the location where scope ends is specified.  For
file scope, it ends at the end of the translation unit; for block scope,
the } that ends the associate block; for function prototype scope, the
end of the associated function declarator; and for function scope (labels),
the } that ends the function.

There is no such thing as "expression scope".

Dave Prosser	...not an official X3J11 answer...

mikpe@majestix.ida.liu.se (Mikael Pettersson) (08/09/89)

In article <1324@majestix.ida.liu.se> I asked:
>  What is the scope of the "type-name" in a cast expression?
> [example of legal, but ugly, code omitted]
>
>AdvTHANX for any references to the appropriate "chapter and verse".

(Thanks to cris@mimsy (Chris Torek), mpl@attunix (Mike Lindner),
karl@haddock (Karl Heuer) and dfp@cbnewsl (Dave Prosser) for
pointing me in the right direction.)

K&R1, the appendix, section 11.1:
	"Members and tags follow the same scope rules as other
	 identifiers. The enum constants ... follow the same scope rules."

ditto, section 8.5:
	"A structure [or union] specifier [of the form]
		struct identifier { struct-decl-list }
	 declares the identifier to be the structure tag..."

ditto, section 8.6:
	[enumeration tags behave just like struct/union tags]

ditto, section 16.2:
	"type-name:		type-specifier ...
	 type-specifier:	struct-or-union-specifier | ..."

This means that the "type-name" in a cast (or sizeof) expression
may introduce new names in the closest surrounding block. They are
visible from the declaration point to the end of the block.

Now why didn't I see this before :-( [at 1 AM !? gimme a break]
(I'm in good company though; H&S-2nd ed. page 121 makes the same mistake:
	/* struct S is not defined here */
	i = sizeof( struct S { ... });	/* OK, but strange */
	j = sizeof( struct S );		/* probably illegal because
					struct S is still not defined */
:-> )

/Mike
(p.s. In case you're wondering why on earth one would want to examine
dubious constructs like these, it's because I'm working on a denotational
definition for C. It'll be a rather messy one..)
-- 
Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden
email: mpe@ida.liu.se  or  ..!{mcvax,munnari,uunet}!enea!liuida!mpe