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