[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