<div dir="ltr">Currently the modernize-avoid-bind clang-tidy check only supports FunctionDecls.  So if you have this:<div><br></div><div>void foo(int x) {}</div><div><br></div><div>struct Foo {</div><div>    void operator()(int x) {}</div><div>};</div><div><br></div><div>int main() {</div><div>    Foo foo;</div><div></div><div>    auto x = std::bind(foo, 3);   // Catches this;</div><div>    auto y = std::bind(Foo{}, 3);   // Doesn't catch this<br></div><div>    auto z = std::bind(foo, 3);    // Doesn't catch this<br></div><div>}</div><div><br></div><div>I'd like to improve this.  Currently the matcher looks like this:</div><div><br></div><div>  Finder->addMatcher(<br>      callExpr(<br>          callee(namedDecl(hasName("::std::bind"))),<br>          hasArgument(0, declRefExpr(to(functionDecl().bind("f"))).bind("ref")))<br>          .bind("bind"),<br>      this);<br></div><div><br></div><div>How can I get it to match the other two cases?  I managed to get it to match the third case with this:</div><div><br></div><div>    Finder->addMatcher(<br>      callExpr(<br>          callee(namedDecl(hasName("::std::bind"))),<br>          hasArgument(0,</div><div>              anyOf(</div><div>                 declRefExpr(to(functionDecl().bind("f"))).bind("ref"),</div><div>                 declRefExpr(to(varDecl().bind("f")).bind("ref")))<br>          .bind("bind"),<br>      this);  <br></div><div><br></div><div>But I can't get it to match the second case where it's a temporary object.</div><div><br></div><div>The AST looks like this:</div><div><br></div><div>    |-DeclStmt 0x2303a87c288 <line:18:5, col:38><br>    | `-VarDecl 0x2303a85b778 <col:5, col:37> col:10 eeeeee 'std::_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar, int>' cinit<br>    |   `-ExprWithCleanups 0x2303a87c270 <col:19, col:37> 'std::_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar, int>'<br>    |     `-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<br>    |       `-MaterializeTemporaryExpr 0x2303a879018 <col:19, col:37> '_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar, int>' xvalue<br>    |         `-CallExpr 0x2303a85c0a0 <col:19, col:37> '_Binder<std::_Unforced, Bar, int>':'std::_Binder<std::_Unforced, Bar, int>'<br>    |           |-ImplicitCastExpr 0x2303a85c088 <col:19, col:24> '_Binder<std::_Unforced, Bar, int> (*)(Bar &&, int &&)' <FunctionToPointerDecay><br>    |           | `-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')<br>    |           |-MaterializeTemporaryExpr 0x2303a8785d0 <col:29, col:33> 'Bar' xvalue<br>    |           | `-CXXTemporaryObjectExpr 0x2303a85b860 <col:29, col:33> 'Bar' 'void () noexcept' zeroing<br>    |           `-MaterializeTemporaryExpr 0x2303a8785e8 <col:36> 'int':'int' xvalue<br>    |             `-IntegerLiteral 0x2303a85b970 <col:36> 'int' 3<br></div><div><br></div><div>But for whatever reason trying to match the first argument against materializeTemporaryExpr() doesn't seem to work.</div><div><br></div><div><br></div><div>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</div><div><br></div><div><div>    Finder->addMatcher(<br>      callExpr(<br>          callee(namedDecl(hasName("::std::bind"))))</div><div>          .bind("bind"),<br></div><div>      this);  </div></div><div><br></div><div>?  Suggestions appreciated.</div></div>