steveire updated this revision to Diff 267750.
steveire added a comment.

Update


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80961/new/

https://reviews.llvm.org/D80961

Files:
  clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
  clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
  clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
  clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
  clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
  clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
  clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
  clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
  clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
  clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
  
clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
  clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
  clang/include/clang/AST/ASTNodeTraverser.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/AST/ASTDumper.cpp
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/AST/ASTTraverserTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
  clang/unittests/Tooling/TransformerTest.cpp

Index: clang/unittests/Tooling/TransformerTest.cpp
===================================================================
--- clang/unittests/Tooling/TransformerTest.cpp
+++ clang/unittests/Tooling/TransformerTest.cpp
@@ -695,6 +695,70 @@
   EXPECT_EQ(ErrorCount, 0);
 }
 
+TEST_F(TransformerTest, TemplateInstantiation) {
+
+  std::string NonTemplatesInput = R"cpp(
+struct S {
+  int m_i;
+};
+)cpp";
+  std::string NonTemplatesExpected = R"cpp(
+struct S {
+  safe_int m_i;
+};
+)cpp";
+
+  std::string TemplatesInput = R"cpp(
+template<typename T>
+struct TemplStruct {
+  TemplStruct() {}
+  ~TemplStruct() {}
+
+private:
+  T m_t;
+};
+
+void instantiate()
+{
+  TemplStruct<int> ti;
+}
+)cpp";
+
+  auto MatchedField = fieldDecl(hasType(asString("int"))).bind("theField");
+
+  // Changes the 'int' in 'S', but not the 'T' in 'TemplStruct':
+  testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedField),
+                    changeTo(cat("safe_int ", name("theField")))),
+           NonTemplatesInput + TemplatesInput,
+           NonTemplatesExpected + TemplatesInput);
+
+  // In AsIs mode, template instantiations are modified, which is
+  // often not desired:
+
+  std::string IncorrectTemplatesExpected = R"cpp(
+template<typename T>
+struct TemplStruct {
+  TemplStruct() {}
+  ~TemplStruct() {}
+
+private:
+  safe_int m_t;
+};
+
+void instantiate()
+{
+  TemplStruct<int> ti;
+}
+)cpp";
+
+  // Changes the 'int' in 'S', and (incorrectly) the 'T' in 'TemplStruct':
+  testRule(makeRule(traverse(TK_AsIs, MatchedField),
+                    changeTo(cat("safe_int ", name("theField")))),
+
+           NonTemplatesInput + TemplatesInput,
+           NonTemplatesExpected + IncorrectTemplatesExpected);
+}
+
 // Transformation of macro source text when the change encompasses the entirety
 // of the expanded text.
 TEST_F(TransformerTest, SimpleMacro) {
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1890,7 +1890,60 @@
                    substNonTypeTemplateParmExpr(has(integerLiteral())))))))));
 
   EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
-                                     staticAssertDecl(has(integerLiteral())))));
+                                     staticAssertDecl(has(declRefExpr())))));
+
+  Code = R"cpp(
+
+template<typename T>
+struct TemplStruct {
+  TemplStruct() {}
+  ~TemplStruct() {}
+
+private:
+  T m_t;
+};
+
+template<typename T>
+T timesTwo(T input)
+{
+  return input * 2;
+}
+
+void instantiate()
+{
+  TemplStruct<int> ti;
+  TemplStruct<double> td;
+  (void)timesTwo<int>(2);
+  (void)timesTwo<double>(2);
+}
+
+)cpp";
+  {
+    auto M = cxxRecordDecl(hasName("TemplStruct"),
+                           has(fieldDecl(hasType(asString("int")))));
+    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+  }
+  {
+    auto M = cxxRecordDecl(hasName("TemplStruct"),
+                           has(fieldDecl(hasType(asString("double")))));
+    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+  }
+  {
+    auto M =
+        functionDecl(hasName("timesTwo"),
+                     hasParameter(0, parmVarDecl(hasType(asString("int")))));
+    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+  }
+  {
+    auto M =
+        functionDecl(hasName("timesTwo"),
+                     hasParameter(0, parmVarDecl(hasType(asString("double")))));
+    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+  }
 }
 
 template <typename MatcherT>
@@ -3337,24 +3390,24 @@
   StatementMatcher IsPlacementNew = cxxNewExpr(hasAnyPlacementArg(anything()));
 
   EXPECT_TRUE(matches(R"(
-    void* operator new(decltype(sizeof(void*)), void*); 
+    void* operator new(decltype(sizeof(void*)), void*);
     int *foo(void* Storage) {
-      return new (Storage) int; 
+      return new (Storage) int;
     })",
                       IsPlacementNew));
 
   EXPECT_TRUE(matches(R"(
-    void* operator new(decltype(sizeof(void*)), void*, unsigned); 
+    void* operator new(decltype(sizeof(void*)), void*, unsigned);
     int *foo(void* Storage) {
-      return new (Storage, 16) int; 
+      return new (Storage, 16) int;
     })",
                       cxxNewExpr(hasPlacementArg(
                           1, ignoringImpCasts(integerLiteral(equals(16)))))));
 
   EXPECT_TRUE(notMatches(R"(
-    void* operator new(decltype(sizeof(void*)), void*); 
+    void* operator new(decltype(sizeof(void*)), void*);
     int *foo(void* Storage) {
-      return new int; 
+      return new int;
     })",
                          IsPlacementNew));
 }
Index: clang/unittests/AST/ASTTraverserTest.cpp
===================================================================
--- clang/unittests/AST/ASTTraverserTest.cpp
+++ clang/unittests/AST/ASTTraverserTest.cpp
@@ -68,6 +68,14 @@
   void Visit(const TemplateArgument &A, SourceRange R = {},
              const Decl *From = nullptr, const char *Label = nullptr) {
     OS << "TemplateArgument";
+    switch (A.getKind()) {
+    case TemplateArgument::Type: {
+      OS << " type " << A.getAsType().getAsString();
+      break;
+    }
+    default:
+      break;
+    }
   }
 
   template <typename... T> void Visit(T...) {}
@@ -420,8 +428,9 @@
 
   {
     auto FN = ast_matchers::match(
-        functionDecl(hasName("template_test"),
-                     hasDescendant(staticAssertDecl().bind("staticAssert"))),
+        traverse(TK_AsIs, functionDecl(hasName("template_test"),
+                                       hasDescendant(staticAssertDecl().bind(
+                                           "staticAssert")))),
         AST->getASTContext());
     EXPECT_EQ(FN.size(), 2u);
 
@@ -873,4 +882,141 @@
   }
 }
 
+TEST(Traverse, IgnoreUnlessSpelledInSourceTemplateInstantiations) {
+
+  auto AST = buildASTFromCode(R"cpp(
+template<typename T>
+struct TemplStruct {
+  TemplStruct() {}
+  ~TemplStruct() {}
+
+private:
+  T m_t;
+};
+
+template<typename T>
+T timesTwo(T input)
+{
+  return input * 2;
+}
+
+void instantiate()
+{
+  TemplStruct<int> ti;
+  TemplStruct<double> td;
+  (void)timesTwo<int>(2);
+  (void)timesTwo<double>(2);
+}
+)cpp");
+  {
+    auto BN = ast_matchers::match(
+        classTemplateDecl(hasName("TemplStruct")).bind("rec"),
+        AST->getASTContext());
+    EXPECT_EQ(BN.size(), 1u);
+
+    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+                            BN[0].getNodeAs<Decl>("rec")),
+              R"cpp(
+ClassTemplateDecl 'TemplStruct'
+|-TemplateTypeParmDecl 'T'
+`-CXXRecordDecl 'TemplStruct'
+  |-CXXRecordDecl 'TemplStruct'
+  |-CXXConstructorDecl 'TemplStruct<T>'
+  | `-CompoundStmt
+  |-CXXDestructorDecl '~TemplStruct<T>'
+  | `-CompoundStmt
+  |-AccessSpecDecl
+  `-FieldDecl 'm_t'
+)cpp");
+
+    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),
+              R"cpp(
+ClassTemplateDecl 'TemplStruct'
+|-TemplateTypeParmDecl 'T'
+|-CXXRecordDecl 'TemplStruct'
+| |-CXXRecordDecl 'TemplStruct'
+| |-CXXConstructorDecl 'TemplStruct<T>'
+| | `-CompoundStmt
+| |-CXXDestructorDecl '~TemplStruct<T>'
+| | `-CompoundStmt
+| |-AccessSpecDecl
+| `-FieldDecl 'm_t'
+|-ClassTemplateSpecializationDecl 'TemplStruct'
+| |-TemplateArgument type int
+| |-CXXRecordDecl 'TemplStruct'
+| |-CXXConstructorDecl 'TemplStruct'
+| | `-CompoundStmt
+| |-CXXDestructorDecl '~TemplStruct'
+| | `-CompoundStmt
+| |-AccessSpecDecl
+| |-FieldDecl 'm_t'
+| `-CXXConstructorDecl 'TemplStruct'
+|   `-ParmVarDecl ''
+`-ClassTemplateSpecializationDecl 'TemplStruct'
+  |-TemplateArgument type double
+  |-CXXRecordDecl 'TemplStruct'
+  |-CXXConstructorDecl 'TemplStruct'
+  | `-CompoundStmt
+  |-CXXDestructorDecl '~TemplStruct'
+  | `-CompoundStmt
+  |-AccessSpecDecl
+  |-FieldDecl 'm_t'
+  `-CXXConstructorDecl 'TemplStruct'
+    `-ParmVarDecl ''
+)cpp");
+  }
+  {
+    auto BN = ast_matchers::match(
+        functionTemplateDecl(hasName("timesTwo")).bind("fn"),
+        AST->getASTContext());
+    EXPECT_EQ(BN.size(), 1u);
+
+    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+                            BN[0].getNodeAs<Decl>("fn")),
+              R"cpp(
+FunctionTemplateDecl 'timesTwo'
+|-TemplateTypeParmDecl 'T'
+`-FunctionDecl 'timesTwo'
+  |-ParmVarDecl 'input'
+  `-CompoundStmt
+    `-ReturnStmt
+      `-BinaryOperator
+        |-DeclRefExpr 'input'
+        `-IntegerLiteral
+)cpp");
+
+    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("fn")),
+              R"cpp(
+FunctionTemplateDecl 'timesTwo'
+|-TemplateTypeParmDecl 'T'
+|-FunctionDecl 'timesTwo'
+| |-ParmVarDecl 'input'
+| `-CompoundStmt
+|   `-ReturnStmt
+|     `-BinaryOperator
+|       |-DeclRefExpr 'input'
+|       `-IntegerLiteral
+|-FunctionDecl 'timesTwo'
+| |-TemplateArgument type int
+| |-ParmVarDecl 'input'
+| `-CompoundStmt
+|   `-ReturnStmt
+|     `-BinaryOperator
+|       |-ImplicitCastExpr
+|       | `-DeclRefExpr 'input'
+|       `-IntegerLiteral
+`-FunctionDecl 'timesTwo'
+  |-TemplateArgument type double
+  |-ParmVarDecl 'input'
+  `-CompoundStmt
+    `-ReturnStmt
+      `-BinaryOperator
+        |-ImplicitCastExpr
+        | `-DeclRefExpr 'input'
+        `-ImplicitCastExpr
+          `-IntegerLiteral
+)cpp");
+  }
+}
+
 } // namespace clang
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -282,6 +282,13 @@
   TraversalKindScope RAII(Finder->getASTContext(),
                           Implementation->TraversalKind());
 
+  if (Finder->getASTContext().getParentMapContext().getTraversalKind() ==
+      TK_IgnoreUnlessSpelledInSource) {
+    if (Finder->isMatchingInImplicitTemplateInstantiation()) {
+      return false;
+    }
+  }
+
   auto N =
       Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode);
 
Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -561,6 +561,114 @@
   bool shouldVisitTemplateInstantiations() const { return true; }
   bool shouldVisitImplicitCode() const { return true; }
 
+  bool m_traversingImplicitTemplateInstantiation = false;
+
+  bool isMatchingInImplicitTemplateInstantiation() const override {
+    return m_traversingImplicitTemplateInstantiation;
+  }
+
+  struct ImplicitTemplateInstantiationScope {
+    ImplicitTemplateInstantiationScope(MatchASTVisitor *V, bool b) : m_V(V) {
+      m_B = V->m_traversingImplicitTemplateInstantiation;
+      V->m_traversingImplicitTemplateInstantiation = b;
+    }
+    ~ImplicitTemplateInstantiationScope() {
+      m_V->m_traversingImplicitTemplateInstantiation = m_B;
+    }
+
+  private:
+    MatchASTVisitor *m_V;
+    bool m_B;
+  };
+
+#define TRY_TO(CALL_EXPR)                                                      \
+  do {                                                                         \
+    if (!getDerived().CALL_EXPR)                                               \
+      return false;                                                            \
+  } while (false)
+
+  bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
+    for (auto *SD : D->specializations()) {
+      for (auto *RD : SD->redecls()) {
+        // We don't want to visit injected-class-names in this traversal.
+        if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
+          continue;
+
+        switch (cast<ClassTemplateSpecializationDecl>(RD)
+                    ->getSpecializationKind()) {
+        // Visit the implicit instantiations with the requested pattern.
+        case TSK_Undeclared:
+        case TSK_ImplicitInstantiation: {
+          ImplicitTemplateInstantiationScope RAII(this, true);
+          TRY_TO(TraverseDecl(RD));
+          break;
+        }
+
+        // We don't need to do anything on an explicit instantiation
+        // or explicit specialization because there will be an explicit
+        // node for it elsewhere.
+        case TSK_ExplicitInstantiationDeclaration:
+        case TSK_ExplicitInstantiationDefinition:
+        case TSK_ExplicitSpecialization:
+          break;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
+    for (auto *SD : D->specializations()) {
+      for (auto *RD : SD->redecls()) {
+        switch (
+            cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
+        case TSK_Undeclared:
+        case TSK_ImplicitInstantiation: {
+          ImplicitTemplateInstantiationScope RAII(this, true);
+          TRY_TO(TraverseDecl(RD));
+          break;
+        }
+
+        case TSK_ExplicitInstantiationDeclaration:
+        case TSK_ExplicitInstantiationDefinition:
+        case TSK_ExplicitSpecialization:
+          break;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
+    for (auto *FD : D->specializations()) {
+      for (auto *RD : FD->redecls()) {
+        switch (RD->getTemplateSpecializationKind()) {
+        case TSK_Undeclared:
+        case TSK_ImplicitInstantiation: {
+          // We don't know what kind of FunctionDecl this is.
+          ImplicitTemplateInstantiationScope RAII(this, true);
+          TRY_TO(TraverseDecl(RD));
+          break;
+        }
+
+        // FIXME: For now traverse explicit instantiations here. Change that
+        // once they are represented as dedicated nodes in the AST.
+        case TSK_ExplicitInstantiationDeclaration:
+        case TSK_ExplicitInstantiationDefinition:
+          TRY_TO(TraverseDecl(RD));
+          break;
+
+        case TSK_ExplicitSpecialization:
+          break;
+        }
+      }
+    }
+
+    return true;
+  }
+
 private:
   class TimeBucketRegion {
   public:
Index: clang/lib/AST/ASTDumper.cpp
===================================================================
--- clang/lib/AST/ASTDumper.cpp
+++ clang/lib/AST/ASTDumper.cpp
@@ -129,9 +129,10 @@
 
   Visit(D->getTemplatedDecl());
 
-  for (const auto *Child : D->specializations())
-    dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
-                                   !D->isCanonicalDecl());
+  if (GetTraversalKind() == TK_AsIs)
+    for (const auto *Child : D->specializations())
+      dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
+                                     !D->isCanonicalDecl());
 }
 
 void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1056,6 +1056,8 @@
 
   virtual ASTContext &getASTContext() const = 0;
 
+  virtual bool isMatchingInImplicitTemplateInstantiation() const = 0;
+
 protected:
   virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
                               const DynTypedMatcher &Matcher,
Index: clang/include/clang/AST/ASTNodeTraverser.h
===================================================================
--- clang/include/clang/AST/ASTNodeTraverser.h
+++ clang/include/clang/AST/ASTNodeTraverser.h
@@ -78,6 +78,7 @@
   bool getDeserialize() const { return Deserialize; }
 
   void SetTraversalKind(TraversalKind TK) { Traversal = TK; }
+  TraversalKind GetTraversalKind() const { return Traversal; }
 
   void Visit(const Decl *D) {
     getNodeDelegate().AddChild([=] {
@@ -475,8 +476,9 @@
 
     Visit(D->getTemplatedDecl());
 
-    for (const auto *Child : D->specializations())
-      dumpTemplateDeclSpecialization(Child);
+    if (Traversal == TK_AsIs)
+      for (const auto *Child : D->specializations())
+        dumpTemplateDeclSpecialization(Child);
   }
 
   void VisitTypeAliasDecl(const TypeAliasDecl *D) {
Index: clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
+++ clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
@@ -28,11 +28,12 @@
 
 void TemporaryObjectsCheck::registerMatchers(MatchFinder *Finder) {
   // Matcher for default constructors.
-  Finder->addMatcher(
-      cxxTemporaryObjectExpr(hasDeclaration(cxxConstructorDecl(hasParent(
-                                 cxxRecordDecl(matchesAnyName(Names))))))
-          .bind("temps"),
-      this);
+  Finder->addMatcher(traverse(ast_type_traits::TK_AsIs,
+                              cxxTemporaryObjectExpr(
+                                  hasDeclaration(cxxConstructorDecl(hasParent(
+                                      cxxRecordDecl(matchesAnyName(Names))))))
+                                  .bind("temps")),
+                     this);
 
   // Matcher for user-defined constructors.
   Finder->addMatcher(
Index: clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -39,8 +39,7 @@
 void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(
       memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
-                                      varDecl(hasStaticStorageDuration()))),
-                 unless(isInTemplateInstantiation()))
+                                      varDecl(hasStaticStorageDuration()))))
           .bind("memberExpression"),
       this);
 }
Index: clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
@@ -127,30 +127,35 @@
   auto IsBoundToType = refersToType(equalsBoundNode("type"));
 
   Finder->addMatcher(
-      ExplicitSingleVarDecl(hasType(autoType(hasDeducedType(
+      traverse(TK_AsIs, ExplicitSingleVarDecl(
+                            hasType(autoType(hasDeducedType(
                                 pointerType(pointee(unless(functionType())))))),
-                            "auto"),
+                            "auto")),
       this);
 
   Finder->addMatcher(
-      ExplicitSingleVarDeclInTemplate(
-          allOf(hasType(autoType(hasDeducedType(pointerType(
-                    pointee(hasUnqualifiedType(qualType().bind("type")),
-                            unless(functionType())))))),
-                anyOf(hasAncestor(
-                          functionDecl(hasAnyTemplateArgument(IsBoundToType))),
-                      hasAncestor(classTemplateSpecializationDecl(
-                          hasAnyTemplateArgument(IsBoundToType))))),
-          "auto"),
+      traverse(TK_AsIs,
+               ExplicitSingleVarDeclInTemplate(
+                   allOf(hasType(autoType(hasDeducedType(pointerType(pointee(
+                             hasUnqualifiedType(qualType().bind("type")),
+                             unless(functionType())))))),
+                         anyOf(hasAncestor(functionDecl(
+                                   hasAnyTemplateArgument(IsBoundToType))),
+                               hasAncestor(classTemplateSpecializationDecl(
+                                   hasAnyTemplateArgument(IsBoundToType))))),
+                   "auto")),
       this);
   if (!AddConstToQualified)
     return;
-  Finder->addMatcher(ExplicitSingleVarDecl(
-                         hasType(pointerType(pointee(autoType()))), "auto_ptr"),
-                     this);
   Finder->addMatcher(
-      ExplicitSingleVarDecl(hasType(lValueReferenceType(pointee(autoType()))),
-                            "auto_ref"),
+      traverse(TK_AsIs,
+               ExplicitSingleVarDecl(hasType(pointerType(pointee(autoType()))),
+                                     "auto_ptr")),
+      this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, ExplicitSingleVarDecl(
+                            hasType(lValueReferenceType(pointee(autoType()))),
+                            "auto_ref")),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -55,13 +55,15 @@
           hasParent(explicitCastExpr(hasDestinationType(booleanType())))));
 
   Finder->addMatcher(
-      cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer),
-                                      hasType(pointsTo(ValidContainer)),
-                                      hasType(references(ValidContainer))))),
-                        callee(cxxMethodDecl(hasName("size"))), WrongUse,
-                        unless(hasAncestor(cxxMethodDecl(
-                            ofClass(equalsBoundNode("container"))))))
-          .bind("SizeCallExpr"),
+      traverse(TK_AsIs,
+               cxxMemberCallExpr(
+                   on(expr(anyOf(hasType(ValidContainer),
+                                 hasType(pointsTo(ValidContainer)),
+                                 hasType(references(ValidContainer))))),
+                   callee(cxxMethodDecl(hasName("size"))), WrongUse,
+                   unless(hasAncestor(
+                       cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
+                   .bind("SizeCallExpr")),
       this);
 
   // Empty constructor matcher.
@@ -86,13 +88,15 @@
                     expr(hasType(pointsTo(ValidContainer))).bind("Pointee"))),
             expr(hasType(ValidContainer)).bind("STLObject"));
   Finder->addMatcher(
-      cxxOperatorCallExpr(
-          hasAnyOverloadedOperatorName("==", "!="),
-          anyOf(allOf(hasArgument(0, WrongComparend), hasArgument(1, STLArg)),
-                allOf(hasArgument(0, STLArg), hasArgument(1, WrongComparend))),
-          unless(hasAncestor(
-              cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
-          .bind("BinCmp"),
+      traverse(TK_AsIs,
+               cxxOperatorCallExpr(hasAnyOverloadedOperatorName("==", "!="),
+                                   anyOf(allOf(hasArgument(0, WrongComparend),
+                                               hasArgument(1, STLArg)),
+                                         allOf(hasArgument(0, STLArg),
+                                               hasArgument(1, WrongComparend))),
+                                   unless(hasAncestor(cxxMethodDecl(
+                                       ofClass(equalsBoundNode("container"))))))
+                   .bind("BinCmp")),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
+++ clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
@@ -69,15 +69,17 @@
                  "find_last_of", "find_last_not_of");
 
   Finder->addMatcher(
-      cxxMemberCallExpr(
-          callee(functionDecl(StringFindFunctions).bind("func")),
-          anyOf(argumentCountIs(1), argumentCountIs(2)),
-          hasArgument(0, SingleChar),
-          on(expr(
-              hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
-                  recordDecl(hasAnyName(SmallVector<StringRef, 4>(
-                      StringLikeClasses.begin(), StringLikeClasses.end()))))))),
-              unless(hasSubstitutedType())))),
+      traverse(TK_AsIs,
+               cxxMemberCallExpr(
+                   callee(functionDecl(StringFindFunctions).bind("func")),
+                   anyOf(argumentCountIs(1), argumentCountIs(2)),
+                   hasArgument(0, SingleChar),
+                   on(expr(hasType(hasUnqualifiedDesugaredType(
+                               recordType(hasDeclaration(recordDecl(
+                                   hasAnyName(SmallVector<StringRef, 4>(
+                                       StringLikeClasses.begin(),
+                                       StringLikeClasses.end()))))))),
+                           unless(hasSubstitutedType()))))),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
@@ -21,29 +21,32 @@
 
   // Using declaration: warning and fix-it.
   Finder->addMatcher(
-      usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
-          .bind("using_decl"),
+      traverse(TK_AsIs, usingDecl(hasAnyUsingShadowDecl(
+                                      hasTargetDecl(hasName(MatchText))))
+                            .bind("using_decl")),
       this);
 
   // DeclRefExpr: warning, no fix-it.
   Finder->addMatcher(
-      declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr()))
-          .bind("decl_ref_expr"),
+      traverse(TK_AsIs, declRefExpr(to(functionDecl(hasName(MatchText))),
+                                    unless(callExpr()))
+                            .bind("decl_ref_expr")),
       this);
 
   auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts(
       declRefExpr(hasDeclaration(functionDecl(hasName(MatchText)))))));
 
   // CallExpr: warning, fix-it.
-  Finder->addMatcher(callExpr(DirectCallToUncaughtException,
-                              unless(hasAncestor(initListExpr())))
-                         .bind("call_expr"),
-                     this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, callExpr(DirectCallToUncaughtException,
+                                 unless(hasAncestor(initListExpr())))
+                            .bind("call_expr")),
+      this);
   // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
   // conversions.
-  Finder->addMatcher(callExpr(DirectCallToUncaughtException,
-                              hasAncestor(initListExpr()))
-                         .bind("init_call_expr"),
+  Finder->addMatcher(traverse(TK_AsIs, callExpr(DirectCallToUncaughtException,
+                                                hasAncestor(initListExpr()))
+                                           .bind("init_call_expr")),
                      this);
 }
 
Index: clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
@@ -34,10 +34,13 @@
 void UseOverrideCheck::registerMatchers(MatchFinder *Finder) {
   if (IgnoreDestructors)
     Finder->addMatcher(
-        cxxMethodDecl(isOverride(), unless(cxxDestructorDecl())).bind("method"),
+        traverse(TK_AsIs,
+                 cxxMethodDecl(isOverride(), unless(cxxDestructorDecl()))
+                     .bind("method")),
         this);
   else
-    Finder->addMatcher(cxxMethodDecl(isOverride()).bind("method"), this);
+    Finder->addMatcher(
+        traverse(TK_AsIs, cxxMethodDecl(isOverride()).bind("method")), this);
 }
 
 // Re-lex the tokens to get precise locations to insert 'override' and remove
Index: clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
@@ -95,19 +95,23 @@
   //
   //   std::auto_ptr<int> fn(std::auto_ptr<int>);
   //        ^~~~~~~~~~~~~         ^~~~~~~~~~~~~
-  Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType,
-                                          // Skip elaboratedType() as the named
-                                          // type will match soon thereafter.
-                                          unless(elaboratedType()))))
-                         .bind(AutoPtrTokenId),
-                     this);
+  Finder->addMatcher(
+      traverse(TK_AsIs,
+               typeLoc(loc(qualType(AutoPtrType,
+                                    // Skip elaboratedType() as the named
+                                    // type will match soon thereafter.
+                                    unless(elaboratedType()))))
+                   .bind(AutoPtrTokenId)),
+      this);
 
   //   using std::auto_ptr;
   //   ^~~~~~~~~~~~~~~~~~~
-  Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(namedDecl(
-                                   hasName("auto_ptr"), isFromStdNamespace()))))
-                         .bind(AutoPtrTokenId),
-                     this);
+  Finder->addMatcher(
+      traverse(TK_AsIs,
+               usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(namedDecl(
+                             hasName("auto_ptr"), isFromStdNamespace()))))
+                   .bind(AutoPtrTokenId)),
+      this);
 
   // Find ownership transfers via copy construction and assignment.
   // AutoPtrOwnershipTransferId is bound to the part that has to be wrapped
@@ -119,9 +123,10 @@
       expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId);
 
   Finder->addMatcher(
-      cxxOperatorCallExpr(hasOverloadedOperatorName("="),
-                          callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
-                          hasArgument(1, MovableArgumentMatcher)),
+      traverse(TK_AsIs,
+               cxxOperatorCallExpr(hasOverloadedOperatorName("="),
+                                   callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
+                                   hasArgument(1, MovableArgumentMatcher))),
       this);
   Finder->addMatcher(
       traverse(ast_type_traits::TK_AsIs,
Index: clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -114,6 +114,8 @@
   // pointer, 'make_smart_ptr' refers to 'std::make_shared' or
   // 'std::make_unique' or other function that creates smart_ptr.
 
+  TraversalKindScope RAII(*Result.Context, TK_AsIs);
+
   SourceManager &SM = *Result.SourceManager;
   const auto *Construct =
       Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
Index: clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
@@ -34,7 +34,8 @@
   auto IoStateType =
       qualType(hasDeclaration(IoStateDecl), unless(elaboratedType()));
 
-  Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, typeLoc(loc(IoStateType)).bind("TypeLoc")), this);
 }
 
 void DeprecatedIosBaseAliasesCheck::check(
Index: clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
+++ clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -18,23 +18,25 @@
 
 void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(
-      cxxThrowExpr(
-          unless(has(expr(anyOf(isTypeDependent(), isValueDependent())))),
-          // The thrown value is not derived from 'std::exception'.
-          has(expr(unless(
-              hasType(qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
-                  isSameOrDerivedFrom(hasName("::std::exception")))))))))),
-          // This condition is always true, but will bind to the
-          // template value if the thrown type is templated.
-          anyOf(has(expr(
-                    hasType(substTemplateTypeParmType().bind("templ_type")))),
-                anything()),
-          // Bind to the declaration of the type of the value that
-          // is thrown. 'anything()' is necessary to always succeed
-          // in the 'eachOf' because builtin types are not
-          // 'namedDecl'.
-          eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))
-          .bind("bad_throw"),
+      traverse(
+          TK_AsIs,
+          cxxThrowExpr(
+              unless(has(expr(anyOf(isTypeDependent(), isValueDependent())))),
+              // The thrown value is not derived from 'std::exception'.
+              has(expr(unless(hasType(
+                  qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
+                      isSameOrDerivedFrom(hasName("::std::exception")))))))))),
+              // This condition is always true, but will bind to the
+              // template value if the thrown type is templated.
+              anyOf(has(expr(hasType(
+                        substTemplateTypeParmType().bind("templ_type")))),
+                    anything()),
+              // Bind to the declaration of the type of the value that
+              // is thrown. 'anything()' is necessary to always succeed
+              // in the 'eachOf' because builtin types are not
+              // 'namedDecl'.
+              eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))
+              .bind("bad_throw")),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
+++ clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
@@ -168,10 +168,11 @@
                               .bind("class")))))
           .bind("method");
 
-  Finder->addMatcher(expr(anyOf(callExpr(callee(Methods)).bind("call"),
-                                declRefExpr(to(Methods)).bind("ref")),
-                          LocationFilter),
-                     this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, expr(anyOf(callExpr(callee(Methods)).bind("call"),
+                                   declRefExpr(to(Methods)).bind("ref")),
+                             LocationFilter)),
+      this);
 
   Finder->addMatcher(
       usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(Methods)), LocationFilter)
Index: clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
@@ -216,11 +216,13 @@
 
 void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(
-      cxxMethodDecl(
-          unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
-                       cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
-                       isOverloadedOperator())))
-          .bind("method"),
+      traverse(
+          TK_AsIs,
+          cxxMethodDecl(
+              unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
+                           cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
+                           isOverloadedOperator())))
+              .bind("method")),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
@@ -30,18 +30,20 @@
 
   // Check whether destination object is not TriviallyCopyable.
   // Applicable to all three memory manipulation functions.
-  Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
-                                  "::memset", "::memcpy", "::memmove"))),
-                              hasArgument(0, NotTriviallyCopyableObject))
-                         .bind("dest"),
-                     this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, callExpr(callee(functionDecl(hasAnyName(
+                                     "::memset", "::memcpy", "::memmove"))),
+                                 hasArgument(0, NotTriviallyCopyableObject))
+                            .bind("dest")),
+      this);
 
   // Check whether source object is not TriviallyCopyable.
   // Only applicable to memcpy() and memmove().
   Finder->addMatcher(
-      callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))),
-               hasArgument(1, NotTriviallyCopyableObject))
-          .bind("src"),
+      traverse(TK_AsIs, callExpr(callee(functionDecl(
+                                     hasAnyName("::memcpy", "::memmove"))),
+                                 hasArgument(1, NotTriviallyCopyableObject))
+                            .bind("src")),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
@@ -79,20 +79,22 @@
       expr(ignoringParenImpCasts(hasType(isInteger()))).bind(LoopIncrementName);
 
   Finder->addMatcher(
-      forStmt(
-          hasCondition(anyOf(
-              binaryOperator(hasOperatorName("<"),
-                             hasLHS(LoopVarConversionMatcher),
-                             hasRHS(LoopBoundMatcher)),
-              binaryOperator(hasOperatorName("<="),
-                             hasLHS(LoopVarConversionMatcher),
-                             hasRHS(LoopBoundMatcher)),
-              binaryOperator(hasOperatorName(">"), hasLHS(LoopBoundMatcher),
-                             hasRHS(LoopVarConversionMatcher)),
-              binaryOperator(hasOperatorName(">="), hasLHS(LoopBoundMatcher),
-                             hasRHS(LoopVarConversionMatcher)))),
-          hasIncrement(IncrementMatcher))
-          .bind(LoopName),
+      traverse(TK_AsIs,
+               forStmt(hasCondition(anyOf(
+                           binaryOperator(hasOperatorName("<"),
+                                          hasLHS(LoopVarConversionMatcher),
+                                          hasRHS(LoopBoundMatcher)),
+                           binaryOperator(hasOperatorName("<="),
+                                          hasLHS(LoopVarConversionMatcher),
+                                          hasRHS(LoopBoundMatcher)),
+                           binaryOperator(hasOperatorName(">"),
+                                          hasLHS(LoopBoundMatcher),
+                                          hasRHS(LoopVarConversionMatcher)),
+                           binaryOperator(hasOperatorName(">="),
+                                          hasLHS(LoopBoundMatcher),
+                                          hasRHS(LoopVarConversionMatcher)))),
+                       hasIncrement(IncrementMatcher))
+                   .bind(LoopName)),
       this);
 }
 
Index: clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -97,9 +97,10 @@
   //       the sizeof size_t.
   if (WarnOnSizeOfConstant) {
     Finder->addMatcher(
-        expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))),
-             unless(SizeOfZero))
-            .bind("sizeof-constant"),
+        traverse(TK_AsIs,
+                 expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))),
+                      unless(SizeOfZero))
+                     .bind("sizeof-constant")),
         this);
   }
 
@@ -186,14 +187,15 @@
   const auto DenomType = qualType(hasCanonicalType(type().bind("denom-type")));
 
   Finder->addMatcher(
-      binaryOperator(hasOperatorName("/"),
-                     hasLHS(expr(ignoringParenImpCasts(
-                         anyOf(sizeOfExpr(has(NumType)),
-                               sizeOfExpr(has(expr(hasType(NumType)))))))),
-                     hasRHS(expr(ignoringParenImpCasts(
-                         anyOf(sizeOfExpr(has(DenomType)),
-                               sizeOfExpr(has(expr(hasType(DenomType)))))))))
-          .bind("sizeof-divide-expr"),
+      traverse(TK_AsIs,
+               binaryOperator(hasOperatorName("/"),
+                              hasLHS(expr(ignoringParenImpCasts(anyOf(
+                                  sizeOfExpr(has(NumType)),
+                                  sizeOfExpr(has(expr(hasType(NumType)))))))),
+                              hasRHS(expr(ignoringParenImpCasts(anyOf(
+                                  sizeOfExpr(has(DenomType)),
+                                  sizeOfExpr(has(expr(hasType(DenomType)))))))))
+                   .bind("sizeof-divide-expr")),
       this);
 
   // Detect expression like: sizeof(...) * sizeof(...)); most likely an error.
Index: clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
@@ -29,57 +29,66 @@
   // Match expressions like `a *= b` and `a /= b` where `a` has type
   // `absl::Duration` and `b` is not of a built-in type.
   Finder->addMatcher(
-      cxxOperatorCallExpr(
-          argumentCountIs(2),
-          hasArgument(
-              0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
-          hasArgument(1, expr().bind("arg")),
-          callee(functionDecl(
-              hasParent(functionTemplateDecl()),
-              unless(hasTemplateArgument(0, refersToType(builtinType()))),
-              hasAnyName("operator*=", "operator/="))))
-          .bind("OuterExpr"),
+      traverse(
+          ast_type_traits::TK_AsIs,
+          cxxOperatorCallExpr(
+              argumentCountIs(2),
+              hasArgument(
+                  0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
+              hasArgument(1, expr().bind("arg")),
+              callee(functionDecl(
+                  hasParent(functionTemplateDecl()),
+                  unless(hasTemplateArgument(0, refersToType(builtinType()))),
+                  hasAnyName("operator*=", "operator/="))))
+              .bind("OuterExpr")),
       this);
 
   // Match expressions like `a.operator*=(b)` and `a.operator/=(b)` where `a`
   // has type `absl::Duration` and `b` is not of a built-in type.
   Finder->addMatcher(
-      cxxMemberCallExpr(
-          callee(cxxMethodDecl(
-              ofClass(cxxRecordDecl(hasName("::absl::Duration"))),
-              hasParent(functionTemplateDecl()),
-              unless(hasTemplateArgument(0, refersToType(builtinType()))),
-              hasAnyName("operator*=", "operator/="))),
-          argumentCountIs(1), hasArgument(0, expr().bind("arg")))
-          .bind("OuterExpr"),
+      traverse(
+          ast_type_traits::TK_AsIs,
+          cxxMemberCallExpr(
+              callee(cxxMethodDecl(
+                  ofClass(cxxRecordDecl(hasName("::absl::Duration"))),
+                  hasParent(functionTemplateDecl()),
+                  unless(hasTemplateArgument(0, refersToType(builtinType()))),
+                  hasAnyName("operator*=", "operator/="))),
+              argumentCountIs(1), hasArgument(0, expr().bind("arg")))
+              .bind("OuterExpr")),
       this);
 
   // Match expressions like `a * b`, `a / b`, `operator*(a, b)`, and
   // `operator/(a, b)` where `a` has type `absl::Duration` and `b` is not of a
   // built-in type.
   Finder->addMatcher(
-      callExpr(callee(functionDecl(
-                   hasParent(functionTemplateDecl()),
-                   unless(hasTemplateArgument(0, refersToType(builtinType()))),
-                   hasAnyName("::absl::operator*", "::absl::operator/"))),
-               argumentCountIs(2),
-               hasArgument(0, expr(hasType(
-                                  cxxRecordDecl(hasName("::absl::Duration"))))),
-               hasArgument(1, expr().bind("arg")))
-          .bind("OuterExpr"),
+      traverse(
+          ast_type_traits::TK_AsIs,
+          callExpr(
+              callee(functionDecl(
+                  hasParent(functionTemplateDecl()),
+                  unless(hasTemplateArgument(0, refersToType(builtinType()))),
+                  hasAnyName("::absl::operator*", "::absl::operator/"))),
+              argumentCountIs(2),
+              hasArgument(
+                  0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
+              hasArgument(1, expr().bind("arg")))
+              .bind("OuterExpr")),
       this);
 
   // Match expressions like `a * b` and `operator*(a, b)` where `a` is not of a
   // built-in type and `b` has type `absl::Duration`.
   Finder->addMatcher(
-      callExpr(callee(functionDecl(
-                   hasParent(functionTemplateDecl()),
-                   unless(hasTemplateArgument(0, refersToType(builtinType()))),
-                   hasName("::absl::operator*"))),
-               argumentCountIs(2), hasArgument(0, expr().bind("arg")),
-               hasArgument(1, expr(hasType(
-                                  cxxRecordDecl(hasName("::absl::Duration"))))))
-          .bind("OuterExpr"),
+      traverse(
+          ast_type_traits::TK_AsIs,
+          callExpr(callee(functionDecl(hasParent(functionTemplateDecl()),
+                                       unless(hasTemplateArgument(
+                                           0, refersToType(builtinType()))),
+                                       hasName("::absl::operator*"))),
+                   argumentCountIs(2), hasArgument(0, expr().bind("arg")),
+                   hasArgument(1, expr(hasType(cxxRecordDecl(
+                                      hasName("::absl::Duration"))))))
+              .bind("OuterExpr")),
       this);
 
   // For the factory functions, we match only the non-templated overloads that
Index: clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
@@ -114,7 +114,7 @@
                                           hasLHS(TimeInverseMatcher))
                                .bind("binop")))
             .bind("outer_call");
-    Finder->addMatcher(CallMatcher, this);
+    Finder->addMatcher(traverse(TK_AsIs, CallMatcher), this);
 
     // Match cases where we know the second operand is a 'Time'. Since
     // subtracting a 'Time' from a 'Duration' is not defined, in these cases,
@@ -122,7 +122,7 @@
     auto OperandMatcher =
         binaryOperator(hasOperatorName("-"), hasRHS(TimeInverseMatcher))
             .bind("binop");
-    Finder->addMatcher(OperandMatcher, this);
+    Finder->addMatcher(traverse(TK_AsIs, OperandMatcher), this);
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to