[cfe-dev] Implicitly declared K&R parameters.
Douglas Gregor
dgregor at apple.com
Wed Sep 29 08:27:28 PDT 2010
On Sep 29, 2010, at 5:11 AM, Enea Zaffanella wrote:
> Hello.
>
> Consider the following K&R function definition:
>
> void foo(implicit, explicit)
> int explicit;
> {}
>
> While traversing the corresponding AST chunk, we would like to be able
> to distinguish between parameter 'explicit' (which was explicitly
> declared) from parameter 'implicit' (which was implicitly declared).
>
> Is there a reliable way of distinguishing between the two cases?
>
> First (failed) attempt:
> Usually, implicit declarations are provided with an invalid source
> location, but this is false for the case at hand: the location of the
> identifier is obtained.
>
> Second (failed) attempt:
> Since 'implicit' has no type written, we also checked for an invalid
> getTypeSpecStartLoc(), but again we obtained a valid location, which is
> the same as that of the identifier. Here are the relevant source lines
> in SemaDecl.cpp:
>
> // Implicitly declare the argument as type 'int' for lack of a better
> // type.
> DeclSpec DS;
> const char* PrevSpec; // unused
> unsigned DiagID; // unused
> DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
> PrevSpec, DiagID);
>
> Third (maybe working) attempt:
> We ended up checking whether or not the two source locations mentioned
> above happen to be the same source location:
>
> bool implicit = (param.getLocation() == param.getTypeSpecStartLoc());
>
> This was working as expected on the few tests we tried.
> However, we would like to avoid making wild guesses: is such a property
> a valid (i.e., supported) clang invariant or is it just working by chance?
It probably comes from building a "trivial" TypeSourceInfo for the parameter type, using the location of the identifier. It's somewhat of an accident, but it's also unlikely to change.
> For clarity, would you accept the addition of a method
>
> bool ParmVarDecl::isImplicitIntKNRParameter() const {
> return getLocation() == getTypeSpecTypeLoc();
> }
>
> ?
There are likely to be other implicitly-generated ParmVarDecls that are likely to be caught by this, e.g., the ParmVarDecls for an implicitly-generated copy constructor or copy assignment operator. At the very least, this should check that getLocation() is valid and that the parameter is from a K&R function definition.
However, I do wonder you're really trying to solve the larger problem of "implicit int", which would likely require something completely different. For example, here's some ugly C89 code:
f(x, y) {
register z = x + y;
return z;
}
We'll don't keep track of the implicit int in f, x, y, or z. So, while I'm not opposed to the method you're suggesting (with fixes), I think it's only solving part of the problem that you're probably working on.
- Doug
More information about the cfe-dev
mailing list