All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: Derek M Jones <derek@knosof.co.uk>
Cc: Christopher Li <sparse@chrisli.org>, linux-sparse@vger.kernel.org
Subject: Re: fun with declarations and definitions
Date: Thu, 5 Feb 2009 21:19:21 +0000	[thread overview]
Message-ID: <20090205211921.GP28946@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20090205202811.GO28946@ZenIV.linux.org.uk>

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.

  reply	other threads:[~2009-02-05 21:19 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-02  7:30 fun with declarations and definitions Al Viro
2009-02-02 20:17 ` Christopher Li
2009-02-02 20:58   ` Al Viro
2009-02-02 22:25     ` Christopher Li
2009-02-03  3:07 ` Christopher Li
2009-02-03  4:13   ` Al Viro
2009-02-05 18:40     ` Christopher Li
2009-02-05 18:47       ` Derek M Jones
2009-02-05 20:28         ` Al Viro
2009-02-05 21:19           ` Al Viro [this message]
2009-02-06  5:36             ` Al Viro
2009-02-09  7:52               ` Christopher Li
2009-02-09  8:54                 ` Al Viro
2009-02-05 22:41           ` Christopher Li
2009-02-05 23:22             ` Al Viro
2009-02-03  4:41   ` Al Viro
2009-02-03  6:28     ` Ralf Wildenhues
2009-02-05 18:52     ` Christopher Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090205211921.GP28946@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=derek@knosof.co.uk \
    --cc=linux-sparse@vger.kernel.org \
    --cc=sparse@chrisli.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.