Chromium Code Reviews| Index: tools/clang/base_bind_rewriters/BaseBindRewriters.cpp |
| diff --git a/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp b/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp |
| index 55877c3055e83ff786d83e52c97a7aa31096960f..bea291b22e0c1d8d9e78153c276ff51571b58732 100644 |
| --- a/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp |
| +++ b/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp |
| @@ -29,42 +29,52 @@ using Replacements = std::vector<clang::tooling::Replacement>; |
| namespace { |
| -// Remove unneeded scoped_refptr<>::get on a receivers of method bind. |
| +// Replace base::Bind() to base::BindOnce() where resulting base::Callback is |
| +// implicitly converted into base::OnceCallback. |
| // Example: |
| // // Before |
| -// scoped_refptr<Foo> foo; |
| -// base::Bind(&Foo::Bar, foo.get()); |
| +// base::PostTask(FROM_HERE, base::Bind(&Foo)); |
| +// base::OnceCallback<void()> cb = base::Bind(&Foo); |
| // |
| // // After |
| -// scoped_refptr<Foo> foo; |
| -// base::Bind(&Foo::Bar, foo); |
| -// |
| -class ScopedRefptrGetRewriter : public MatchFinder::MatchCallback { |
| +// base::PostTask(FROM_HERE, base::BindOnce(&Foo)); |
| +// base::OnceCallback<void()> cb = base::BindOnce(&Foo); |
| +class BindOnceRewriter : public MatchFinder::MatchCallback { |
| public: |
| - explicit ScopedRefptrGetRewriter(Replacements* replacements) |
| + explicit BindOnceRewriter(Replacements* replacements) |
| : replacements_(replacements) {} |
| StatementMatcher GetMatcher() { |
| - auto is_bind_call = callee(namedDecl(hasName("::base::Bind"))); |
| - auto is_method_bind = hasArgument(0, hasType(memberPointerType())); |
| - auto is_raw_pointer_receiver = hasArgument(1, hasType(pointerType())); |
| - auto is_scoped_refptr_get_call = |
| - cxxMemberCallExpr(thisPointerType(namedDecl(hasName("scoped_refptr"))), |
| - callee(namedDecl(hasName("get")))); |
| - return callExpr(is_bind_call, is_method_bind, is_raw_pointer_receiver, |
| - hasArgument(1, is_scoped_refptr_get_call), |
| - hasArgument(1, stmt().bind("target"))); |
| + auto is_once_callback = hasType(classTemplateSpecializationDecl( |
| + hasName("::base::Callback"), |
| + hasTemplateArgument(1, equalsIntegralValue("0")), |
| + hasTemplateArgument(2, equalsIntegralValue("0")))); |
| + auto is_repeating_callback = hasType(classTemplateSpecializationDecl( |
| + hasName("::base::Callback"), |
| + hasTemplateArgument(1, equalsIntegralValue("1")), |
| + hasTemplateArgument(2, equalsIntegralValue("1")))); |
| + |
| + auto bind_call = |
| + callExpr(callee(namedDecl(hasName("::base::Bind")))).bind("target"); |
| + auto parameter_construction = |
| + cxxConstructExpr(is_repeating_callback, argumentCountIs(1), |
| + hasArgument(0, ignoringImplicit(bind_call))); |
| + auto constructor_conversion = cxxConstructExpr( |
| + is_once_callback, argumentCountIs(1), |
| + hasArgument(0, ignoringImplicit(parameter_construction))); |
| + auto implicit_conversion = implicitCastExpr( |
| + is_once_callback, hasSourceExpression(constructor_conversion)); |
| + return implicit_conversion; |
| } |
| void run(const MatchFinder::MatchResult& result) override { |
| - auto* target = result.Nodes.getNodeAs<clang::CXXMemberCallExpr>("target"); |
| - auto* member = llvm::cast<clang::MemberExpr>(target->getCallee()); |
| - assert(target && member && "Unexpected match! No Expr captured!"); |
| + auto* target = result.Nodes.getNodeAs<clang::CallExpr>("target"); |
| + auto* callee = llvm::dyn_cast<clang::DeclRefExpr>( |
| + target->getCallee()->IgnoreImplicit()); |
|
dcheng
2017/04/05 16:57:37
Out of curiosity, why do we have to IgnoreImplicit
tzik
2017/04/11 07:35:13
Hmm, that seems unneeded. Let me remove it.
There
|
| auto range = clang::CharSourceRange::getTokenRange( |
| - result.SourceManager->getSpellingLoc(member->getOperatorLoc()), |
| - result.SourceManager->getSpellingLoc(target->getLocEnd())); |
| - |
| - replacements_->emplace_back(*result.SourceManager, range, ""); |
| + result.SourceManager->getSpellingLoc(callee->getLocEnd()), |
| + result.SourceManager->getSpellingLoc(callee->getLocEnd())); |
| + replacements_->emplace_back(*result.SourceManager, range, "BindOnce"); |
| } |
| private: |
| @@ -87,10 +97,8 @@ int main(int argc, const char* argv[]) { |
| MatchFinder match_finder; |
| std::vector<clang::tooling::Replacement> replacements; |
| - |
| - ScopedRefptrGetRewriter scoped_refptr_rewriter(&replacements); |
| - match_finder.addMatcher(scoped_refptr_rewriter.GetMatcher(), |
| - &scoped_refptr_rewriter); |
| + BindOnceRewriter bind_once_rewriter(&replacements); |
| + match_finder.addMatcher(bind_once_rewriter.GetMatcher(), &bind_once_rewriter); |
| std::unique_ptr<clang::tooling::FrontendActionFactory> factory = |
| clang::tooling::newFrontendActionFactory(&match_finder); |