Re: fun with declarations and definitions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Feb 05, 2009 at 08:28:11PM +0000, Al Viro wrote:
> typedef int T;
> extern void f(int);
> void g(int x)
> {
>         int (T);
>         T = x;
>         f(T);
> }
> 
> which is a valid C (we have T redeclared in the function scope as int,
> with declarator -> direct-declarator -> ( declarator ) -> ( identifier )
> as derivation).  sparse mistakes int (T) for typename, does *NOT* notice
> that typename has no business whatsoever being there and silently proceeds
> to T = ..., without having redeclared T as object of type int.  It sees
> typedef-name <something>, decides that it's a beginning of external-definition
> and vomits on the following =.
> 
> IOW, the rule in direct_declarator() for distinguishing between function
> and non-function is broken...

PS: note that C grammar has an ambiguity, resolved in constraints (6.7.5.3p11).
We have 3 different cases:
	* typename
	* normal declaration
	* parameter declaration
In the first case, int (T) is "function that takes T and returns int"; we can
have no identifiers in nested abstract-declarator, so there's no problem.
In the second case, int (T) is "declare X as object of type int"; we can't
have parameter-type-list or identifier-list without having seen an identifier.
Again, no problem.  In the third case, though, we can have both
	parameter-declaration -> declaration-specifiers declarator
and
	parameter-declaration -> declaration-specifiers abstract-declarator
with the former going through
	direct-declarator -> ( declarator ) -> ( identifier )
and the latter -
	direct-abstract-declarator ->
	direct-abstract-declarator? ( parameter-type-list) ->
	( parameter-type-list ) -> ( identifier )

It is resolved by "an identifier that can be interpreted either as a typedef
name or as a parameter name shall be taken as a typedef name".

IOW, direct_declarator() (which doubles for direct-abstract-declarator) should
have more than one-bit indication of which case we've got.  Right now it's
done by "have we passed a non-NULL ident ** to store the identifier being
declared"; that's not enough.  What we need is explicit 'is that a part of
parameter declaration' flag; then the rule turns into
	if (p && *p)
		fn = 1; /* we'd seen identifier already, can't be nested */
	else if match_op(next, ')')
		fn = 1; /* empty list can't be direct-declarator or
			 * direct-abstract-declarator */
	else
		fn = (in_parameter && lookup_type(next));

We also need to barf on lack of identifier in definition, unless it
has no storage class specifiers and the type has been struct/union/enum,
straight from the input - not a typedef or typeof resolving to such, but
that's a separate story.
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux