[cfe-dev] How do I detect global variables?

Eli Friedman eli.friedman at gmail.com
Tue Jul 22 16:56:17 PDT 2008


On Tue, Jul 22, 2008 at 2:18 PM, Nico Weber <nicolasweber at gmx.de> wrote:
> Now, what's the best method to find all global variable definitions?
> (global functions are not interesting, and I don't want to find
> globals form system headers).
>
> Right now, I'm trying to overwrite ActOnDeclarator. In there, I only
> look at variables with FileContext, and reject everything that is
> `extern` (I only want the definitions of globals). Furthermore, I try
> to skip functions by checking for PQ_FunctionSpecifier, but that does
> not seem to skip all functions (for example, the `main` function of my
> test input program).

Right... it would be easier to do this from an ASTConsumer, where you
would have access to types.  Fundamentally, in C, it's impossible to
tell apart a global function declaration and a global variable
declaration without resolving typedefs and __typeof expressions.
Since that's beyond the scope of the parser, you'll either need to use
Sema, do these yourself, or be a bit conservative about printing out
things that aren't actually globals.

Examples of function declarations without an explicit type declarator:
typedef int x();
x z;
__typeof(z) r;

Also, with AST information, you can easily do other interesting
things, like printing the canonical type (the type stripped of
typedefs), or printing out all globals of a particular type, or
pretty-printing initializers, or more easily supporting C++
namespaces/classes using a visitor pattern.

If you're willing to be conservative with the cases of declaring a
function with __typeof or typedef, it isn't too hard. The check you
need is for whether the outermost type declarator is a function type
declarator (untested, but something like
"D.getTypeObject(D.getNumTypeObjects() - 1).Kind ==
DeclaratorChunk::Function").

PQ_FunctionSpecifier isn't even close to what you want; it essentially
tracks whether "inline" was specified on the declaration.

If you want to try and resolve typedefs, try looking at the
implementation of MinimalAction in clang/lib/Parser/MinimalAction.cpp.
 Resolving __typeof would require implementing a large chunk of Sema,
so that's probably not something you want to mess with.

> And it does not skip stuff that comes from angle-
> bracket includes:

clang/lib/Sema/SemaDecl.cpp does this as follows:

  SourceManager &SrcMgr = Context.getSourceManager();
  HeaderSearch &HdrInfo = PP.getHeaderSearchInfo();
  const FileEntry *OldDeclFile = SrcMgr.getFileEntryForLoc(Old->getLocation());
  if (OldDeclFile) {
    DirectoryLookup::DirType OldDirType = HdrInfo.getFileDirFlavor(OldDeclFile);
    // Allow reclarations in both SystemHeaderDir and ExternCSystemHeaderDir.
    if (OldDirType != DirectoryLookup::NormalHeaderDir)
      return New;
  }

That said, we should probably move this into some sort of helper
method on the Preprocessor class or something like that.  Would
someone more familiar with the Preprocessor mind commenting?

>   Action::DeclTy *
>   ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup) {
>     // Print names of global variables
>     if (D.getContext() == Declarator::FileContext) {
>       IdentifierInfo *II = D.getIdentifier();
>       const DeclSpec& DS = D.getDeclSpec();
>
>       if (DS.getStorageClassSpec() != DeclSpec::SCS_extern
>           && (DS.getParsedSpecifiers() &
> DeclSpec::PQ_FunctionSpecifier) == 0) {
>         cerr << "Found global declarator " << II->getName()
>              << " " << D.getNumTypeObjects() << endl;
>       }
>     }

The last line of this method must be "return
MinimalAction::ActOnDeclarator(S, D, LastInGroup);"; otherwise, you'll
mess up the implementation of MinimalAction::isTypeName(), which in
turn will cause parse errors.

> Can you give me a few hints where I should look to add that
> functionality?

If you want to contribute it to clang?  My first instinct is
clang/Driver/ASTConsumers.cpp, assuming you wrote an implementation as
an ASTConsumer.  That said, I'm not sure how useful this would be; if
anyone else would find this useful, please comment.

-Eli



More information about the cfe-dev mailing list