| 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()); | 
|  |