How do I retrieve all non-local variables a function has access to?

Hi!

I’m trying to implement a primitive reaching definitions algorithm for C++, but am struggling a bit. I’d like to make all function calls be definitions of global/static variables, but I can’t seem to retrieve them.

I tried using AST matchers (match() to be precise) on a TranslationUnitDecl, but I can’t seem to be able to match varDecl()s at all. Is there a reason for this? When I use clang-query, “m varDecl()” works like a charm, but match() doesn’t seem to.

In any case, I can retrieve local variables by matching declStmt() and some non-local ones when inspecting the LHS of assignments (I need to do this anyways to find all definitions), but I feel like I’m not the first person trying to recover all accessible variables to a function. Could anyone give me some guidance please? :slight_smile:

Cheers!
Kristóf

P.S. This is the patch I’m working on: https://reviews.llvm.org/D64991

Note that match() doesn't automatically recursively descend into the node. So it should be either matchAST(varDecl()) or match(translationUnitDecl(forEachDescendant(varDecl()))).

Generally, though, i'd recommend taking a look at DeclContext's methods to see if you have anything readily available. Or, at least, you should probably take a look how DeclContext::lookup() is implemented.

Hi Kristóf,

I'm trying to implement a primitive reaching definitions algorithm for C++,
but am struggling a bit.

Is this about finding unused data members and functions where the
compiler can't detect them as that requires CTU analysis?

If so, you might want to look at
<https://cgit.freedesktop.org/libreoffice/core/tree/compilerplugins/clang/unusedmethods.cxx>,
and other unused* files in the same directory, which use the clang AST
to find unused code; though they don't use AST matchers.

Regards,

Miklos

Hi Kristóf,

I’m trying to implement a primitive reaching definitions algorithm for C++,
but am struggling a bit.

Is this about finding unused data members and functions where the
compiler can’t detect them as that requires CTU analysis?

No, not really, I’m trying to find reaching definitions to variables (for example when they caused a division by zero error) to teach the analyzer that certain parts of the program are important, and make it emit bug reports that explain control flow around them better.

If so, you might want to look at
<https://cgit.freedesktop.org/libreoffice/core/tree/compilerplugins/clang/unusedmethods.cxx>,
and other unused* files in the same directory, which use the clang AST
to find unused code; though they don’t use AST matchers.

I took a look and I think this isn’t what I’m looking for specifically, but thanks for the suggestion! :slight_smile:

Okay so the solution was this:

DeclContext *DC = /function’s decl/->getDeclContext();
while (DC) {
DC = DC->getPrimaryContext();
for (const Decl *D : DC->decls()) {
const VarDecl *NonLocalVar = dyn_cast(D);
if (!NonLocalVar)
continue;
// whatever
}
DC = DC->getParent();
}

Thanks for chipping in!