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 85a9661d70f190f8cc0f4857067739b9de772cf6..24fd5e323ee558bdd4f4c0d35d40ff2c02e7668b 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(); |
} |
@@ -158,6 +166,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, |
+ hasBaseType, |
+ 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) |
@@ -491,6 +527,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()); |
@@ -602,6 +656,16 @@ clang::DeclarationName GetUnresolvedName( |
} |
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(); |
} |
@@ -633,7 +697,22 @@ class UnresolvedRewriterBase : public RewriterBase<TargetNode> { |
void run(const MatchFinder::MatchResult& result) override { |
const TargetNode& expr = Base::GetTargetNode(result); |
- llvm::StringRef old_name = GetUnresolvedName(expr).getAsString(); |
+ |
+ 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)) { |
@@ -716,6 +795,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); |
@@ -1042,6 +1127,65 @@ 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> |
+ // - ... |
+ // TODO(lukasza): The matchers below can be simplified after |
+ // https://llvm.org/bugs/show_bug.cgi?id=30331 is fixed. |
+ // Simplified matchers: |
+ // auto blink_qual_type_base_matcher = |
+ // qualType(hasDeclaration(in_blink_namespace)); |
+ // auto blink_qual_type_matcher = qualType(anyOf( |
+ // blink_qual_type_base_matcher, |
+ // pointsTo(blink_qual_type_base_matcher), |
+ // references(blink_qual_type_base_matcher))); |
+ auto blink_qual_type_bug_workaround_matcher1 = hasBaseType( |
+ 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)))); |
+ auto blink_qual_type_base_matcher = |
+ qualType(anyOf(blink_qual_type_bug_workaround_matcher1, |
+ hasBaseType(elaboratedType( |
+ namesType(blink_qual_type_bug_workaround_matcher1))))); |
+ auto blink_qual_type_matcher = |
+ qualType(anyOf(blink_qual_type_base_matcher, pointsTo(in_blink_namespace), |
+ references(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()); |