Index: tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp |
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp |
index 21a696afa0d65de0ba6d3a2ee9d3fa36b39bef60..7d7b67b4744796c116ea66003d26ada30269bd19 100644 |
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp |
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp |
@@ -55,6 +55,14 @@ const clang::ast_matchers::internal:: |
VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> |
unresolvedMemberExpr; |
+const clang::ast_matchers::internal:: |
+ VariadicDynCastAllOfMatcher<clang::Expr, clang::DependentScopeDeclRefExpr> |
+ dependentScopeDeclRefExpr; |
+ |
+const clang::ast_matchers::internal:: |
+ VariadicDynCastAllOfMatcher<clang::Expr, clang::CXXDependentScopeMemberExpr> |
+ cxxDependentScopeMemberExpr; |
+ |
AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { |
return Node.isOverloadedOperator(); |
} |
@@ -154,6 +162,34 @@ AST_MATCHER_P(clang::CXXMethodDecl, |
return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder); |
} |
+// Matches |x.m| CXXDependentScopeMemberExpr if InnerMatcher matches |x|. |
+AST_MATCHER_P(clang::CXXDependentScopeMemberExpr, |
+ hasBaseExprMissingOrMatching, |
+ clang::ast_matchers::internal::Matcher<clang::Expr>, |
+ InnerMatcher) { |
+ clang::Expr* base_expr = Node.isImplicitAccess() ? nullptr : Node.getBase(); |
+ return !base_expr || InnerMatcher.matches(*base_expr, Finder, Builder); |
+} |
+ |
+// Matches |T::m| CXXDependentScopeMemberExpr if InnerMatcher matches |T|. |
+AST_MATCHER_P( |
+ clang::CXXDependentScopeMemberExpr, |
+ hasQualifierMissingOrMatching, |
+ clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>, |
+ InnerMatcher) { |
+ clang::NestedNameSpecifier* qual = Node.getQualifier(); |
+ return !qual || InnerMatcher.matches(*qual, Finder, Builder); |
+} |
+ |
+// Matches |const Class<T>&| QualType if InnerMatcher matches |Class<T>|. |
+AST_MATCHER_P(clang::QualType, |
+ hasUnderlyingType, |
+ clang::ast_matchers::internal::Matcher<clang::Type>, |
+ InnerMatcher) { |
+ const clang::Type* type = Node.getTypePtrOrNull(); |
+ return type && InnerMatcher.matches(*type, Finder, Builder); |
+} |
+ |
bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl, |
const char* class_name) { |
if (decl.getParent()->getQualifiedNameAsString() == class_name) |
@@ -487,6 +523,24 @@ struct TargetNodeTraits<clang::DeclRefExpr> { |
}; |
template <> |
+struct TargetNodeTraits<clang::DependentScopeDeclRefExpr> { |
+ static clang::SourceLocation GetLoc( |
+ const clang::DependentScopeDeclRefExpr& expr) { |
+ return expr.getLocation(); |
+ } |
+ static const char* GetName() { return "expr"; } |
+}; |
+ |
+template <> |
+struct TargetNodeTraits<clang::CXXDependentScopeMemberExpr> { |
+ static clang::SourceLocation GetLoc( |
+ const clang::CXXDependentScopeMemberExpr& expr) { |
+ return expr.getMemberLoc(); |
+ } |
+ static const char* GetName() { return "expr"; } |
+}; |
+ |
+template <> |
struct TargetNodeTraits<clang::CXXCtorInitializer> { |
static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { |
assert(init.isWritten()); |
@@ -592,12 +646,24 @@ class DeclRewriterBase : public RewriterBase<TargetNode> { |
} |
}; |
-llvm::StringRef GetCurrentName(const clang::UnresolvedMemberExpr& expr) { |
- return expr.getMemberName().getAsString(); |
+clang::DeclarationName GetUnresolvedName( |
+ const clang::UnresolvedMemberExpr& expr) { |
+ return expr.getMemberName(); |
} |
-llvm::StringRef GetCurrentName(const clang::NamedDecl& decl) { |
- return decl.getName(); |
+clang::DeclarationName GetUnresolvedName( |
+ const clang::DependentScopeDeclRefExpr& expr) { |
+ return expr.getDeclName(); |
+} |
+ |
+clang::DeclarationName GetUnresolvedName( |
+ const clang::CXXDependentScopeMemberExpr& expr) { |
+ return expr.getMember(); |
+} |
+ |
+clang::DeclarationName GetUnresolvedName( |
+ const clang::UnresolvedUsingValueDecl& decl) { |
+ return decl.getDeclName(); |
} |
// Returns whether |expr| is a callee of a method or function call. |
@@ -627,7 +693,22 @@ class UnresolvedRewriterBase : public RewriterBase<TargetNode> { |
void run(const MatchFinder::MatchResult& result) override { |
const TargetNode& expr = Base::GetTargetNode(result); |
- llvm::StringRef old_name = GetCurrentName(expr); |
+ |
+ clang::DeclarationName unresolved_name = GetUnresolvedName(expr); |
+ switch (unresolved_name.getNameKind()) { |
+ // Do not rewrite this: |
+ // return operator T*(); |
+ // into this: |
+ // return Operator type - parameter - 0 - 0 * T * (); |
+ case clang::DeclarationName::NameKind::CXXConversionFunctionName: |
+ case clang::DeclarationName::NameKind::CXXOperatorName: |
+ case clang::DeclarationName::NameKind::CXXLiteralOperatorName: |
+ return; |
+ default: |
+ break; |
+ } |
+ |
+ llvm::StringRef old_name = unresolved_name.getAsString(); |
std::string new_name; |
if (GuessNameForUnresolvedDependentNode(expr, *result.Context, old_name, |
new_name)) { |
@@ -710,6 +791,12 @@ using UnresolvedUsingValueDeclRewriter = |
using UsingDeclRewriter = DeclRewriterBase<clang::UsingDecl, clang::NamedDecl>; |
+using DependentScopeDeclRefExprRewriter = |
+ UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>; |
+ |
+using CXXDependentScopeMemberExprRewriter = |
+ UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>; |
+ |
} // namespace |
static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); |
@@ -1034,6 +1121,51 @@ int main(int argc, const char* argv[]) { |
UsingDeclRewriter using_decl_rewriter(&replacements); |
match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter); |
+ // Matches any QualType that refers to a blink type: |
+ // - const blink::Foo& |
+ // - blink::Foo* |
+ // - blink::Foo<T> |
+ // - ... |
+ auto blink_qual_type_matcher = qualType( |
+ anyOf(pointsTo(in_blink_namespace), references(in_blink_namespace), |
+ hasUnderlyingType(anyOf( |
+ enumType(hasDeclaration(in_blink_namespace)), |
+ recordType(hasDeclaration(in_blink_namespace)), |
+ templateSpecializationType(hasDeclaration(in_blink_namespace)), |
+ templateTypeParmType(hasDeclaration(in_blink_namespace)), |
+ typedefType(hasDeclaration(in_blink_namespace)))))); |
+ |
+ // Template-dependent decl lookup ======== |
+ // Given |
+ // template <typename T> void f() { T::foo(); } |
+ // matches |T::foo|. |
+ auto dependent_scope_decl_ref_expr_matcher = |
+ expr(id("expr", dependentScopeDeclRefExpr(has(nestedNameSpecifier( |
+ specifiesType(blink_qual_type_matcher)))))); |
+ DependentScopeDeclRefExprRewriter dependent_scope_decl_ref_expr_rewriter( |
+ &replacements); |
+ match_finder.addMatcher(dependent_scope_decl_ref_expr_matcher, |
+ &dependent_scope_decl_ref_expr_rewriter); |
+ |
+ // Template-dependent member lookup ======== |
+ // Given |
+ // template <typename T> |
+ // class Foo { |
+ // void f() { T::foo(); } |
+ // void g(T x) { x.bar(); } |
+ // }; |
+ // matches |T::foo| and |x.bar|. |
+ auto cxx_dependent_scope_member_expr_matcher = expr( |
+ id("expr", |
+ cxxDependentScopeMemberExpr(allOf( |
+ hasBaseExprMissingOrMatching(hasType(blink_qual_type_matcher)), |
+ hasQualifierMissingOrMatching( |
+ specifiesType(blink_qual_type_matcher)))))); |
+ CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( |
+ &replacements); |
+ match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, |
+ &cxx_dependent_scope_member_expr_rewriter); |
+ |
std::unique_ptr<clang::tooling::FrontendActionFactory> factory = |
clang::tooling::newFrontendActionFactory(&match_finder); |
int result = tool.run(factory.get()); |