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 4f607edfe19262d174add2b3ebb3c66375277b66..670a636d01fb9e9b96ab6bb4d906b932879688c8 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(); |
} |
@@ -150,6 +158,44 @@ AST_MATCHER_P(clang::CXXMethodDecl, |
return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder); |
} |
+// Matches |x.m| CXXDependentScopeMemberExpr if InnerMatcher matches |x|. |
+AST_MATCHER_P(clang::CXXDependentScopeMemberExpr, |
+ hasBaseExpr, |
+ 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, |
+ hasDependentQualifier, |
+ clang::ast_matchers::internal::Matcher<clang::NestedNameSpecifier>, |
+ InnerMatcher) { |
+ clang::NestedNameSpecifier* qual = Node.getQualifier(); |
+ return qual && InnerMatcher.matches(*qual, Finder, Builder); |
+} |
+ |
+// Matches |T::m| DependentScopeDeclRefExpr if InnerMatcher matches |T|. |
+AST_MATCHER_P( |
+ clang::DependentScopeDeclRefExpr, |
+ dependentScopeIfQualifier, |
+ 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) |
@@ -477,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()); |
@@ -586,6 +650,14 @@ llvm::StringRef GetCurrentName(const clang::UnresolvedMemberExpr& expr) { |
return expr.getMemberName().getAsString(); |
} |
+llvm::StringRef GetCurrentName(const clang::DependentScopeDeclRefExpr& expr) { |
+ return expr.getDeclName().getAsString(); |
+} |
+ |
+llvm::StringRef GetCurrentName(const clang::CXXDependentScopeMemberExpr& expr) { |
+ return expr.getMember().getAsString(); |
+} |
+ |
llvm::StringRef GetCurrentName(const clang::NamedDecl& decl) { |
return decl.getName(); |
} |
@@ -696,6 +768,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); |
@@ -995,6 +1073,50 @@ 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), |
Łukasz Anforowicz
2016/08/25 18:11:13
This strips only 1 layer of indirection, but I don
|
+ 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)))))); |
Łukasz Anforowicz
2016/08/25 18:11:13
I don't know how I can avoid listing all the vario
|
+ |
+ // 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(dependentScopeIfQualifier( |
+ 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(anyOf( |
+ hasBaseExpr(hasType(blink_qual_type_matcher)), |
+ hasDependentQualifier(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()); |