[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