Chromium Code Reviews| Index: tools/clang/value_cleanup/ListValueRewriter.cpp | 
| diff --git a/tools/clang/value_cleanup/ListValueRewriter.cpp b/tools/clang/value_cleanup/ListValueRewriter.cpp | 
| index ce27dd1f5b41368ddbf1ac5eb19955ae67d3bee2..b5e5260eab1e6210d71425bb85079440e94f6246 100644 | 
| --- a/tools/clang/value_cleanup/ListValueRewriter.cpp | 
| +++ b/tools/clang/value_cleanup/ListValueRewriter.cpp | 
| @@ -108,11 +108,39 @@ void ListValueRewriter::AppendStringCallback::run( | 
| AppendCallback::run(result); | 
| } | 
| +ListValueRewriter::AppendReleasedUniquePtrCallback:: | 
| + AppendReleasedUniquePtrCallback(Replacements* replacements) | 
| + : replacements_(replacements) {} | 
| + | 
| +void ListValueRewriter::AppendReleasedUniquePtrCallback::run( | 
| + const MatchFinder::MatchResult& result) { | 
| + auto* object_expr = result.Nodes.getNodeAs<clang::Expr>("objectExpr"); | 
| + bool arg_is_rvalue = object_expr->Classify(*result.Context).isRValue(); | 
| + | 
| + // Remove .release() | 
| + auto* member_call = | 
| + result.Nodes.getNodeAs<clang::CXXMemberCallExpr>("memberCall"); | 
| + auto* member_expr = result.Nodes.getNodeAs<clang::MemberExpr>("memberExpr"); | 
| 
 
vmpstr
2016/06/09 00:15:59
Does this always find the release/last method?
I'
 
dcheng
2016/06/09 00:57:12
This will match the rvalue reference case, with th
 
 | 
| + clang::CharSourceRange release_range = clang::CharSourceRange::getTokenRange( | 
| + member_expr->getOperatorLoc(), member_call->getLocEnd()); | 
| + replacements_->emplace(*result.SourceManager, release_range, | 
| + arg_is_rvalue ? "" : ")"); | 
| + | 
| + if (arg_is_rvalue) | 
| + return; | 
| + | 
| + // Insert `std::move(' for non-rvalue expressions. | 
| + clang::CharSourceRange insertion_range = clang::CharSourceRange::getCharRange( | 
| + object_expr->getLocStart(), object_expr->getLocStart()); | 
| + replacements_->emplace(*result.SourceManager, insertion_range, "std::move("); | 
| +} | 
| + | 
| ListValueRewriter::ListValueRewriter(Replacements* replacements) | 
| : append_boolean_callback_(replacements), | 
| append_integer_callback_(replacements), | 
| append_double_callback_(replacements), | 
| - append_string_callback_(replacements) {} | 
| + append_string_callback_(replacements), | 
| + append_released_unique_ptr_callback_(replacements) {} | 
| void ListValueRewriter::RegisterMatchers(MatchFinder* match_finder) { | 
| auto is_list_append = | 
| @@ -191,4 +219,26 @@ void ListValueRewriter::RegisterMatchers(MatchFinder* match_finder) { | 
| argumentCountIs(1), | 
| hasArgument(0, id("argExpr", expr())))))))))), | 
| &append_string_callback_); | 
| + | 
| + auto is_unique_ptr_release = | 
| + allOf(callee(cxxMethodDecl( | 
| + hasName("release"), | 
| + ofClass(cxxRecordDecl(hasName("::std::unique_ptr"))))), | 
| + argumentCountIs(0)); | 
| + | 
| + // base::ListValue::Append(ReturnsUniquePtr().release()) | 
| + // => base::ListValue::Append(ReturnsUniquePtr()) | 
| + // or | 
| + // base::ListValue::Append(unique_ptr_var.release()) | 
| + // => base::ListValue::Append(std::move(unique_ptr_var)) | 
| + match_finder->addMatcher( | 
| + cxxMemberCallExpr( | 
| + is_list_append, | 
| + hasArgument( | 
| + 0, ignoringParenImpCasts( | 
| + id("memberCall", | 
| + cxxMemberCallExpr(has(id("memberExpr", memberExpr())), | 
| + is_unique_ptr_release, | 
| + on(id("objectExpr", expr()))))))), | 
| 
 
vmpstr
2016/06/09 00:15:59
:)))))))))))
 
 | 
| + &append_released_unique_ptr_callback_); | 
| } |