Finding function declaration?

If I have a checker for check::PreStmt<ReturnStmt>, how do I get from
the ReturnStmt to the function it is part of (I want to check
attributes on that function)?

I think you’ll need to use ParentMap from ASTContext.

I think you’ll need to use ParentMap from ASTContext.

Note that the parent-map is lazy-built (that is, the first time you get a parent, you build the parent-map for the whole TU), and thus has a pretty high cost. Usually we first try to get away with not using it.

Can you give a bit more context on what you’re trying to do?

I think you'll need to use ParentMap from ASTContext.

Note that the parent-map is lazy-built (that is, the first time you get a
parent, you build the parent-map for the whole TU), and thus has a pretty
high cost. Usually we first try to get away with not using it.

Can you give a bit more context on what you're trying to do?

Sorry for delay ... I am trying to label functions to have certain checks
done on their return values if an attribute is set on the function.

ParentMap appears not to work for this case (it stops finding parents once
you have the function body).

Currently, the only way I could make this work was to construct a map of
function bodies that have the attribute set in an AST observer, and then
using ParentMap to get back to the body, which is looked up in the map.

Doesn't seem optimal!

Manuel asked me for more info.

Given a checker like this:

class MyChecker :
public Checker< check::PreStmt > {

public:

void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;

};

void MyChecker::checkPreStmt(const ReturnStmt *RS,
CheckerContext &C) const {
RS->dump();

const Stmt *s = RS;

ParentMap &PM = C.getLocationContext()->getParentMap();

while ((s = PM.getParent(s)) != NULL) {
std::cerr << “------\n”;
s->dump();
}
}

And this as input:

int f(void)
{
return 1;
}

This is the output:

ReturnStmt 0x807cbdda8
`-IntegerLiteral 0x807cbdd88 ‘int’ 1

Ah, wrong parent map :slight_smile: the ast context has a function to retrieve parents that supports crossing into decls. I can look up the details when I’m back at a real computer …

BTW do you need the symbolic execution engine for what you want to check? If the ast is enough consider using a clang-tidy check, those are a bit simpler to write with the ast matchers.

Ah, wrong parent map :slight_smile: the ast context has a function to retrieve parents
that supports crossing into decls. I can look up the details when I'm back
at a real computer ...

Ah! Thanks.

BTW do you need the symbolic execution engine for what you want to check?
If the ast is enough consider using a clang-tidy check, those are a bit
simpler to write with the ast matchers.

I do need symbolic execution.

You can get the ASTContext from the CheckerContext, and then call getParents() on it.

Also cc’ing Anna and Jordan, who might have better ideas how to capture context info from a static analyzer check.

You can get the ASTContext from the CheckerContext, and then call getParents() on it.

CheckerContext is the way to go.

Ah, wrong parent map :slight_smile: the ast context has a function to retrieve
parents that supports crossing into decls. I can look up the details when
I'm back at a real computer ...

Ah! Thanks.

You can get the ASTContext from the CheckerContext, and then call
getParents() on it.

Mildly puzzled why there might be multiple parents, but in any case, it
works, thanks.

Templates.
Template instantiation works in clang by doing tree transformations from the template pattern to the instantiated template.
To make this scale, non-type-dependent statements are shared between all instantiations of a template (including its pattern).

Actually, you can solve the original problem a bit more easily: the current LocationContext (which is also in the CheckerContext) contains a reference to the current function, method, or block.

Jordan