[cfe-dev] Writing an AST matcher that matches any callable expression
Zachary Turner via cfe-dev
cfe-dev at lists.llvm.org
Tue Nov 5 14:32:57 PST 2019
Currently the modernize-avoid-bind clang-tidy check only supports
FunctionDecls. So if you have this:
void foo(int x) {}
struct Foo {
void operator()(int x) {}
};
int main() {
Foo foo;
auto x = std::bind(foo, 3); // Catches this;
auto y = std::bind(Foo{}, 3); // Doesn't catch this
auto z = std::bind(foo, 3); // Doesn't catch this
}
I'd like to improve this. Currently the matcher looks like this:
Finder->addMatcher(
callExpr(
callee(namedDecl(hasName("::std::bind"))),
hasArgument(0, declRefExpr(to(functionDecl().bind("f"))).bind("ref")))
.bind("bind"),
this);
How can I get it to match the other two cases? I managed to get it to
match the third case with this:
Finder->addMatcher(
callExpr(
callee(namedDecl(hasName("::std::bind"))),
hasArgument(0,
anyOf(
declRefExpr(to(functionDecl().bind("f"))).bind("ref"),
declRefExpr(to(varDecl().bind("f")).bind("ref")))
.bind("bind"),
this);
But I can't get it to match the second case where it's a temporary object.
The AST looks like this:
|-DeclStmt 0x2303a87c288 <line:18:5, col:38>
| `-VarDecl 0x2303a85b778 <col:5, col:37> col:10 eeeeee
'std::_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar,
int>' cinit
| `-ExprWithCleanups 0x2303a87c270 <col:19, col:37>
'std::_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar,
int>'
| `-CXXConstructExpr 0x2303a87c240 <col:19, col:37>
'std::_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar,
int>' 'void (std::_Binder<std::_Unforced, Bar, int> &&) noexcept' elidable
| `-MaterializeTemporaryExpr 0x2303a879018 <col:19, col:37>
'_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar,
int>' xvalue
| `-CallExpr 0x2303a85c0a0 <col:19, col:37>
'_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar, int>'
| |-ImplicitCastExpr 0x2303a85c088 <col:19, col:24>
'_Binder<std::_Unforced, Bar, int> (*)(Bar &&, int &&)'
<FunctionToPointerDecay>
| | `-DeclRefExpr 0x2303a85bff0 <col:19, col:24>
'_Binder<std::_Unforced, Bar, int> (Bar &&, int &&)' lvalue Function
0x2303a85bea8 'bind' '_Binder<std::_Unforced, Bar, int> (Bar &&, int &&)'
(FunctionTemplate 0x2303a7462a8 'bind')
| |-MaterializeTemporaryExpr 0x2303a8785d0 <col:29, col:33>
'Bar' xvalue
| | `-CXXTemporaryObjectExpr 0x2303a85b860 <col:29, col:33>
'Bar' 'void () noexcept' zeroing
| `-MaterializeTemporaryExpr 0x2303a8785e8 <col:36>
'int':'int' xvalue
| `-IntegerLiteral 0x2303a85b970 <col:36> 'int' 3
But for whatever reason trying to match the first argument against
materializeTemporaryExpr() doesn't seem to work.
I'm also wondering if maybe I don't need to go through all of this. The
first argument to std::bind() is always a callable anyway, so why do I need
to match it against anything? Maybe I can just use
Finder->addMatcher(
callExpr(
callee(namedDecl(hasName("::std::bind"))))
.bind("bind"),
this);
? Suggestions appreciated.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20191105/9de0fc34/attachment.html>
More information about the cfe-dev
mailing list