diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 60ff6ffe6056..eb85e420e7e4 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -679,7 +679,8 @@ Given #pragma omp parallel default(firstprivate) #pragma omp parallel -``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and ``default(firstprivate)``. +``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and +``default(firstprivate)`` @@ -1625,6 +1626,17 @@ whileStmt() +Matcher<TemplateArgumentLoc>templateArgumentLocMatcher<TemplateArgumentLoc>... +
Matches template arguments (with location info).
+
+Given
+  template <typename T> struct C {};
+  C<int> c;
+templateArgumentLoc()
+  matches 'int' in C<int>.
+
+ + Matcher<TemplateArgument>templateArgumentMatcher<TemplateArgument>...
Matches template arguments.
 
@@ -3776,6 +3788,22 @@ namespaceDecl(isInline()) will match n::m.
 
+Matcher<OMPDefaultClause>isFirstPrivateKind +
Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
+specified.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel default(none)
+  #pragma omp parallel default(shared)
+  #pragma omp parallel default(firstprivate)
+
+``ompDefaultClause(isFirstPrivateKind())`` matches only
+``default(firstprivate)``.
+
+ + Matcher<OMPDefaultClause>isNoneKind
Matches if the OpenMP ``default`` clause has ``none`` kind specified.
 
@@ -3804,20 +3832,6 @@ Given
 
-Matcher<OMPDefaultClause>isSharedKind -
Matches if the OpenMP ``default`` clause has ``firstprivate`` kind specified.
-
-Given
-
-  #pragma omp parallel
-  #pragma omp parallel default(none)
-  #pragma omp parallel default(shared)
-  #pragma omp parallel default(firstprivate)
-
-``ompDefaultClause(isFirstPrivateKind())`` matches only ``default(firstprivate)``.
-
- - Matcher<OMPExecutableDirective>isAllowedToContainClauseKindOpenMPClauseKind CKind
Matches if the OpenMP directive is allowed to contain the specified OpenMP
 clause kind.
diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h
index 328b7bce6ba5..bd817b75bb84 100644
--- a/clang/include/clang/AST/ASTTypeTraits.h
+++ b/clang/include/clang/AST/ASTTypeTraits.h
@@ -132,6 +132,7 @@ private:
   enum NodeKindId {
     NKI_None,
     NKI_TemplateArgument,
+    NKI_TemplateArgumentLoc,
     NKI_TemplateName,
     NKI_NestedNameSpecifierLoc,
     NKI_QualType,
@@ -191,6 +192,7 @@ private:
   };
 KIND_TO_KIND_ID(CXXCtorInitializer)
 KIND_TO_KIND_ID(TemplateArgument)
+KIND_TO_KIND_ID(TemplateArgumentLoc)
 KIND_TO_KIND_ID(TemplateName)
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
@@ -456,12 +458,13 @@ private:
   /// Note that we can store \c Decls, \c Stmts, \c Types,
   /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
   /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
-  /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
-  /// \c TemplateArguments on the other hand do not have storage or unique
-  /// pointers and thus need to be stored by value.
+  /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs,
+  /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not
+  /// have storage or unique pointers and thus need to be stored by value.
   llvm::AlignedCharArrayUnion Storage;
+                              TemplateArgumentLoc, NestedNameSpecifierLoc,
+                              QualType, TypeLoc>
+      Storage;
 };
 
 template 
@@ -496,6 +499,10 @@ template <>
 struct DynTypedNode::BaseConverter<
     TemplateArgument, void> : public ValueConverter {};
 
+template <>
+struct DynTypedNode::BaseConverter
+    : public ValueConverter {};
+
 template <>
 struct DynTypedNode::BaseConverter<
     TemplateName, void> : public ValueConverter {};
diff --git a/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/clang/include/clang/ASTMatchers/ASTMatchFinder.h
index 0af98438ab52..81125ad8d96d 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -159,6 +159,8 @@ public:
                   MatchCallback *Action);
   void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
                   MatchCallback *Action);
+  void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
+                  MatchCallback *Action);
   /// @}
 
   /// Adds a matcher to execute when running over the AST.
@@ -209,6 +211,8 @@ public:
         NestedNameSpecifierLoc;
     std::vector> TypeLoc;
     std::vector> CtorInit;
+    std::vector>
+        TemplateArgumentLoc;
     /// All the callbacks in one container to simplify iteration.
     llvm::SmallPtrSet AllCallbacks;
   };
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 643419743a11..e37c68a8f156 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -145,6 +145,7 @@ using TypeLocMatcher = internal::Matcher;
 using NestedNameSpecifierMatcher = internal::Matcher;
 using NestedNameSpecifierLocMatcher = internal::Matcher;
 using CXXCtorInitializerMatcher = internal::Matcher;
+using TemplateArgumentLocMatcher = internal::Matcher;
 /// @}
 
 /// Matches any node.
@@ -515,6 +516,18 @@ extern const internal::VariadicAllOfMatcher
 ///   matches 'int' in C.
 extern const internal::VariadicAllOfMatcher templateArgument;
 
+/// Matches template arguments (with location info).
+///
+/// Given
+/// \code
+///   template  struct C {};
+///   C c;
+/// \endcode
+/// templateArgumentLoc()
+///   matches 'int' in C.
+extern const internal::VariadicAllOfMatcher
+    templateArgumentLoc;
+
 /// Matches template name.
 ///
 /// Given
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 3992850c992d..09774b3c912c 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -938,14 +938,13 @@ private:
 template 
 struct IsBaseType {
   static const bool value =
-      std::is_same::value ||
-      std::is_same::value ||
-      std::is_same::value ||
-      std::is_same::value ||
+      std::is_same::value || std::is_same::value ||
+      std::is_same::value || std::is_same::value ||
       std::is_same::value ||
       std::is_same::value ||
       std::is_same::value ||
-      std::is_same::value;
+      std::is_same::value ||
+      std::is_same::value;
 };
 template 
 const bool IsBaseType::value;
diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp
index 34fc587694be..ce8a321a691f 100644
--- a/clang/lib/AST/ASTTypeTraits.cpp
+++ b/clang/lib/AST/ASTTypeTraits.cpp
@@ -23,6 +23,7 @@ using namespace clang;
 const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
   { NKI_None, "" },
   { NKI_None, "TemplateArgument" },
+  { NKI_None, "TemplateArgumentLoc" },
   { NKI_None, "TemplateName" },
   { NKI_None, "NestedNameSpecifierLoc" },
   { NKI_None, "QualType" },
@@ -129,6 +130,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
                          const PrintingPolicy &PP) const {
   if (const TemplateArgument *TA = get())
     TA->print(PP, OS);
+  else if (const TemplateArgumentLoc *TAL = get())
+    TAL->getArgument().print(PP, OS);
   else if (const TemplateName *TN = get())
     TN->print(OS, PP);
   else if (const NestedNameSpecifier *NNS = get())
@@ -175,6 +178,8 @@ SourceRange DynTypedNode::getSourceRange() const {
     return D->getSourceRange();
   if (const Stmt *S = get())
     return S->getSourceRange();
+  if (const TemplateArgumentLoc *TAL = get())
+    return TAL->getSourceRange();
   if (const auto *C = get())
     return SourceRange(C->getBeginLoc(), C->getEndLoc());
   return SourceRange();
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index e88da16dd3d4..dc937dde88e3 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -128,6 +128,9 @@ public:
       traverse(*T);
     else if (const auto *C = DynNode.get())
       traverse(*C);
+    else if (const TemplateArgumentLoc *TALoc =
+                 DynNode.get())
+      traverse(*TALoc);
     // FIXME: Add other base types after adding tests.
 
     // It's OK to always overwrite the bound nodes, as if there was
@@ -224,6 +227,10 @@ public:
     ScopedIncrement ScopedDepth(&CurrentDepth);
     return traverse(*CtorInit);
   }
+  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
+    ScopedIncrement ScopedDepth(&CurrentDepth);
+    return traverse(TAL);
+  }
   bool TraverseLambdaExpr(LambdaExpr *Node) {
     if (Finder->getASTContext().getParentMapContext().getTraversalKind() !=
         TK_IgnoreUnlessSpelledInSource)
@@ -304,6 +311,9 @@ private:
     return VisitorBase::TraverseConstructorInitializer(
         const_cast(&CtorInit));
   }
+  bool baseTraverse(TemplateArgumentLoc TAL) {
+    return VisitorBase::TraverseTemplateArgumentLoc(TAL);
+  }
 
   // Sets 'Matched' to true if 'Matcher' matches 'Node' and:
   //   0 < CurrentDepth <= MaxDepth.
@@ -447,6 +457,7 @@ public:
   bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
   bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
+  bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
 
   // Matches children or descendants of 'Node' with 'BaseMatcher'.
   bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx,
@@ -557,6 +568,8 @@ public:
       match(*N);
     } else if (auto *N = Node.get()) {
       match(*N);
+    } else if (auto *N = Node.get()) {
+      match(*N);
     }
   }
 
@@ -680,6 +693,9 @@ private:
   void matchDispatch(const CXXCtorInitializer *Node) {
     matchWithoutFilter(*Node, Matchers->CtorInit);
   }
+  void matchDispatch(const TemplateArgumentLoc *Node) {
+    matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
+  }
   void matchDispatch(const void *) { /* Do nothing. */ }
   /// @}
 
@@ -1035,6 +1051,11 @@ bool MatchASTVisitor::TraverseConstructorInitializer(
       CtorInit);
 }
 
+bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
+  match(Loc);
+  return RecursiveASTVisitor::TraverseTemplateArgumentLoc(Loc);
+}
+
 class MatchASTConsumer : public ASTConsumer {
 public:
   MatchASTConsumer(MatchFinder *Finder,
@@ -1111,6 +1132,12 @@ void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
   Matchers.AllCallbacks.insert(Action);
 }
 
+void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
+                             MatchCallback *Action) {
+  Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
+  Matchers.AllCallbacks.insert(Action);
+}
+
 bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
                                     MatchCallback *Action) {
   if (NodeMatch.canConvertTo()) {
@@ -1134,6 +1161,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
   } else if (NodeMatch.canConvertTo()) {
     addMatcher(NodeMatch.convertTo(), Action);
     return true;
+  } else if (NodeMatch.canConvertTo()) {
+    addMatcher(NodeMatch.convertTo(), Action);
+    return true;
   }
   return false;
 }
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 4b9baf7a0e75..5b9476f3098a 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -734,6 +734,7 @@ const internal::VariadicDynCastAllOfMatcher
     accessSpecDecl;
 const internal::VariadicAllOfMatcher cxxCtorInitializer;
 const internal::VariadicAllOfMatcher templateArgument;
+const internal::VariadicAllOfMatcher templateArgumentLoc;
 const internal::VariadicAllOfMatcher templateName;
 const internal::VariadicDynCastAllOfMatcher
     nonTypeTemplateParmDecl;
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 380538697f46..c7db52b37a50 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -2637,6 +2637,19 @@ TEST(Has, DoesNotDeleteBindings) {
     std::make_unique>("x", 1)));
 }
 
+TEST(TemplateArgumentLoc, Matches) {
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      R"cpp(
+        template  class C> class X {};
+        class A {};
+        const int B = 42;
+        template  class C {};
+        X x;
+      )cpp",
+      templateArgumentLoc().bind("x"),
+      std::make_unique>("x", 3)));
+}
+
 TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
   // Those matchers cover all the cases where an inner matcher is called
   // and there is not a 1:1 relationship between the match of the outer