| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This implements a Clang tool to convert all instances of std::string("") to | 5 // This implements a Clang tool to convert all instances of std::string("") to |
| 6 // std::string(). The latter is more efficient (as std::string doesn't have to | 6 // std::string(). The latter is more efficient (as std::string doesn't have to |
| 7 // take a copy of an empty string) and generates fewer instructions as well. It | 7 // take a copy of an empty string) and generates fewer instructions as well. It |
| 8 // should be run using the tools/clang/scripts/run_tool.py helper. | 8 // should be run using the tools/clang/scripts/run_tool.py helper. |
| 9 | 9 |
| 10 #include "clang/ASTMatchers/ASTMatchers.h" | 10 #include "clang/ASTMatchers/ASTMatchers.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 | 89 |
| 90 void SetupMatchers(MatchFinder* match_finder); | 90 void SetupMatchers(MatchFinder* match_finder); |
| 91 | 91 |
| 92 private: | 92 private: |
| 93 ConstructorCallback constructor_callback_; | 93 ConstructorCallback constructor_callback_; |
| 94 InitializerCallback initializer_callback_; | 94 InitializerCallback initializer_callback_; |
| 95 TemporaryCallback temporary_callback_; | 95 TemporaryCallback temporary_callback_; |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 void EmptyStringConverter::SetupMatchers(MatchFinder* match_finder) { | 98 void EmptyStringConverter::SetupMatchers(MatchFinder* match_finder) { |
| 99 const auto& constructor_call = | 99 const clang::ast_matchers::StatementMatcher& constructor_call = |
| 100 id("call", | 100 id("call", |
| 101 constructExpr( | 101 constructExpr( |
| 102 hasDeclaration(methodDecl(ofClass(hasName("std::basic_string")))), | 102 hasDeclaration(methodDecl(ofClass(hasName("std::basic_string")))), |
| 103 argumentCountIs(2), | 103 argumentCountIs(2), |
| 104 hasArgument(0, id("literal", stringLiteral())), | 104 hasArgument(0, id("literal", stringLiteral())), |
| 105 hasArgument(1, defaultArgExpr()))); | 105 hasArgument(1, defaultArgExpr()))); |
| 106 | 106 |
| 107 // Note that expr(has()) in the matcher is significant; the Clang AST wraps | 107 // Note that expr(has()) in the matcher is significant; the Clang AST wraps |
| 108 // calls to the std::string constructor with exprWithCleanups nodes. Without | 108 // calls to the std::string constructor with exprWithCleanups nodes. Without |
| 109 // the expr(has()) matcher, the first and last rules would not match anything! | 109 // the expr(has()) matcher, the first and last rules would not match anything! |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 int result = | 182 int result = |
| 183 tool.run(clang::tooling::newFrontendActionFactory(&match_finder)); | 183 tool.run(clang::tooling::newFrontendActionFactory(&match_finder)); |
| 184 if (result != 0) | 184 if (result != 0) |
| 185 return result; | 185 return result; |
| 186 | 186 |
| 187 // Each replacement line should have the following format: | 187 // Each replacement line should have the following format: |
| 188 // r:<file path>:<offset>:<length>:<replacement text> | 188 // r:<file path>:<offset>:<length>:<replacement text> |
| 189 // Only the <replacement text> field can contain embedded ":" characters. | 189 // Only the <replacement text> field can contain embedded ":" characters. |
| 190 // TODO(dcheng): Use a more clever serialization. | 190 // TODO(dcheng): Use a more clever serialization. |
| 191 llvm::outs() << "==== BEGIN EDITS ====\n"; | 191 llvm::outs() << "==== BEGIN EDITS ====\n"; |
| 192 for (const Replacement& r : replacements) { | 192 for (Replacements::const_iterator it = replacements.begin(); |
| 193 llvm::outs() << "r:" << r.getFilePath() << ":" << r.getOffset() << ":" | 193 it != replacements.end(); ++it) { |
| 194 << r.getLength() << ":" << r.getReplacementText() << "\n"; | 194 llvm::outs() << "r:" << it->getFilePath() << ":" << it->getOffset() << ":" |
| 195 << it->getLength() << ":" << it->getReplacementText() << "\n"; |
| 195 } | 196 } |
| 196 llvm::outs() << "==== END EDITS ====\n"; | 197 llvm::outs() << "==== END EDITS ====\n"; |
| 197 | 198 |
| 198 return 0; | 199 return 0; |
| 199 } | 200 } |
| OLD | NEW |