steveire updated this revision to Diff 270517.
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/misc/UnusedUsingDeclsCheck.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/AST/RecursiveASTVisitor.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/ASTContextParentMapTest.cpp
  clang/unittests/AST/ASTImporterTest.cpp
  clang/unittests/AST/ASTTraverserTest.cpp
  clang/unittests/AST/SourceLocationTest.cpp
  clang/unittests/AST/StructuralEquivalenceTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
  clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
  clang/unittests/Sema/GslOwnerPointerInference.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/Sema/GslOwnerPointerInference.cpp
===================================================================
--- clang/unittests/Sema/GslOwnerPointerInference.cpp
+++ clang/unittests/Sema/GslOwnerPointerInference.cpp
@@ -14,42 +14,45 @@
 using namespace ast_matchers;
 
 TEST(OwnerPointer, BothHaveAttributes) {
-  EXPECT_TRUE(matches("template<class T>"
-                      "class [[gsl::Owner]] C;"
+  EXPECT_TRUE(matches(
+      "template<class T>"
+      "class [[gsl::Owner]] C;"
 
-                      "template<class T>"
-                      "class [[gsl::Owner]] C {};"
+      "template<class T>"
+      "class [[gsl::Owner]] C {};"
 
-                      "C<int> c;",
-                      classTemplateSpecializationDecl(
-                          hasName("C"), hasAttr(clang::attr::Owner))));
+      "C<int> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(
+                            hasName("C"), hasAttr(clang::attr::Owner)))));
 }
 
 TEST(OwnerPointer, ForwardDeclOnly) {
-  EXPECT_TRUE(matches("template<class T>"
-                      "class [[gsl::Owner]] C;"
+  EXPECT_TRUE(matches(
+      "template<class T>"
+      "class [[gsl::Owner]] C;"
 
-                      "template<class T>"
-                      "class C {};"
+      "template<class T>"
+      "class C {};"
 
-                      "C<int> c;",
-                      classTemplateSpecializationDecl(
-                          hasName("C"), hasAttr(clang::attr::Owner))));
+      "C<int> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(
+                            hasName("C"), hasAttr(clang::attr::Owner)))));
 }
 
 TEST(OwnerPointer, LateForwardDeclOnly) {
-  EXPECT_TRUE(matches("template<class T>"
-                      "class C;"
+  EXPECT_TRUE(matches(
+      "template<class T>"
+      "class C;"
 
-                      "template<class T>"
-                      "class C {};"
+      "template<class T>"
+      "class C {};"
 
-                      "template<class T>"
-                      "class [[gsl::Owner]] C;"
+      "template<class T>"
+      "class [[gsl::Owner]] C;"
 
-                      "C<int> c;",
-                      classTemplateSpecializationDecl(
-                          hasName("C"), hasAttr(clang::attr::Owner))));
+      "C<int> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(
+                            hasName("C"), hasAttr(clang::attr::Owner)))));
 }
 
 } // namespace clang
Index: clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -268,13 +268,15 @@
 }
 
 TEST_F(RegistryTest, TemplateArgument) {
-  Matcher<Decl> HasTemplateArgument = constructMatcher(
-      "classTemplateSpecializationDecl",
+  Matcher<Decl> HasTemplateArgument = traverse(
+      TK_AsIs,
       constructMatcher(
-          "hasAnyTemplateArgument",
-          constructMatcher("refersToType",
-                           constructMatcher("asString", StringRef("int")))))
-      .getTypedMatcher<Decl>();
+          "classTemplateSpecializationDecl",
+          constructMatcher(
+              "hasAnyTemplateArgument",
+              constructMatcher("refersToType",
+                               constructMatcher("asString", StringRef("int")))))
+          .getTypedMatcher<Decl>());
   EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
                       HasTemplateArgument));
   EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -26,13 +26,14 @@
 }
 
 TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
-  EXPECT_TRUE(matches(
-    "template <typename T> struct A {"
-      "  template <typename T2> struct F {};"
-      "};"
-      "template <typename T> struct B : A<T>::template F<T> {};"
-      "B<int> b;",
-    cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
+  EXPECT_TRUE(
+      matches("template <typename T> struct A {"
+              "  template <typename T2> struct F {};"
+              "};"
+              "template <typename T> struct B : A<T>::template F<T> {};"
+              "B<int> b;",
+              traverse(TK_AsIs, cxxRecordDecl(hasName("B"),
+                                              isDerivedFrom(recordDecl())))));
 }
 
 TEST(DeclarationMatcher, hasDeclContext) {
@@ -828,33 +829,35 @@
 
 TEST(Matcher, MatchesTypeTemplateArgument) {
   EXPECT_TRUE(matches(
-    "template<typename T> struct B {};"
+      "template<typename T> struct B {};"
       "B<int> b;",
-    classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
-      asString("int"))))));
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            refersToType(asString("int")))))));
 }
 
 TEST(Matcher, MatchesTemplateTemplateArgument) {
-  EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
-                      "template<typename T> class Y {};"
-                      "X<Y> xi;",
-                      classTemplateSpecializationDecl(hasAnyTemplateArgument(
-                          refersToTemplate(templateName())))));
+  EXPECT_TRUE(matches(
+      "template<template <typename> class S> class X {};"
+      "template<typename T> class Y {};"
+      "X<Y> xi;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            refersToTemplate(templateName()))))));
 }
 
 TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {
-  EXPECT_TRUE(matches(
-    "struct B { int next; };"
-      "template<int(B::*next_ptr)> struct A {};"
-      "A<&B::next> a;",
-    classTemplateSpecializationDecl(hasAnyTemplateArgument(
-      refersToDeclaration(fieldDecl(hasName("next")))))));
+  EXPECT_TRUE(
+      matches("struct B { int next; };"
+              "template<int(B::*next_ptr)> struct A {};"
+              "A<&B::next> a;",
+              traverse(TK_AsIs,
+                       classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                           refersToDeclaration(fieldDecl(hasName("next"))))))));
 
   EXPECT_TRUE(notMatches(
-    "template <typename T> struct A {};"
+      "template <typename T> struct A {};"
       "A<int> a;",
-    classTemplateSpecializationDecl(hasAnyTemplateArgument(
-      refersToDeclaration(decl())))));
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            refersToDeclaration(decl()))))));
 
   EXPECT_TRUE(matches(
     "struct B { int next; };"
@@ -873,15 +876,15 @@
 
 TEST(Matcher, MatchesSpecificArgument) {
   EXPECT_TRUE(matches(
-    "template<typename T, typename U> class A {};"
+      "template<typename T, typename U> class A {};"
       "A<bool, int> a;",
-    classTemplateSpecializationDecl(hasTemplateArgument(
-      1, refersToType(asString("int"))))));
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasTemplateArgument(
+                            1, refersToType(asString("int")))))));
   EXPECT_TRUE(notMatches(
-    "template<typename T, typename U> class A {};"
+      "template<typename T, typename U> class A {};"
       "A<int, bool> a;",
-    classTemplateSpecializationDecl(hasTemplateArgument(
-      1, refersToType(asString("int"))))));
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasTemplateArgument(
+                            1, refersToType(asString("int")))))));
 
   EXPECT_TRUE(matches(
     "template<typename T, typename U> class A {};"
@@ -894,27 +897,30 @@
     templateSpecializationType(hasTemplateArgument(
       1, refersToType(asString("int"))))));
 
-  EXPECT_TRUE(matches(
-    "template<typename T> void f() {};"
-      "void func() { f<int>(); }",
-    functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
-  EXPECT_TRUE(notMatches(
-    "template<typename T> void f() {};",
-    functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
+  EXPECT_TRUE(
+      matches("template<typename T> void f() {};"
+              "void func() { f<int>(); }",
+              traverse(TK_AsIs, functionDecl(hasTemplateArgument(
+                                    0, refersToType(asString("int")))))));
+  EXPECT_TRUE(
+      notMatches("template<typename T> void f() {};",
+                 traverse(TK_AsIs, functionDecl(hasTemplateArgument(
+                                       0, refersToType(asString("int")))))));
 }
 
 TEST(TemplateArgument, Matches) {
-  EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(templateArgument()))));
+  EXPECT_TRUE(matches(
+      "template<typename T> struct C {}; C<int> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(
+                            hasAnyTemplateArgument(templateArgument())))));
   EXPECT_TRUE(matches(
     "template<typename T> struct C {}; C<int> c;",
     templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
 
-  EXPECT_TRUE(matches(
-    "template<typename T> void f() {};"
-      "void func() { f<int>(); }",
-    functionDecl(hasAnyTemplateArgument(templateArgument()))));
+  EXPECT_TRUE(matches("template<typename T> void f() {};"
+                      "void func() { f<int>(); }",
+                      traverse(TK_AsIs, functionDecl(hasAnyTemplateArgument(
+                                            templateArgument())))));
 }
 
 TEST(TemplateTypeParmDecl, CXXMethodDecl) {
@@ -1005,13 +1011,14 @@
 }
 
 TEST(RefersToIntegralType, Matches) {
-  EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(refersToIntegralType(
-                          asString("int"))))));
-  EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",
-                         classTemplateSpecializationDecl(hasAnyTemplateArgument(
-                           refersToIntegralType(asString("int"))))));
+  EXPECT_TRUE(matches(
+      "template<int T> struct C {}; C<42> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            refersToIntegralType(asString("int")))))));
+  EXPECT_TRUE(notMatches(
+      "template<unsigned T> struct C {}; C<42> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            refersToIntegralType(asString("int")))))));
 }
 
 TEST(ConstructorDeclaration, SimpleCase) {
@@ -1381,13 +1388,13 @@
 
 TEST(Matcher, VisitsTemplateInstantiations) {
   EXPECT_TRUE(matches(
-    "class A { public: void x(); };"
+      "class A { public: void x(); };"
       "template <typename T> class B { public: void y() { T t; t.x(); } };"
       "void f() { B<A> b; b.y(); }",
-    callExpr(callee(cxxMethodDecl(hasName("x"))))));
+      traverse(TK_AsIs, callExpr(callee(cxxMethodDecl(hasName("x")))))));
 
   EXPECT_TRUE(matches(
-    "class A { public: void x(); };"
+      "class A { public: void x(); };"
       "class C {"
       " public:"
       "  template <typename T> class B { public: void y() { T t; t.x(); } };"
@@ -1395,8 +1402,9 @@
       "void f() {"
       "  C::B<A> b; b.y();"
       "}",
-    recordDecl(hasName("C"), hasDescendant(callExpr(
-      callee(cxxMethodDecl(hasName("x"))))))));
+      traverse(TK_AsIs,
+               recordDecl(hasName("C"), hasDescendant(callExpr(callee(
+                                            cxxMethodDecl(hasName("x")))))))));
 }
 
 TEST(Matcher, HasCondition) {
@@ -1890,7 +1898,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>
@@ -2668,11 +2729,12 @@
                               anyOf(unless(anything()), anything())),
     std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "template<typename T1, typename T2> class X {}; X<float, int> x;",
-    classTemplateSpecializationDecl(
-      decl().bind("x"),
-      hasAnyTemplateArgument(refersToType(asString("int")))),
-    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
+      "template<typename T1, typename T2> class X {}; X<float, int> x;",
+      traverse(TK_AsIs,
+               classTemplateSpecializationDecl(
+                   decl().bind("x"),
+                   hasAnyTemplateArgument(refersToType(asString("int"))))),
+      std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
   EXPECT_TRUE(matchAndVerifyResultTrue(
     "class X { void f(); void g(); };",
     cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
@@ -2716,12 +2778,13 @@
     functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
     std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "template <typename T> struct A { struct B {"
+      "template <typename T> struct A { struct B {"
       "  void f() { if(true) {} }"
       "}; };"
       "void t() { A<int>::B b; b.f(); }",
-    ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
-    std::make_unique<VerifyIdIsBoundTo<Stmt>>("x", 2)));
+      traverse(TK_AsIs, ifStmt(stmt().bind("x"),
+                               hasAncestor(recordDecl(hasName("::A"))))),
+      std::make_unique<VerifyIdIsBoundTo<Stmt>>("x", 2)));
   EXPECT_TRUE(matchAndVerifyResultTrue(
     "class A {};",
     recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),
@@ -2838,10 +2901,10 @@
 
 TEST(HasAncestor, MatchesInTemplateInstantiations) {
   EXPECT_TRUE(matches(
-    "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
+      "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
       "A<int>::B::C a;",
-    fieldDecl(hasType(asString("int")),
-              hasAncestor(recordDecl(hasName("A"))))));
+      traverse(TK_AsIs, fieldDecl(hasType(asString("int")),
+                                  hasAncestor(recordDecl(hasName("A")))))));
 }
 
 TEST(HasAncestor, MatchesInImplicitCode) {
@@ -3293,20 +3356,24 @@
                        "double F(T t);"
                        "int i;"
                        "double j = F(i);";
-  EXPECT_TRUE(matches(Fragment, substTemplateTypeParmType(hasReplacementType(
-                                    qualType(asString("int"))))));
-  EXPECT_TRUE(notMatches(Fragment, substTemplateTypeParmType(hasReplacementType(
-                                       qualType(asString("double"))))));
-  EXPECT_TRUE(
-      notMatches("template<int N>"
-                 "double F();"
-                 "double j = F<5>();",
-                 substTemplateTypeParmType(hasReplacementType(qualType()))));
+  EXPECT_TRUE(matches(
+      Fragment, traverse(TK_AsIs, substTemplateTypeParmType(hasReplacementType(
+                                      qualType(asString("int")))))));
+  EXPECT_TRUE(notMatches(
+      Fragment, traverse(TK_AsIs, substTemplateTypeParmType(hasReplacementType(
+                                      qualType(asString("double")))))));
+  EXPECT_TRUE(notMatches(
+      "template<int N>"
+      "double F();"
+      "double j = F<5>();",
+      traverse(TK_AsIs,
+               substTemplateTypeParmType(hasReplacementType(qualType())))));
 }
 
 TEST(ClassTemplateSpecializationDecl, HasSpecializedTemplate) {
-  auto Matcher = classTemplateSpecializationDecl(
-      hasSpecializedTemplate(classTemplateDecl()));
+  auto Matcher =
+      traverse(TK_AsIs, classTemplateSpecializationDecl(
+                            hasSpecializedTemplate(classTemplateDecl())));
   EXPECT_TRUE(
       matches("template<typename T> class A {}; typedef A<int> B;", Matcher));
   EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher));
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -561,12 +561,12 @@
 
 TEST(Matcher, MatchesClassTemplateSpecialization) {
   EXPECT_TRUE(matches("template<typename T> struct A {};"
-                        "template<> struct A<int> {};",
-                      classTemplateSpecializationDecl()));
+                      "template<> struct A<int> {};",
+                      traverse(TK_AsIs, classTemplateSpecializationDecl())));
   EXPECT_TRUE(matches("template<typename T> struct A {}; A<int> a;",
-                      classTemplateSpecializationDecl()));
+                      traverse(TK_AsIs, classTemplateSpecializationDecl())));
   EXPECT_TRUE(notMatches("template<typename T> struct A {};",
-                         classTemplateSpecializationDecl()));
+                         traverse(TK_AsIs, classTemplateSpecializationDecl())));
 }
 
 TEST(DeclaratorDecl, MatchesDeclaratorDecls) {
@@ -1485,10 +1485,12 @@
                    "  return 1 + T();"
                    "}"
                    "int i = F<int>();";
-  EXPECT_FALSE(matches(code, binaryOperator(hasLHS(
-    expr(hasType(substTemplateTypeParmType()))))));
-  EXPECT_TRUE(matches(code, binaryOperator(hasRHS(
-    expr(hasType(substTemplateTypeParmType()))))));
+  EXPECT_FALSE(
+      matches(code, traverse(TK_AsIs, binaryOperator(hasLHS(expr(hasType(
+                                          substTemplateTypeParmType())))))));
+  EXPECT_TRUE(
+      matches(code, traverse(TK_AsIs, binaryOperator(hasRHS(expr(hasType(
+                                          substTemplateTypeParmType())))))));
 }
 
 TEST(NNS, MatchesNestedNameSpecifiers) {
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -493,9 +493,9 @@
   EXPECT_TRUE(notMatches("", IsAX));
 
   DeclarationMatcher ZIsDerivedFromX =
-    cxxRecordDecl(hasName("Z"), isDerivedFrom("X"));
-  DeclarationMatcher ZIsDirectlyDerivedFromX =
-      cxxRecordDecl(hasName("Z"), isDirectlyDerivedFrom("X"));
+      traverse(TK_AsIs, cxxRecordDecl(hasName("Z"), isDerivedFrom("X")));
+  DeclarationMatcher ZIsDirectlyDerivedFromX = traverse(
+      TK_AsIs, cxxRecordDecl(hasName("Z"), isDirectlyDerivedFrom("X")));
   EXPECT_TRUE(
     matches("class X {}; class Y : public X {}; class Z : public Y {};",
             ZIsDerivedFromX));
@@ -1248,42 +1248,49 @@
 }
 
 TEST(TemplateArgumentCountIs, Matches) {
-  EXPECT_TRUE(
-    matches("template<typename T> struct C {}; C<int> c;",
-            classTemplateSpecializationDecl(templateArgumentCountIs(1))));
-  EXPECT_TRUE(
-    notMatches("template<typename T> struct C {}; C<int> c;",
-               classTemplateSpecializationDecl(templateArgumentCountIs(2))));
+  EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
+                      traverse(TK_AsIs, classTemplateSpecializationDecl(
+                                            templateArgumentCountIs(1)))));
+  EXPECT_TRUE(notMatches("template<typename T> struct C {}; C<int> c;",
+                         traverse(TK_AsIs, classTemplateSpecializationDecl(
+                                               templateArgumentCountIs(2)))));
 
   EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
-                      templateSpecializationType(templateArgumentCountIs(1))));
-  EXPECT_TRUE(
-    notMatches("template<typename T> struct C {}; C<int> c;",
-               templateSpecializationType(templateArgumentCountIs(2))));
+                      traverse(TK_AsIs, templateSpecializationType(
+                                            templateArgumentCountIs(1)))));
+  EXPECT_TRUE(notMatches("template<typename T> struct C {}; C<int> c;",
+                         traverse(TK_AsIs, templateSpecializationType(
+                                               templateArgumentCountIs(2)))));
 }
 
 TEST(IsIntegral, Matches) {
-  EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(isIntegral()))));
-  EXPECT_TRUE(notMatches("template<typename T> struct C {}; C<int> c;",
-                         classTemplateSpecializationDecl(hasAnyTemplateArgument(
-                           templateArgument(isIntegral())))));
+  EXPECT_TRUE(
+      matches("template<int T> struct C {}; C<42> c;",
+              traverse(TK_AsIs, classTemplateSpecializationDecl(
+                                    hasAnyTemplateArgument(isIntegral())))));
+  EXPECT_TRUE(notMatches(
+      "template<typename T> struct C {}; C<int> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            templateArgument(isIntegral()))))));
 }
 
 TEST(EqualsIntegralValue, Matches) {
-  EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(equalsIntegralValue("42")))));
-  EXPECT_TRUE(matches("template<int T> struct C {}; C<-42> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(equalsIntegralValue("-42")))));
-  EXPECT_TRUE(matches("template<int T> struct C {}; C<-0042> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(equalsIntegralValue("-34")))));
-  EXPECT_TRUE(notMatches("template<int T> struct C {}; C<42> c;",
-                         classTemplateSpecializationDecl(hasAnyTemplateArgument(
-                           equalsIntegralValue("0042")))));
+  EXPECT_TRUE(matches(
+      "template<int T> struct C {}; C<42> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            equalsIntegralValue("42"))))));
+  EXPECT_TRUE(matches(
+      "template<int T> struct C {}; C<-42> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            equalsIntegralValue("-42"))))));
+  EXPECT_TRUE(matches(
+      "template<int T> struct C {}; C<-0042> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            equalsIntegralValue("-34"))))));
+  EXPECT_TRUE(notMatches(
+      "template<int T> struct C {}; C<42> c;",
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                            equalsIntegralValue("0042"))))));
 }
 
 TEST(Matcher, MatchesAccessSpecDecls) {
@@ -2056,56 +2063,63 @@
   // Make sure that we can both match the class by name (::X) and by the type
   // the template was instantiated with (via a field).
 
-  EXPECT_TRUE(matches(
-    "template <typename T> class X {}; class A {}; X<A> x;",
-    cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("template <typename T> class X {}; class A {}; X<A> x;",
+              traverse(TK_AsIs, cxxRecordDecl(hasName("::X"),
+                                              isTemplateInstantiation()))));
 
   EXPECT_TRUE(matches(
-    "template <typename T> class X { T t; }; class A {}; X<A> x;",
-    cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
-      fieldDecl(hasType(recordDecl(hasName("A"))))))));
+      "template <typename T> class X { T t; }; class A {}; X<A> x;",
+      traverse(TK_AsIs, cxxRecordDecl(isTemplateInstantiation(),
+                                      hasDescendant(fieldDecl(hasType(
+                                          recordDecl(hasName("A")))))))));
 }
 
 TEST(IsTemplateInstantiation, MatchesImplicitFunctionTemplateInstantiation) {
   EXPECT_TRUE(matches(
-    "template <typename T> void f(T t) {} class A {}; void g() { f(A()); }",
-    functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
-                 isTemplateInstantiation())));
+      "template <typename T> void f(T t) {} class A {}; void g() { f(A()); }",
+      traverse(TK_AsIs,
+               functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
+                            isTemplateInstantiation()))));
 }
 
 TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
   EXPECT_TRUE(matches(
-    "template <typename T> class X { T t; }; class A {};"
+      "template <typename T> class X { T t; }; class A {};"
       "template class X<A>;",
-    cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
-      fieldDecl(hasType(recordDecl(hasName("A"))))))));
+      traverse(TK_AsIs, cxxRecordDecl(isTemplateInstantiation(),
+                                      hasDescendant(fieldDecl(hasType(
+                                          recordDecl(hasName("A")))))))));
 
   // Make sure that we match the instantiation instead of the template
   // definition by checking whether the member function is present.
-  EXPECT_TRUE(
-      matches("template <typename T> class X { void f() { T t; } };"
-              "extern template class X<int>;",
-              cxxRecordDecl(isTemplateInstantiation(),
-                            unless(hasDescendant(varDecl(hasName("t")))))));
+  EXPECT_TRUE(matches(
+      "template <typename T> class X { void f() { T t; } };"
+      "extern template class X<int>;",
+      traverse(TK_AsIs,
+               cxxRecordDecl(isTemplateInstantiation(),
+                             unless(hasDescendant(varDecl(hasName("t"))))))));
 }
 
 TEST(IsTemplateInstantiation,
      MatchesInstantiationOfPartiallySpecializedClassTemplate) {
-  EXPECT_TRUE(matches(
-    "template <typename T> class X {};"
-      "template <typename T> class X<T*> {}; class A {}; X<A*> x;",
-    cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("template <typename T> class X {};"
+              "template <typename T> class X<T*> {}; class A {}; X<A*> x;",
+              traverse(TK_AsIs, cxxRecordDecl(hasName("::X"),
+                                              isTemplateInstantiation()))));
 }
 
 TEST(IsTemplateInstantiation,
      MatchesInstantiationOfClassTemplateNestedInNonTemplate) {
-  EXPECT_TRUE(matches(
-    "class A {};"
-      "class X {"
-      "  template <typename U> class Y { U u; };"
-      "  Y<A> y;"
-      "};",
-    cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("class A {};"
+              "class X {"
+              "  template <typename U> class Y { U u; };"
+              "  Y<A> y;"
+              "};",
+              traverse(TK_AsIs, cxxRecordDecl(hasName("::X::Y"),
+                                              isTemplateInstantiation()))));
 }
 
 TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
@@ -2113,73 +2127,79 @@
   // normal use case as long as the uppermost instantiation always is marked
   // as template instantiation, but it might be confusing as a predicate.
   EXPECT_TRUE(matches(
-    "class A {};"
+      "class A {};"
       "template <typename T> class X {"
       "  template <typename U> class Y { U u; };"
       "  Y<T> y;"
       "}; X<A> x;",
-    cxxRecordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
+      traverse(TK_AsIs, cxxRecordDecl(hasName("::X<A>::Y"),
+                                      unless(isTemplateInstantiation())))));
 }
 
 TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) {
-  EXPECT_TRUE(notMatches(
-    "template <typename T> class X {}; class A {};"
-      "template <> class X<A> {}; X<A> x;",
-    cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      notMatches("template <typename T> class X {}; class A {};"
+                 "template <> class X<A> {}; X<A> x;",
+                 traverse(TK_AsIs, cxxRecordDecl(hasName("::X"),
+                                                 isTemplateInstantiation()))));
 }
 
 TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
-  EXPECT_TRUE(notMatches(
-    "class A {}; class Y { A a; };",
-    cxxRecordDecl(isTemplateInstantiation())));
+  EXPECT_TRUE(
+      notMatches("class A {}; class Y { A a; };",
+                 traverse(TK_AsIs, cxxRecordDecl(isTemplateInstantiation()))));
 }
 
 TEST(IsInstantiated, MatchesInstantiation) {
   EXPECT_TRUE(
-    matches("template<typename T> class A { T i; }; class Y { A<int> a; };",
-            cxxRecordDecl(isInstantiated())));
+      matches("template<typename T> class A { T i; }; class Y { A<int> a; };",
+              traverse(TK_AsIs, cxxRecordDecl(isInstantiated()))));
 }
 
 TEST(IsInstantiated, NotMatchesDefinition) {
   EXPECT_TRUE(notMatches("template<typename T> class A { T i; };",
-                         cxxRecordDecl(isInstantiated())));
+                         traverse(TK_AsIs, cxxRecordDecl(isInstantiated()))));
 }
 
 TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) {
-  EXPECT_TRUE(matches("template<typename T> struct A { A() { T i; } };"
-                        "class Y { A<int> a; }; Y y;",
-                      declStmt(isInTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("template<typename T> struct A { A() { T i; } };"
+              "class Y { A<int> a; }; Y y;",
+              traverse(TK_AsIs, declStmt(isInTemplateInstantiation()))));
 }
 
 TEST(IsInTemplateInstantiation, NotMatchesDefinitionStmt) {
-  EXPECT_TRUE(notMatches("template<typename T> struct A { void x() { T i; } };",
-                         declStmt(isInTemplateInstantiation())));
+  EXPECT_TRUE(
+      notMatches("template<typename T> struct A { void x() { T i; } };",
+                 traverse(TK_AsIs, declStmt(isInTemplateInstantiation()))));
 }
 
 TEST(IsInstantiated, MatchesFunctionInstantiation) {
   EXPECT_TRUE(
-    matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
-            functionDecl(isInstantiated())));
+      matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
+              traverse(TK_AsIs, functionDecl(isInstantiated()))));
 }
 
 TEST(IsInstantiated, NotMatchesFunctionDefinition) {
   EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }",
-                         varDecl(isInstantiated())));
+                         traverse(TK_AsIs, varDecl(isInstantiated()))));
 }
 
 TEST(IsInTemplateInstantiation, MatchesFunctionInstantiationStmt) {
   EXPECT_TRUE(
-    matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
-            declStmt(isInTemplateInstantiation())));
+      matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
+              traverse(TK_AsIs, declStmt(isInTemplateInstantiation()))));
 }
 
 TEST(IsInTemplateInstantiation, NotMatchesFunctionDefinitionStmt) {
-  EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }",
-                         declStmt(isInTemplateInstantiation())));
+  EXPECT_TRUE(
+      notMatches("template<typename T> void A(T t) { T i; }",
+                 traverse(TK_AsIs, declStmt(isInTemplateInstantiation()))));
 }
 
 TEST(IsInTemplateInstantiation, Sharing) {
-  auto Matcher = binaryOperator(unless(isInTemplateInstantiation()));
+  auto Matcher =
+      traverse(TK_AsIs, binaryOperator(unless(isInTemplateInstantiation())));
   // FIXME: Node sharing is an implementation detail, exposing it is ugly
   // and makes the matcher behave in non-obvious ways.
   EXPECT_TRUE(notMatches(
Index: clang/unittests/AST/StructuralEquivalenceTest.cpp
===================================================================
--- clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -933,7 +933,8 @@
 // Instantiate with substitution Arg into P1.
 template class Templ <Arg>;
       )",
-      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
+      Lang_CXX03,
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("Primary"))));
   EXPECT_TRUE(testStructuralMatch(t));
 }
 
@@ -964,7 +965,8 @@
 // Instantiate with substitution Arg into P1.
 template class Templ <Arg>;
       )",
-      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));
+      Lang_CXX03,
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("Primary"))));
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
@@ -987,8 +989,9 @@
         void f();
       };
       )";
-  auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
-                                           functionTemplateDecl(hasName("f")));
+  auto t = makeDecls<FunctionTemplateDecl>(
+      Code, Code, Lang_CXX11,
+      traverse(TK_AsIs, functionTemplateDecl(hasName("f"))));
   EXPECT_TRUE(testStructuralMatch(t));
 }
 
@@ -1005,22 +1008,22 @@
       template <typename>
       struct enable_if;
       )";
-  auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
+  auto t = makeDecls<FunctionTemplateDecl>(
+      Code + R"(
       struct S
       {
         template <typename T, typename enable_if<S1<T>>::type>
         void f();
       };
       )",
-                                           Code + R"(
+      Code + R"(
       struct S
       {
         template <typename T, typename enable_if<S2<T>>::type>
         void f();
       };
       )",
-                                           Lang_CXX11,
-                                           functionTemplateDecl(hasName("f")));
+      Lang_CXX11, traverse(TK_AsIs, functionTemplateDecl(hasName("f"))));
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
@@ -1040,8 +1043,9 @@
         void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^
       };
       )";
-  auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,
-                                           functionTemplateDecl(hasName("f")));
+  auto t = makeDecls<FunctionTemplateDecl>(
+      Code, Code, Lang_CXX11,
+      traverse(TK_AsIs, functionTemplateDecl(hasName("f"))));
   EXPECT_TRUE(testStructuralMatch(t));
 }
 
@@ -1058,22 +1062,22 @@
       template <bool>
       struct enable_if;
       )";
-  auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
+  auto t = makeDecls<FunctionTemplateDecl>(
+      Code + R"(
       struct S
       {
         template <typename T, typename enable_if<S1<T>::value>::type>
         void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^
       };
       )",
-                                           Code + R"(
+      Code + R"(
       struct S
       {
         template <typename T, typename enable_if<S2<T>::value>::type>
         void f();
       };
       )",
-                                           Lang_CXX03,
-                                           functionTemplateDecl(hasName("f")));
+      Lang_CXX03, traverse(TK_AsIs, functionTemplateDecl(hasName("f"))));
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
@@ -1087,22 +1091,22 @@
       template <bool>
       struct enable_if;
       )";
-  auto t = makeDecls<FunctionTemplateDecl>(Code + R"(
+  auto t = makeDecls<FunctionTemplateDecl>(
+      Code + R"(
       struct S
       {
         template <typename T, typename enable_if<S1<T>::value1>::type>
         void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^
       };
       )",
-                                           Code + R"(
+      Code + R"(
       struct S
       {
         template <typename T, typename enable_if<S1<T>::value2>::type>
         void f();
       };
       )",
-                                           Lang_CXX03,
-                                           functionTemplateDecl(hasName("f")));
+      Lang_CXX03, traverse(TK_AsIs, functionTemplateDecl(hasName("f"))));
   EXPECT_FALSE(testStructuralMatch(t));
 }
 
Index: clang/unittests/AST/SourceLocationTest.cpp
===================================================================
--- clang/unittests/AST/SourceLocationTest.cpp
+++ clang/unittests/AST/SourceLocationTest.cpp
@@ -269,10 +269,10 @@
 TEST(CompoundLiteralExpr, ParensCompoundVectorLiteralRange) {
   RangeVerifier<CompoundLiteralExpr> Verifier;
   Verifier.expectRange(2, 20, 2, 31);
-  EXPECT_TRUE(Verifier.match(
-                  "typedef int int2 __attribute__((ext_vector_type(2)));\n"
-                  "constant int2 i2 = (int2)(1, 2);", 
-                  compoundLiteralExpr(), Lang_OpenCL));
+  EXPECT_TRUE(
+      Verifier.match("typedef int int2 __attribute__((ext_vector_type(2)));\n"
+                     "constant int2 i2 = (int2)(1, 2);",
+                     compoundLiteralExpr(), Lang_OpenCL));
 }
 
 TEST(InitListExpr, VectorLiteralListBraceRange) {
@@ -612,14 +612,15 @@
 TEST(FriendDecl, InstantiationSourceRange) {
   RangeVerifier<FriendDecl> Verifier;
   Verifier.expectRange(4, 3, 4, 35);
-  EXPECT_TRUE(Verifier.match(
-      "template <typename T> class S;\n"
-      "template<class T> void operator+(S<T> x);\n"
-      "template<class T> struct S {\n"
-      "  friend void operator+<>(S<T> src);\n"
-      "};\n"
-      "void test(S<double> s) { +s; }",
-      friendDecl(hasParent(cxxRecordDecl(isTemplateInstantiation())))));
+  EXPECT_TRUE(
+      Verifier.match("template <typename T> class S;\n"
+                     "template<class T> void operator+(S<T> x);\n"
+                     "template<class T> struct S {\n"
+                     "  friend void operator+<>(S<T> src);\n"
+                     "};\n"
+                     "void test(S<double> s) { +s; }",
+                     traverse(TK_AsIs, friendDecl(hasParent(cxxRecordDecl(
+                                           isTemplateInstantiation()))))));
 }
 
 TEST(ObjCMessageExpr, ParenExprRange) {
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...) {}
@@ -234,7 +242,8 @@
   }
 
   auto Result = ast_matchers::match(
-      classTemplateSpecializationDecl(hasName("templ")).bind("fn"),
+      traverse(TK_AsIs,
+               classTemplateSpecializationDecl(hasName("templ")).bind("fn")),
       AST->getASTContext());
   EXPECT_EQ(Result.size(), 1u);
   auto Templ = Result[0].getNodeAs<ClassTemplateSpecializationDecl>("fn");
@@ -243,7 +252,7 @@
 
   verifyWithDynNode(TA,
                     R"cpp(
-TemplateArgument
+TemplateArgument type int
 )cpp");
 
   Func = getFunctionNode(AST.get(), "parmvardecl_attr");
@@ -420,8 +429,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 +883,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/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -3260,7 +3260,7 @@
       }
       )", Lang_CXX11);
   auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      ToTU, classTemplateSpecializationDecl(hasName("X")));
+      ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   // FieldDecl without InitlistExpr:
   auto *ToField = *ToSpec->field_begin();
   ASSERT_TRUE(ToField);
@@ -3273,7 +3273,7 @@
       }
       )", Lang_CXX11);
   auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      FromTU, classTemplateSpecializationDecl(hasName("X")));
+      FromTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   // FieldDecl with InitlistExpr:
   auto *FromField = *FromSpec->field_begin();
   ASSERT_TRUE(FromField);
@@ -3312,19 +3312,19 @@
       }
       )", Lang_CXX11);
   auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      FromTU, classTemplateSpecializationDecl(hasName("X")));
+      FromTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   auto FunPattern = functionDecl(hasName("g"),
                          hasParent(classTemplateSpecializationDecl()));
-  auto *FromFun =
-      FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
-  auto *ToFun =
-      FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
+  auto *FromFun = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, traverse(TK_AsIs, FunPattern));
+  auto *ToFun = FirstDeclMatcher<FunctionDecl>().match(
+      ToTU, traverse(TK_AsIs, FunPattern));
   ASSERT_TRUE(FromFun->hasBody());
   ASSERT_FALSE(ToFun->hasBody());
   auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
   ASSERT_TRUE(ImportedSpec);
   auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      ToTU, classTemplateSpecializationDecl(hasName("X")));
+      ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   EXPECT_EQ(ImportedSpec, ToSpec);
   EXPECT_TRUE(ToFun->hasBody());
 }
@@ -3359,7 +3359,7 @@
       )",
                            Lang_CXX11);
   auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      FromTU, classTemplateSpecializationDecl(hasName("X")));
+      FromTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
 
   // We expect one (ODR) warning during the import.
@@ -3369,9 +3369,9 @@
   // ODR, consequently we expect to keep the first specialization only, which is
   // already in the "To" context.
   EXPECT_FALSE(ImportedSpec);
-  EXPECT_EQ(1u,
-            DeclCounter<ClassTemplateSpecializationDecl>().match(
-                ToTU, classTemplateSpecializationDecl(hasName("X"))));
+  EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
+                    ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl(
+                                                hasName("X")))));
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase,
@@ -3397,21 +3397,21 @@
       }
       )", Lang_CXX11);
   auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      FromTU, classTemplateSpecializationDecl(hasName("X")));
+      FromTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   // Match the void(int) ctor.
   auto CtorPattern =
       cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
                          hasParent(classTemplateSpecializationDecl()));
-  auto *FromCtor =
-      FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
-  auto *ToCtor =
-      FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
+  auto *FromCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
+      FromTU, traverse(TK_AsIs, CtorPattern));
+  auto *ToCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
+      ToTU, traverse(TK_AsIs, CtorPattern));
   ASSERT_TRUE(FromCtor->hasBody());
   ASSERT_FALSE(ToCtor->hasBody());
   auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
   ASSERT_TRUE(ImportedSpec);
   auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      ToTU, classTemplateSpecializationDecl(hasName("X")));
+      ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   EXPECT_EQ(ImportedSpec, ToSpec);
   EXPECT_TRUE(ToCtor->hasBody());
 }
@@ -3432,15 +3432,16 @@
   Decl *FromTU = getTuDecl(Code, Lang_CXX11);
   auto *FromSpec =
       FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
-          FromTU, classTemplatePartialSpecializationDecl());
+          FromTU, traverse(TK_AsIs, classTemplatePartialSpecializationDecl()));
   auto *ToSpec =
       FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
-          ToTU, classTemplatePartialSpecializationDecl());
+          ToTU, traverse(TK_AsIs, classTemplatePartialSpecializationDecl()));
 
   auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
   EXPECT_EQ(ImportedSpec, ToSpec);
   EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
-                    ToTU, classTemplatePartialSpecializationDecl()));
+                    ToTU, traverse(TK_AsIs,
+                                   classTemplatePartialSpecializationDecl())));
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase,
@@ -3458,14 +3459,15 @@
   Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
   Decl *FromTU = getTuDecl(Code, Lang_CXX11);
   auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      FromTU, classTemplateSpecializationDecl());
+      FromTU, traverse(TK_AsIs, classTemplateSpecializationDecl()));
   auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      ToTU, classTemplateSpecializationDecl());
+      ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl()));
 
   auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
   EXPECT_EQ(ImportedSpec, ToSpec);
-  EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
-                   ToTU, classTemplateSpecializationDecl()));
+  EXPECT_EQ(1u,
+            DeclCounter<ClassTemplateSpecializationDecl>().match(
+                ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl())));
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase,
@@ -3488,17 +3490,20 @@
   Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
   Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
   auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      FromTU, classTemplateSpecializationDecl());
+      FromTU, traverse(TK_AsIs, classTemplateSpecializationDecl()));
 
   auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
   EXPECT_TRUE(ImportedSpec);
   // Check the number of partial specializations.
   EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
-                    ToTU, classTemplatePartialSpecializationDecl()));
+                    ToTU, traverse(TK_AsIs,
+                                   classTemplatePartialSpecializationDecl())));
   // Check the number of full specializations.
-  EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
-                    ToTU, classTemplateSpecializationDecl(
-                              unless(classTemplatePartialSpecializationDecl()))));
+  EXPECT_EQ(
+      1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
+              ToTU, traverse(TK_AsIs,
+                             classTemplateSpecializationDecl(unless(
+                                 classTemplatePartialSpecializationDecl())))));
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase,
@@ -3794,7 +3799,8 @@
 }
 
 TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
-  auto Pattern = classTemplateSpecializationDecl(hasName("X"));
+  auto Pattern =
+      traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X")));
 
   ClassTemplateSpecializationDecl *Imported1;
   {
@@ -4050,8 +4056,9 @@
       Lang_CXX03, "input0.cc");
 
   // Check that the function template instantiation is NOT the child of the TU.
-  auto Pattern = translationUnitDecl(
-      unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
+  auto Pattern =
+      traverse(TK_AsIs, translationUnitDecl(unless(has(functionDecl(
+                            hasName("f"), isTemplateInstantiation())))));
   ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
 
   auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
@@ -4074,8 +4081,10 @@
       Lang_CXX03, "input0.cc");
 
   // Check that the function template instantiation is NOT the child of the TU.
-  auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
-  auto Pattern = translationUnitDecl(unless(has(Instantiation)));
+  auto Instantiation =
+      traverse(TK_AsIs, functionDecl(hasName("f"), isTemplateInstantiation()));
+  auto Pattern =
+      traverse(TK_AsIs, translationUnitDecl(unless(has(Instantiation))));
   ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
 
   ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),
@@ -4642,7 +4651,7 @@
       fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
 
   auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
-      ToTU, classTemplateSpecializationDecl(hasName("X")));
+      ToTU, traverse(TK_AsIs, classTemplateSpecializationDecl(hasName("X"))));
   FieldDecl *FieldInSpec = *Spec->field_begin();
   ASSERT_TRUE(FieldInSpec);
 
Index: clang/unittests/AST/ASTContextParentMapTest.cpp
===================================================================
--- clang/unittests/AST/ASTContextParentMapTest.cpp
+++ clang/unittests/AST/ASTContextParentMapTest.cpp
@@ -54,20 +54,24 @@
   EXPECT_TRUE(DeclVerifier.match(
       "template<typename T> struct C { void f() {} };"
       "void g() { C<int> c; c.f(); }",
-      cxxMethodDecl(hasName("f"),
-                 hasParent(cxxRecordDecl(isTemplateInstantiation())))));
+      traverse(TK_AsIs,
+               cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(
+                                               isTemplateInstantiation()))))));
   EXPECT_TRUE(DeclVerifier.match(
       "template<typename T> struct C { void f() {} };"
       "void g() { C<int> c; c.f(); }",
-      cxxMethodDecl(hasName("f"),
-                 hasParent(cxxRecordDecl(unless(isTemplateInstantiation()))))));
+      traverse(TK_AsIs,
+               cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(unless(
+                                               isTemplateInstantiation())))))));
   EXPECT_FALSE(DeclVerifier.match(
       "template<typename T> struct C { void f() {} };"
       "void g() { C<int> c; c.f(); }",
-      cxxMethodDecl(
-          hasName("f"),
-          allOf(hasParent(cxxRecordDecl(unless(isTemplateInstantiation()))),
-                hasParent(cxxRecordDecl(isTemplateInstantiation()))))));
+      traverse(
+          TK_AsIs,
+          cxxMethodDecl(
+              hasName("f"),
+              allOf(hasParent(cxxRecordDecl(unless(isTemplateInstantiation()))),
+                    hasParent(cxxRecordDecl(isTemplateInstantiation())))))));
 }
 
 TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) {
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);
 
@@ -302,6 +309,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,44 @@
   bool shouldVisitTemplateInstantiations() const { return true; }
   bool shouldVisitImplicitCode() const { return true; }
 
+  bool TraversingImplicitTemplateInstantiation = false;
+
+  bool isMatchingInImplicitTemplateInstantiation() const override {
+    return TraversingImplicitTemplateInstantiation;
+  }
+
+  struct ImplicitTemplateInstantiationScope {
+    ImplicitTemplateInstantiationScope(MatchASTVisitor *V, bool B)
+        : MV(V), MB(V->TraversingImplicitTemplateInstantiation) {
+      V->TraversingImplicitTemplateInstantiation = B;
+    }
+    ~ImplicitTemplateInstantiationScope() {
+      MV->TraversingImplicitTemplateInstantiation = MB;
+    }
+
+  private:
+    MatchASTVisitor *MV;
+    bool MB;
+  };
+
+  bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
+    ImplicitTemplateInstantiationScope RAII(this, true);
+    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
+        D);
+  }
+
+  bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
+    ImplicitTemplateInstantiationScope RAII(this, true);
+    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
+        D);
+  }
+
+  bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
+    ImplicitTemplateInstantiationScope RAII(this, true);
+    return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateInstantiations(
+        D);
+  }
+
 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
@@ -585,6 +585,10 @@
       return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
                                         Builder);
     }
+
+    llvm::Optional<clang::TraversalKind> TraversalKind() const override {
+      return this->InnerMatcher.getTraversalKind();
+    }
   };
 
 private:
@@ -1056,6 +1060,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/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -508,6 +508,13 @@
 
   bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child);
 
+#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND)                                   \
+  bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
+  DEF_TRAVERSE_TMPL_INST(Class)
+  DEF_TRAVERSE_TMPL_INST(Var)
+  DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+
 private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
@@ -516,12 +523,6 @@
   template <typename T>
   bool TraverseDeclTemplateParameterLists(T *D);
 
-#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND)                                   \
-  bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
-  DEF_TRAVERSE_TMPL_INST(Class)
-  DEF_TRAVERSE_TMPL_INST(Var)
-  DEF_TRAVERSE_TMPL_INST(Function)
-#undef DEF_TRAVERSE_TMPL_INST
   bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
                                           unsigned Count);
   bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
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/misc/UnusedUsingDeclsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
@@ -62,20 +62,24 @@
   auto DeclMatcher = hasDeclaration(namedDecl().bind("used"));
   Finder->addMatcher(loc(enumType(DeclMatcher)), this);
   Finder->addMatcher(loc(recordType(DeclMatcher)), this);
-  Finder->addMatcher(loc(templateSpecializationType(DeclMatcher)), this);
-  Finder->addMatcher(loc(deducedTemplateSpecializationType(
-                         refsToTemplatedDecl(namedDecl().bind("used")))),
-                     this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, loc(templateSpecializationType(DeclMatcher))), this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, loc(deducedTemplateSpecializationType(
+                            refsToTemplatedDecl(namedDecl().bind("used"))))),
+      this);
   Finder->addMatcher(declRefExpr().bind("used"), this);
   Finder->addMatcher(callExpr(callee(unresolvedLookupExpr().bind("used"))),
                      this);
   Finder->addMatcher(
-      callExpr(hasDeclaration(functionDecl(
-          forEachTemplateArgument(templateArgument().bind("used"))))),
+      traverse(TK_AsIs,
+               callExpr(hasDeclaration(functionDecl(
+                   forEachTemplateArgument(templateArgument().bind("used")))))),
+      this);
+  Finder->addMatcher(
+      traverse(TK_AsIs, loc(templateSpecializationType(forEachTemplateArgument(
+                            templateArgument().bind("used"))))),
       this);
-  Finder->addMatcher(loc(templateSpecializationType(forEachTemplateArgument(
-                         templateArgument().bind("used")))),
-                     this);
 }
 
 void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) {
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