diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -573,15 +573,6 @@ Return typeNameParameters -Matcher<CXXBaseSpecifier>cxxBaseSpecifierMatcher<CXXBaseSpecifier>... -
Matches class bases.
-
-Examples matches public virtual B.
-  class B {};
-  class C : public virtual B {};
-
- - Matcher<Attr>attrMatcher<Attr>...
Matches attributes.
 Attributes may be attached with a variety of different syntaxes (including
@@ -600,6 +591,15 @@
 
+Matcher<CXXBaseSpecifier>cxxBaseSpecifierMatcher<CXXBaseSpecifier>... +
Matches class bases.
+
+Examples matches public virtual B.
+  class B {};
+  class C : public virtual B {};
+
+ + Matcher<CXXCtorInitializer>cxxCtorInitializerMatcher<CXXCtorInitializer>...
Matches constructor initializers.
 
@@ -633,7 +633,7 @@
 
-Matcher<Decl>blockDeclMatcher<BlockDecl>... +Matcher<Decl>blockDeclMatcher<BlockDecl>...
Matches block declarations.
 
 Example matches the declaration of the nameless block printing an input
@@ -943,7 +943,7 @@
 
-Matcher<Decl>objcIvarDeclMatcher<ObjCIvarDecl>... +Matcher<Decl>objcIvarDeclMatcher<ObjCIvarDecl>...
Matches Objective-C instance variable declarations.
 
 Example matches _enabled
@@ -954,7 +954,7 @@
 
-Matcher<Decl>objcMethodDeclMatcher<ObjCMethodDecl>... +Matcher<Decl>objcMethodDeclMatcher<ObjCMethodDecl>...
Matches Objective-C method declarations.
 
 Example matches both declaration and definition of -[Foo method]
@@ -968,7 +968,7 @@
 
-Matcher<Decl>objcPropertyDeclMatcher<ObjCPropertyDecl>... +Matcher<Decl>objcPropertyDeclMatcher<ObjCPropertyDecl>...
Matches Objective-C property declarations.
 
 Example matches enabled
@@ -1160,6 +1160,16 @@
   matches using namespace X 
+Matcher<Decl>usingEnumDeclMatcher<UsingEnumDecl>... +
Matches using-enum declarations.
+
+Given
+  namespace X { enum x {...}; }
+  using enum X::x;
+usingEnumDecl()
+  matches using enum X::x 
+ + Matcher<Decl>valueDeclMatcher<ValueDecl>...
Matches any value declaration.
 
@@ -1200,7 +1210,7 @@
 
-Matcher<OMPClause>ompDefaultClauseMatcher<OMPDefaultClause>... +Matcher<OMPClause>ompDefaultClauseMatcher<OMPDefaultClause>...
Matches OpenMP ``default`` clause.
 
 Given
@@ -1252,7 +1262,7 @@
 
-Matcher<Stmt>atomicExprMatcher<AtomicExpr>... +Matcher<Stmt>atomicExprMatcher<AtomicExpr>...
Matches atomic builtins.
 Example matches __atomic_load_n(ptr, 1)
   void foo() { int *ptr; __atomic_load_n(ptr, 1); }
@@ -1279,7 +1289,7 @@
 
-Matcher<Stmt>binaryOperatorMatcher<BinaryOperator>... +Matcher<Stmt>binaryOperatorMatcher<BinaryOperator>...
Matches binary operator expressions.
 
 Example matches a || b
@@ -1359,7 +1369,7 @@
 
-Matcher<Stmt>chooseExprMatcher<ChooseExpr>... +Matcher<Stmt>chooseExprMatcher<ChooseExpr>...
Matches GNU __builtin_choose_expr.
 
@@ -1596,7 +1606,7 @@ -Matcher<Stmt>cxxNullPtrLiteralExprMatcher<CXXNullPtrLiteralExpr>... +Matcher<Stmt>cxxNullPtrLiteralExprMatcher<CXXNullPtrLiteralExpr>...
Matches nullptr literal.
 
@@ -1839,12 +1849,12 @@ -Matcher<Stmt>genericSelectionExprMatcher<GenericSelectionExpr>... +Matcher<Stmt>genericSelectionExprMatcher<GenericSelectionExpr>...
Matches C11 _Generic expression.
 
-Matcher<Stmt>gnuNullExprMatcher<GNUNullExpr>... +Matcher<Stmt>gnuNullExprMatcher<GNUNullExpr>...
Matches GNU __null expression.
 
@@ -1969,7 +1979,7 @@ -Matcher<Stmt>objcCatchStmtMatcher<ObjCAtCatchStmt>... +Matcher<Stmt>objcCatchStmtMatcher<ObjCAtCatchStmt>...
Matches Objective-C @catch statements.
 
 Example matches @catch
@@ -2011,14 +2021,14 @@
 
-Matcher<Stmt>objcThrowStmtMatcher<ObjCAtThrowStmt>... +Matcher<Stmt>objcThrowStmtMatcher<ObjCAtThrowStmt>...
Matches Objective-C statements.
 
 Example matches @throw obj;
 
-Matcher<Stmt>objcTryStmtMatcher<ObjCAtTryStmt>... +Matcher<Stmt>objcTryStmtMatcher<ObjCAtTryStmt>...
Matches Objective-C @try statements.
 
 Example matches @try
@@ -2105,7 +2115,7 @@
 
-Matcher<Stmt>stmtExprMatcher<StmtExpr>... +Matcher<Stmt>stmtExprMatcher<StmtExpr>...
Matches statement expression (GNU extension).
 
 Example match: ({ int X = 4; X; })
@@ -2252,6 +2262,59 @@
 
+Matcher<TypeLoc>elaboratedTypeLocMatcher<ElaboratedTypeLoc>... +
Matches elaborated `TypeLoc`s.
+
+Given
+  class C {};
+  class C c;
+elaboratedTypeLoc()
+  matches `class C`.
+
+ + +Matcher<TypeLoc>pointerTypeLocMatcher<PointerTypeLoc>... +
Matches pointer `TypeLoc`s.
+
+Given
+  int* x;
+pointerTypeLoc()
+  matches `int*`.
+
+ + +Matcher<TypeLoc>qualifiedTypeLocMatcher<QualifiedTypeLoc>... +
Matches `QualifiedTypeLoc`s in the clang AST.
+
+Given
+  const int x = 0;
+qualifiedTypeLoc()
+  matches `const int`.
+
+ + +Matcher<TypeLoc>referenceTypeLocMatcher<ReferenceTypeLoc>... +
Matches reference `TypeLoc`s.
+
+Given
+  int x = 3;
+  int& xx = x;
+referenceTypeLoc()
+  matches `int&`.
+
+ + +Matcher<TypeLoc>templateSpecializationTypeLocMatcher<TemplateSpecializationTypeLoc>... +
Matches template specialization `TypeLoc`s.
+
+Given
+  template <typename T> class C {};
+  C<char> var;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(typeLoc())))
+  matches `C<char> var`.
+
+ + Matcher<TypeLoc>typeLocMatcher<TypeLoc>...
Matches TypeLocs in the clang AST.
 
@@ -2768,7 +2831,7 @@ -Matcher<BinaryOperator>hasAnyOperatorNameStringRef, ..., StringRef +Matcher<BinaryOperator>hasAnyOperatorNameStringRef, ..., StringRef
Matches operator expressions (binary or unary) that have any of the
 specified names.
 
@@ -2778,7 +2841,7 @@
 
-Matcher<BinaryOperator>hasOperatorNamestd::string Name +Matcher<BinaryOperator>hasOperatorNamestd::string Name
Matches the operator Name of operator expressions (binary or
 unary).
 
@@ -2787,7 +2850,7 @@
 
-Matcher<BinaryOperator>isAssignmentOperator +Matcher<BinaryOperator>isAssignmentOperator
Matches all kinds of assignment operators.
 
 Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
@@ -2801,7 +2864,7 @@
 
-Matcher<BinaryOperator>isComparisonOperator +Matcher<BinaryOperator>isComparisonOperator
Matches comparison operators.
 
 Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator()))
@@ -3031,6 +3094,10 @@
 
+Matcher<CXXConstructorDecl>isInheritingConstructor +

+
+
 Matcher<CXXConstructorDecl>isMoveConstructor
 
Matches constructor declarations that are move constructors.
 
@@ -3779,7 +3846,7 @@
 Matcher<Decl>isExpandedFromMacrostd::string MacroName
 
Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
@@ -3936,6 +4003,21 @@
+Matcher<ElaboratedTypeLoc>hasNamedTypeLocTypeLocMatcher InnerMatcher +
Matches elaborated `TypeLoc`s that have a named `TypeLoc` matching
+`InnerMatcher`.
+
+Given
+  template <typename T>
+  class C {};
+  class C<int> c;
+varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
+  templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+  templateArgumentLoc()))))))
+  matches `class C<int> c`.
+
+ + Matcher<EnumDecl>isScoped
Matches C++11 scoped enum declaration.
 
@@ -4110,6 +4192,17 @@
 
+Matcher<FunctionDecl>hasReturnTypeLocTypeLocMatcher ReturnMatcher +
Matches a function declared with the specified return `TypeLoc`.
+
+Given
+  int f() { return 5; }
+  void g() {}
+functionDecl(hasReturnTypeLoc(loc(asString("int"))))
+  matches the declaration of `f`, but not `g`.
+
+ + Matcher<FunctionDecl>hasTrailingReturn
Matches a function declared with a trailing return type.
 
@@ -4165,7 +4258,7 @@
   @end
 
 Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
-  Matcher<ObjCMethodDecl>
+  Matcher<ObjCMethodDecl>
 
@@ -4563,7 +4656,7 @@ -Matcher<OMPDefaultClause>isFirstPrivateKind +Matcher<OMPDefaultClause>isFirstPrivateKind
Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
 specified.
 
@@ -4579,7 +4672,7 @@
 
-Matcher<OMPDefaultClause>isNoneKind +Matcher<OMPDefaultClause>isNoneKind
Matches if the OpenMP ``default`` clause has ``none`` kind specified.
 
 Given
@@ -4593,7 +4686,7 @@
 
-Matcher<OMPDefaultClause>isSharedKind +Matcher<OMPDefaultClause>isSharedKind
Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
 
 Given
@@ -4772,7 +4865,7 @@
 
-Matcher<ObjCMethodDecl>isClassMethod +Matcher<ObjCMethodDecl>isClassMethod
Returns true when the Objective-C method declaration is a class method.
 
 Example
@@ -4784,7 +4877,7 @@
 
-Matcher<ObjCMethodDecl>isDefinition +Matcher<ObjCMethodDecl>isDefinition
Matches if a declaration has a body attached.
 
 Example matches A, va, fa
@@ -4802,11 +4895,11 @@
   @end
 
 Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
-  Matcher<ObjCMethodDecl>
+  Matcher<ObjCMethodDecl>
 
-Matcher<ObjCMethodDecl>isInstanceMethod +Matcher<ObjCMethodDecl>isInstanceMethod
Returns true when the Objective-C method declaration is an instance method.
 
 Example
@@ -4856,6 +4949,17 @@
 
+Matcher<PointerTypeLoc>hasPointeeLocTypeLocMatcher PointeeMatcher +
Matches pointer `TypeLoc`s that have a pointee `TypeLoc` matching
+`PointeeMatcher`.
+
+Given
+  int* x;
+pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))
+  matches `int*`.
+
+ + Matcher<QualType>asStringstd::string Name
Matches if the matched type is represented by the given string.
 
@@ -5005,6 +5109,29 @@
 
+Matcher<QualifiedTypeLoc>hasUnqualifiedLocTypeLocMatcher InnerMatcher +
Matches `QualifiedTypeLoc`s that have an unqualified `TypeLoc` matching
+`InnerMatcher`.
+
+Given
+  int* x = 0;
+qualifiedTypeLoc(hasUnqualifiedLoc(typeLoc()))
+  matches `int*`.
+
+ + +Matcher<ReferenceTypeLoc>hasReferentLocTypeLocMatcher ReferentMatcher +
Matches reference `TypeLoc`s that have a referent `TypeLoc` matching
+`ReferentMatcher`.
+
+Given
+  int x = 3;
+  int& xx = x;
+referenceTypeLoc(hasReferentLoc(loc(asString("int"))))
+  matches `int&`.
+
+ + Matcher<Stmt>equalsBoundNodestd::string ID
Matches if a node equals a previously bound node.
 
@@ -5152,7 +5279,7 @@
   @end
 
 Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
-  Matcher<ObjCMethodDecl>
+  Matcher<ObjCMethodDecl>
 
@@ -5232,7 +5359,7 @@ Matcher<TypeLoc>isExpandedFromMacrostd::string MacroName
Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
@@ -5510,7 +5637,7 @@ @end Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>, - Matcher<ObjCMethodDecl> + Matcher<ObjCMethodDecl> @@ -6060,13 +6187,23 @@ -Matcher<BinaryOperator>hasEitherOperandMatcher<Expr> InnerMatcher +Matcher<BaseUsingDecl>hasAnyUsingShadowDeclMatcher<UsingShadowDecl> InnerMatcher +
Matches any using shadow declaration.
+
+Given
+  namespace X { void b(); }
+  using X::b;
+usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
+  matches using X::b 
+ + +Matcher<BinaryOperator>hasEitherOperandMatcher<Expr> InnerMatcher
Matches if either the left hand side or the right hand side of a
 binary operator matches.
 
-Matcher<BinaryOperator>hasLHSMatcher<Expr> InnerMatcher +Matcher<BinaryOperator>hasLHSMatcher<Expr> InnerMatcher
Matches the left hand side of binary operator expressions.
 
 Example matches a (matcher = binaryOperator(hasLHS()))
@@ -6074,7 +6211,7 @@
 
-Matcher<BinaryOperator>hasOperandsMatcher<Expr> Matcher1, Matcher<Expr> Matcher2 +Matcher<BinaryOperator>hasOperandsMatcher<Expr> Matcher1, Matcher<Expr> Matcher2
Matches if both matchers match with opposite sides of the binary operator.
 
 Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
@@ -6086,7 +6223,7 @@
 
-Matcher<BinaryOperator>hasRHSMatcher<Expr> InnerMatcher +Matcher<BinaryOperator>hasRHSMatcher<Expr> InnerMatcher
Matches the right hand side of binary operator expressions.
 
 Example matches b (matcher = binaryOperator(hasRHS()))
@@ -6112,7 +6249,7 @@
 
-Matcher<BlockDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher +Matcher<BlockDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher
Matches any parameter of a function or an ObjC method declaration or a
 block.
 
@@ -6141,7 +6278,7 @@
 
-Matcher<BlockDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher +Matcher<BlockDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher
Matches the n'th parameter of a function or an ObjC method
 declaration or a block.
 
@@ -6161,7 +6298,7 @@
 
-Matcher<BlockDecl>hasTypeLocMatcher<TypeLoc> Inner +Matcher<BlockDecl>hasTypeLocMatcher<TypeLoc> Inner
Matches if the type location of a node matches the inner matcher.
 
 Examples:
@@ -6178,13 +6315,13 @@
 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
   matches Foo(1, 2)
 
-Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
+Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
   Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
   Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
-  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
+  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
 
@@ -6222,13 +6359,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -6450,13 +6587,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -6558,13 +6695,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -6755,13 +6892,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -6957,13 +7094,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7014,13 +7151,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7261,13 +7398,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7304,13 +7441,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7441,13 +7578,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -7463,7 +7600,7 @@ } } -cxxRecordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the +cxxRcordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the declaration of class D. @@ -7622,13 +7759,13 @@ cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) matches Foo(1, 2) -Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, +Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>, Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, Matcher<CXXUnresolvedConstructExpr>, Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, - Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, + Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, Matcher<TypedefNameDecl> @@ -8384,7 +8521,7 @@ -Matcher<OMPExecutableDirective>hasAnyClauseMatcher<OMPClause> InnerMatcher +Matcher<OMPExecutableDirective>hasAnyClauseMatcher<OMPClause> InnerMatcher
Matches any clause in an OpenMP directive.
 
 Given
@@ -8522,7 +8659,7 @@
 
-Matcher<ObjCMethodDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher +Matcher<ObjCMethodDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher
Matches any parameter of a function or an ObjC method declaration or a
 block.
 
@@ -8551,7 +8688,7 @@
 
-Matcher<ObjCMethodDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher +Matcher<ObjCMethodDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher
Matches the n'th parameter of a function or an ObjC method
 declaration or a block.
 
@@ -8571,7 +8708,7 @@
 
-Matcher<ObjCPropertyDecl>hasTypeLocMatcher<TypeLoc> Inner +Matcher<ObjCPropertyDecl>hasTypeLocMatcher<TypeLoc> Inner
Matches if the type location of a node matches the inner matcher.
 
 Examples:
@@ -8588,13 +8725,13 @@
 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
   matches Foo(1, 2)
 
-Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
+Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
   Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
   Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
-  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
+  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
 
@@ -8818,7 +8955,7 @@ -Matcher<StmtExpr>hasAnySubstatementMatcher<Stmt> InnerMatcher +Matcher<StmtExpr>hasAnySubstatementMatcher<Stmt> InnerMatcher
Matches compound statements where at least one substatement matches
 a given matcher. Also matches StmtExprs that have CompoundStmt as children.
 
@@ -8999,13 +9136,13 @@
 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
   matches Foo(1, 2)
 
-Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
+Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
   Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
   Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
-  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
+  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
 
@@ -9077,6 +9214,19 @@ +Matcher<TemplateSpecializationTypeLoc>hasAnyTemplateArgumentLocMatcher<TemplateArgumentLoc> InnerMatcher +
Matches template specialization `TypeLoc`s that have at least one
+`TemplateArgumentLoc` matching the given `InnerMatcher`.
+
+Given
+  template<typename T> class A {};
+  A<int> a;
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+  hasTypeLoc(loc(asString("int")))))))
+  matches `A<int> a`.
+
+ + Matcher<TemplateSpecializationType>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher
Matches classTemplateSpecializations, templateSpecializationType and
 functionDecl that have at least one TemplateArgument matching the given
@@ -9210,13 +9360,13 @@
 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
   matches Foo(1, 2)
 
-Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
+Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
   Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
   Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>,
   Matcher<CXXUnresolvedConstructExpr>,
   Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>,
   Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>,
-  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
+  Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>,
   Matcher<TypedefNameDecl>
 
@@ -9356,16 +9506,6 @@ -Matcher<UsingDecl>hasAnyUsingShadowDeclMatcher<UsingShadowDecl> InnerMatcher -
Matches any using shadow declaration.
-
-Given
-  namespace X { void b(); }
-  using X::b;
-usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
-  matches using X::b 
- - Matcher<UsingShadowDecl>hasTargetDeclMatcher<NamedDecl> InnerMatcher
Matches a using shadow declaration where the target declaration is
 matched by the given matcher.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -6339,6 +6339,203 @@
       new internal::TypeLocTypeMatcher(InnerMatcher));
 }
 
+/// Matches `QualifiedTypeLoc`s in the clang AST.
+///
+/// Given
+/// \code
+///   const int x = 0;
+/// \endcode
+/// qualifiedTypeLoc()
+///   matches `const int`.
+extern const internal::VariadicDynCastAllOfMatcher
+    qualifiedTypeLoc;
+
+/// Matches `QualifiedTypeLoc`s that have an unqualified `TypeLoc` matching
+/// `InnerMatcher`.
+///
+/// Given
+/// \code
+///   int* const x;
+///   const int y;
+/// \endcode
+/// qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))
+///   matches the `TypeLoc` of the variable declaration of `x`, but not `y`.
+AST_MATCHER_P(QualifiedTypeLoc, hasUnqualifiedLoc, TypeLocMatcher,
+              InnerMatcher) {
+  return InnerMatcher.matches(Node.getUnqualifiedLoc(), Finder, Builder);
+}
+
+/// Matches a function declared with the specified return `TypeLoc`.
+///
+/// Given
+/// \code
+///   int f() { return 5; }
+///   void g() {}
+/// \endcode
+/// functionDecl(hasReturnTypeLoc(loc(asString("int"))))
+///   matches the declaration of `f`, but not `g`.
+AST_MATCHER_P(FunctionDecl, hasReturnTypeLoc, TypeLocMatcher, ReturnMatcher) {
+  auto Loc = Node.getFunctionTypeLoc();
+  return Loc && ReturnMatcher.matches(Loc.getReturnLoc(), Finder, Builder);
+}
+
+/// Matches pointer `TypeLoc`s.
+///
+/// Given
+/// \code
+///   int* x;
+/// \endcode
+/// pointerTypeLoc()
+///   matches `int*`.
+extern const internal::VariadicDynCastAllOfMatcher
+    pointerTypeLoc;
+
+/// Matches pointer `TypeLoc`s that have a pointee `TypeLoc` matching
+/// `PointeeMatcher`.
+///
+/// Given
+/// \code
+///   int* x;
+/// \endcode
+/// pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))
+///   matches `int*`.
+AST_MATCHER_P(PointerTypeLoc, hasPointeeLoc, TypeLocMatcher, PointeeMatcher) {
+  return PointeeMatcher.matches(Node.getPointeeLoc(), Finder, Builder);
+}
+
+/// Matches reference `TypeLoc`s.
+///
+/// Given
+/// \code
+///   int x = 3;
+///   int& xx = x;
+/// \endcode
+/// referenceTypeLoc()
+///   matches `int&`.
+extern const internal::VariadicDynCastAllOfMatcher
+    referenceTypeLoc;
+
+/// Matches reference `TypeLoc`s that have a referent `TypeLoc` matching
+/// `ReferentMatcher`.
+///
+/// Given
+/// \code
+///   int x = 3;
+///   int& xx = x;
+/// \endcode
+/// referenceTypeLoc(hasReferentLoc(loc(asString("int"))))
+///   matches `int&`.
+AST_MATCHER_P(ReferenceTypeLoc, hasReferentLoc, TypeLocMatcher,
+              ReferentMatcher) {
+  return ReferentMatcher.matches(Node.getPointeeLoc(), Finder, Builder);
+}
+
+/// Matches template specialization `TypeLoc`s.
+///
+/// Given
+/// \code
+///   template  class C {};
+///   C var;
+/// \endcode
+/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(typeLoc())))
+///   matches `C var`.
+extern const internal::VariadicDynCastAllOfMatcher<
+    TypeLoc, TemplateSpecializationTypeLoc>
+    templateSpecializationTypeLoc;
+
+/// Matches template specialization `TypeLoc`s that have at least one
+/// `TemplateArgumentLoc` matching the given `InnerMatcher`.
+///
+/// Given
+/// \code
+///   template class A {};
+///   A a;
+/// \endcode
+/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+///   hasTypeLoc(loc(asString("int")))))))
+///   matches `A a`.
+AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
+              internal::Matcher, InnerMatcher) {
+  for (unsigned Index = 0, N = Node.getNumArgs(); Index < N; ++Index) {
+    clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
+    if (InnerMatcher.matches(Node.getArgLoc(Index), Finder, &Result)) {
+      *Builder = std::move(Result);
+      return true;
+    }
+  }
+  return false;
+}
+
+inline bool
+MatchTemplateArgLocAt(const DeclRefExpr &Node, unsigned int Index,
+                      internal::Matcher InnerMatcher,
+                      internal::ASTMatchFinder *Finder,
+                      internal::BoundNodesTreeBuilder *Builder) {
+  llvm::ArrayRef ArgLocs = Node.template_arguments();
+  return Index < ArgLocs.size() &&
+         InnerMatcher.matches(ArgLocs[Index], Finder, Builder);
+}
+
+inline bool
+MatchTemplateArgLocAt(const TemplateSpecializationTypeLoc &Node,
+                      unsigned int Index,
+                      internal::Matcher InnerMatcher,
+                      internal::ASTMatchFinder *Finder,
+                      internal::BoundNodesTreeBuilder *Builder) {
+  return !Node.isNull() && Index < Node.getNumArgs() &&
+         InnerMatcher.matches(Node.getArgLoc(Index), Finder, Builder);
+}
+
+/// Matches template specialization `TypeLoc`s where the n'th
+/// `TemplateArgumentLoc` matches the given `InnerMatcher`.
+///
+/// Given
+/// \code
+///   template class A {};
+///   A b;
+///   A c;
+/// \endcode
+/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+///   hasTypeLoc(loc(asString("double")))))))
+///   matches `A b`, but not `A c`.
+AST_POLYMORPHIC_MATCHER_P2(
+    hasTemplateArgumentLoc,
+    AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, TemplateSpecializationTypeLoc),
+    unsigned int, Index, internal::Matcher, InnerMatcher) {
+  return MatchTemplateArgLocAt(Node, Index, InnerMatcher, Finder, Builder);
+}
+
+/// Matches elaborated `TypeLoc`s.
+///
+/// Given
+/// \code
+///   class C {};
+///   class C c;
+/// \endcode
+/// elaboratedTypeLoc()
+///   matches `class C`.
+extern const internal::VariadicDynCastAllOfMatcher
+    elaboratedTypeLoc;
+
+/// Matches elaborated `TypeLoc`s that have a named `TypeLoc` matching
+/// `InnerMatcher`.
+///
+/// Given
+/// \code
+///   template 
+///   class C {};
+///   class C c;
+///
+///   class D {};
+///   class D d;
+/// \endcode
+/// elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()));
+///   matches the `TypeLoc` of the variable declaration of `c`, but not `d`.
+AST_MATCHER_P(ElaboratedTypeLoc, hasNamedTypeLoc, TypeLocMatcher,
+              InnerMatcher) {
+  return InnerMatcher.matches(Node.getNamedTypeLoc(), Finder, Builder);
+}
+
 /// Matches type \c bool.
 ///
 /// Given
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -771,6 +771,19 @@
 const internal::VariadicAllOfMatcher qualType;
 const internal::VariadicAllOfMatcher type;
 const internal::VariadicAllOfMatcher typeLoc;
+
+const internal::VariadicDynCastAllOfMatcher
+    qualifiedTypeLoc;
+const internal::VariadicDynCastAllOfMatcher
+    pointerTypeLoc;
+const internal::VariadicDynCastAllOfMatcher
+    referenceTypeLoc;
+const internal::VariadicDynCastAllOfMatcher
+    templateSpecializationTypeLoc;
+const internal::VariadicDynCastAllOfMatcher
+    elaboratedTypeLoc;
+
 const internal::VariadicDynCastAllOfMatcher
     unaryExprOrTypeTraitExpr;
 const internal::VariadicDynCastAllOfMatcher valueDecl;
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -226,6 +226,7 @@
   REGISTER_MATCHER(doStmt);
   REGISTER_MATCHER(eachOf);
   REGISTER_MATCHER(elaboratedType);
+  REGISTER_MATCHER(elaboratedTypeLoc);
   REGISTER_MATCHER(enumConstantDecl);
   REGISTER_MATCHER(enumDecl);
   REGISTER_MATCHER(enumType);
@@ -274,6 +275,7 @@
   REGISTER_MATCHER(hasAnySelector);
   REGISTER_MATCHER(hasAnySubstatement);
   REGISTER_MATCHER(hasAnyTemplateArgument);
+  REGISTER_MATCHER(hasAnyTemplateArgumentLoc);
   REGISTER_MATCHER(hasAnyUsingShadowDecl);
   REGISTER_MATCHER(hasArgument);
   REGISTER_MATCHER(hasArgumentOfType);
@@ -322,6 +324,7 @@
   REGISTER_MATCHER(hasMemberName);
   REGISTER_MATCHER(hasMethod);
   REGISTER_MATCHER(hasName);
+  REGISTER_MATCHER(hasNamedTypeLoc);
   REGISTER_MATCHER(hasNullSelector);
   REGISTER_MATCHER(hasObjectExpression);
   REGISTER_MATCHER(hasOperands);
@@ -329,12 +332,15 @@
   REGISTER_MATCHER(hasOverloadedOperatorName);
   REGISTER_MATCHER(hasParameter);
   REGISTER_MATCHER(hasParent);
+  REGISTER_MATCHER(hasPointeeLoc);
   REGISTER_MATCHER(hasQualifier);
   REGISTER_MATCHER(hasRHS);
   REGISTER_MATCHER(hasRangeInit);
   REGISTER_MATCHER(hasReceiver);
   REGISTER_MATCHER(hasReceiverType);
+  REGISTER_MATCHER(hasReferentLoc);
   REGISTER_MATCHER(hasReplacementType);
+  REGISTER_MATCHER(hasReturnTypeLoc);
   REGISTER_MATCHER(hasReturnValue);
   REGISTER_MATCHER(hasPlacementArg);
   REGISTER_MATCHER(hasSelector);
@@ -348,6 +354,7 @@
   REGISTER_MATCHER(hasSyntacticForm);
   REGISTER_MATCHER(hasTargetDecl);
   REGISTER_MATCHER(hasTemplateArgument);
+  REGISTER_MATCHER(hasTemplateArgumentLoc);
   REGISTER_MATCHER(hasThen);
   REGISTER_MATCHER(hasThreadStorageDuration);
   REGISTER_MATCHER(hasTrailingReturn);
@@ -358,6 +365,7 @@
   REGISTER_MATCHER(hasUnderlyingDecl);
   REGISTER_MATCHER(hasUnderlyingType);
   REGISTER_MATCHER(hasUnqualifiedDesugaredType);
+  REGISTER_MATCHER(hasUnqualifiedLoc);
   REGISTER_MATCHER(hasValueType);
   REGISTER_MATCHER(ifStmt);
   REGISTER_MATCHER(ignoringElidableConstructorCall);
@@ -504,13 +512,16 @@
   REGISTER_MATCHER(parmVarDecl);
   REGISTER_MATCHER(pointee);
   REGISTER_MATCHER(pointerType);
+  REGISTER_MATCHER(pointerTypeLoc);
   REGISTER_MATCHER(predefinedExpr);
   REGISTER_MATCHER(qualType);
+  REGISTER_MATCHER(qualifiedTypeLoc);
   REGISTER_MATCHER(rValueReferenceType);
   REGISTER_MATCHER(realFloatingPointType);
   REGISTER_MATCHER(recordDecl);
   REGISTER_MATCHER(recordType);
   REGISTER_MATCHER(referenceType);
+  REGISTER_MATCHER(referenceTypeLoc);
   REGISTER_MATCHER(refersToDeclaration);
   REGISTER_MATCHER(refersToIntegralType);
   REGISTER_MATCHER(refersToTemplate);
@@ -538,6 +549,7 @@
   REGISTER_MATCHER(templateArgumentLoc);
   REGISTER_MATCHER(templateName);
   REGISTER_MATCHER(templateSpecializationType);
+  REGISTER_MATCHER(templateSpecializationTypeLoc);
   REGISTER_MATCHER(templateTemplateParmDecl);
   REGISTER_MATCHER(templateTypeParmDecl);
   REGISTER_MATCHER(templateTypeParmType);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2078,6 +2078,168 @@
       notMatches(Code, typeAliasTemplateDecl(hasName("typeAliasDecl"))));
 }
 
+TEST_P(ASTMatchersTest, QualifiedTypeLocTest_BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches("const int x = 0;",
+                      qualifiedTypeLoc(loc(asString("const int")))));
+}
+
+TEST_P(ASTMatchersTest, QualifiedTypeLocTest_BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(matches("const int f() { return 5; }",
+                      qualifiedTypeLoc(loc(asString("const int")))));
+}
+
+TEST_P(ASTMatchersTest, QualifiedTypeLocTest_DoesNotBindToUnqualifiedVarDecl) {
+  EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(loc(asString("int")))));
+}
+
+TEST_P(ASTMatchersTest, QualifiedTypeLocTest_IntDoesNotBindToConstIntDecl) {
+  EXPECT_TRUE(
+      notMatches("const int x = 0;", qualifiedTypeLoc(loc(asString("int")))));
+}
+
+TEST_P(ASTMatchersTest, QualifiedTypeLocTest_IntDoesNotBindToConstFloatDecl) {
+  EXPECT_TRUE(
+      notMatches("const float x = 0;", qualifiedTypeLoc(loc(asString("int")))));
+}
+
+TEST_P(ASTMatchersTest, PointerTypeLocTest_BindsToAnyPointerTypeLoc) {
+  auto matcher = varDecl(hasName("x"), hasTypeLoc(pointerTypeLoc()));
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST_P(ASTMatchersTest, PointerTypeLocTest_DoesNotBindToNonPointerTypeLoc) {
+  auto matcher = varDecl(hasName("x"), hasTypeLoc(pointerTypeLoc()));
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  EXPECT_TRUE(notMatches("char x;", matcher));
+}
+
+TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyReferenceTypeLoc) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  auto matcher = varDecl(hasName("r"), hasTypeLoc(referenceTypeLoc()));
+  EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher));
+  EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher));
+  EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher));
+  EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher));
+  EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher));
+}
+
+TEST_P(ASTMatchersTest, ReferenceTypeLocTest_DoesNotBindToNonReferenceTypeLoc) {
+  auto matcher = varDecl(hasName("r"), hasTypeLoc(referenceTypeLoc()));
+  EXPECT_TRUE(notMatches("int r;", matcher));
+  EXPECT_TRUE(notMatches("int r = 3;", matcher));
+  EXPECT_TRUE(notMatches("const int r = 3;", matcher));
+  EXPECT_TRUE(notMatches("int* r;", matcher));
+  EXPECT_TRUE(notMatches("float r;", matcher));
+  EXPECT_TRUE(notMatches("char r;", matcher));
+}
+
+TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyRvalueReferenceTypeLoc) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  auto matcher = varDecl(hasName("r"), hasTypeLoc(referenceTypeLoc()));
+  EXPECT_TRUE(matches("int&& r = 3;", matcher));
+  EXPECT_TRUE(matches("auto&& r = 3;", matcher));
+  EXPECT_TRUE(matches("float&& r = 3.0;", matcher));
+}
+
+TEST_P(
+    ASTMatchersTest,
+    TemplateSpecializationTypeLocTest_BindsToTemplateSpecializationExplicitInstantiation) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(
+      matches("template  class C {}; template class C;",
+              classTemplateSpecializationDecl(
+                  hasName("C"), hasTypeLoc(templateSpecializationTypeLoc()))));
+}
+
+TEST_P(ASTMatchersTest,
+       TemplateSpecializationTypeLocTest_BindsToVarDeclTemplateSpecialization) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(matches(
+      "template  class C {}; C var;",
+      varDecl(hasName("var"), hasTypeLoc(templateSpecializationTypeLoc()))));
+}
+
+TEST_P(
+    ASTMatchersTest,
+    TemplateSpecializationTypeLocTest_DoesNotBindToNonTemplateSpecialization) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(notMatches(
+      "class C {}; C var;",
+      varDecl(hasName("var"), hasTypeLoc(templateSpecializationTypeLoc()))));
+}
+
+TEST_P(ASTMatchersTest,
+       ElaboratedTypeLocTest_BindsToElaboratedObjectDeclaration) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(matches("class C {}; class C c;",
+                      varDecl(hasName("c"), hasTypeLoc(elaboratedTypeLoc()))));
+}
+
+TEST_P(ASTMatchersTest,
+       ElaboratedTypeLocTest_BindsToNamespaceElaboratedObjectDeclaration) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(matches("namespace N { class D {}; } N::D d;",
+                      varDecl(hasName("d"), hasTypeLoc(elaboratedTypeLoc()))));
+}
+
+TEST_P(ASTMatchersTest,
+       ElaboratedTypeLocTest_BindsToElaboratedStructDeclaration) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(matches("struct s {}; struct s ss;",
+                      varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc()))));
+}
+
+TEST_P(ASTMatchersTest,
+       ElaboratedTypeLocTest_DoesNotBindToNonElaboratedObjectDeclaration) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(
+      notMatches("class C {}; C c;",
+                 varDecl(hasName("c"), hasTypeLoc(elaboratedTypeLoc()))));
+}
+
+TEST_P(
+    ASTMatchersTest,
+    ElaboratedTypeLocTest_DoesNotBindToNamespaceNonElaboratedObjectDeclaration) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(
+      notMatches("namespace N { class D {}; } using N::D; D d;",
+                 varDecl(hasName("d"), hasTypeLoc(elaboratedTypeLoc()))));
+}
+
+TEST_P(ASTMatchersTest,
+       ElaboratedTypeLocTest_DoesNotBindToNonElaboratedStructDeclaration) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(
+      notMatches("struct s {}; s ss;",
+                 varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc()))));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything())));
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,425 @@
                          IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+                                              loc(asString("int"))))));
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches("volatile int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+                                                 loc(asString("int"))))));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntPointerVarDecl) {
+  EXPECT_TRUE(
+      matches("const volatile int* x = 0;",
+              qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"))))));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+      matches("const int f() { return 5; }",
+              qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"))))));
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches("const float x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+                                                loc(asString("float"))))));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+                                           loc(asString("float"))))));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+                                                 loc(asString("float"))))));
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+      "int f() { return 5; }",
+      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+      "float f() { return 5.0; }",
+      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+      "void f() {}",
+      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+      "int f() { return 5; }",
+      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+      "float f() { return 5.0; }",
+      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+                         hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+                         hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  EXPECT_TRUE(notMatches("char x;", matcher));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {
+  EXPECT_TRUE(
+      matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {
+  EXPECT_TRUE(matches("int** x;",
+                      pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {
+  EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
+                                      hasPointeeLoc(loc(asString("int"))))))));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {
+  EXPECT_TRUE(matches("float* x;",
+                      pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
+}
+
+TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {
+  EXPECT_TRUE(notMatches("float* x;",
+                         pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
+}
+
+TEST(HasPointeeLoc, FloatPointeeDoesNotBindToTypeLocPointingToInt) {
+  EXPECT_TRUE(notMatches(
+      "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
+}
+
+TEST(HasReferentLoc, BindsToAnyReferentTypeLoc) {
+  auto matcher = varDecl(
+      hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
+  EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher));
+  EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher));
+  EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher));
+  EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher));
+  EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher));
+}
+
+TEST(HasReferentLoc, DoesNotBindToTypeLocWithoutReferent) {
+  auto matcher = varDecl(
+      hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
+  EXPECT_TRUE(notMatches("int r;", matcher));
+  EXPECT_TRUE(notMatches("int r = 3;", matcher));
+  EXPECT_TRUE(notMatches("const int r = 3;", matcher));
+  EXPECT_TRUE(notMatches("int* r;", matcher));
+  EXPECT_TRUE(notMatches("float r;", matcher));
+  EXPECT_TRUE(notMatches("char r;", matcher));
+}
+
+TEST(HasReferentLoc, BindsToAnyRvalueReference) {
+  auto matcher = varDecl(
+      hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
+  EXPECT_TRUE(matches("int&& r = 3;", matcher));
+  EXPECT_TRUE(matches("auto&& r = 3;", matcher));
+  EXPECT_TRUE(matches("float&& r = 3.0;", matcher));
+}
+
+TEST(HasReferentLoc, BindsToIntReferenceTypeLoc) {
+  EXPECT_TRUE(matches("int rr = 3; int& r = rr;",
+                      referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
+}
+
+TEST(HasReferentLoc, BindsToIntRvalueReferenceTypeLoc) {
+  EXPECT_TRUE(matches("int&& r = 3;",
+                      referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
+}
+
+TEST(HasReferentLoc, BindsToFloatReferenceTypeLoc) {
+  EXPECT_TRUE(
+      matches("float rr = 3.0; float& r = rr;",
+              referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
+}
+
+TEST(HasReferentLoc, BindsToParameterWithIntReferenceTypeLoc) {
+  EXPECT_TRUE(matches(
+      "int f(int& r) { return r; }",
+      parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
+                                    hasReferentLoc(loc(asString("int"))))))));
+}
+
+TEST(HasReferentLoc, IntReferenceDoesNotBindToFloatReferenceTypeLoc) {
+  EXPECT_TRUE(
+      notMatches("float rr = 3.0; float& r = rr;",
+                 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
+}
+
+TEST(HasReferentLoc, FloatReferenceDoesNotBindToIntReferenceTypeLoc) {
+  EXPECT_TRUE(
+      notMatches("int rr = 3; int& r = rr;",
+                 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
+}
+
+TEST(HasReferentLoc, DoesNotBindToParameterWithoutIntReferenceTypeLoc) {
+  EXPECT_TRUE(notMatches(
+      "int f(int r) { return r; }",
+      parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
+                                    hasReferentLoc(loc(asString("int"))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
+  EXPECT_TRUE(
+      matches("template class A {}; A a;",
+              varDecl(hasName("a"), hasTypeLoc(templateSpecializationTypeLoc(
+                                        hasAnyTemplateArgumentLoc(hasTypeLoc(
+                                            loc(asString("int")))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
+  EXPECT_TRUE(
+      matches("template class A {}; A a;",
+              varDecl(hasName("a"), hasTypeLoc(templateSpecializationTypeLoc(
+                                        hasAnyTemplateArgumentLoc(hasTypeLoc(
+                                            loc(asString("double")))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
+  EXPECT_TRUE(matches(
+      "template class A {}; template<> class A {};",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(
+              hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc,
+     BindsToExplicitSpecializationWithDoubleArgument) {
+  EXPECT_TRUE(matches(
+      "template class A {}; template<> class A {};",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+              hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
+  auto code = R"(
+  template class A {};
+  template<> class A {};
+  )";
+  EXPECT_TRUE(
+      matches(code, classTemplateSpecializationDecl(
+                        hasName("A"), hasTypeLoc(templateSpecializationTypeLoc(
+                                          hasAnyTemplateArgumentLoc(hasTypeLoc(
+                                              loc(asString("double")))))))));
+  EXPECT_TRUE(matches(
+      code,
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(
+              hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
+  EXPECT_TRUE(notMatches(
+      "template class A {}; A a;",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+              hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasAnyTemplateArgumentLoc,
+     DoesNotBindToExplicitSpecializationWithIntArgument) {
+  EXPECT_TRUE(notMatches(
+      "template class A {}; template<> class A {};",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+              hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
+  EXPECT_TRUE(matches(
+      "template class A {}; A a;",
+      varDecl(hasName("a"),
+              hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                  0, hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
+  EXPECT_TRUE(matches(
+      "template class A {}; A a;",
+      varDecl(hasName("a"),
+              hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                  0, hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
+  EXPECT_TRUE(matches(
+      "template class A {}; template<> class A {};",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(
+              hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
+  EXPECT_TRUE(matches(
+      "template class A {}; template<> class A {};",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+              0, hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
+  auto code = R"(
+  template class A {};
+  template<> class A {};
+  )";
+  EXPECT_TRUE(matches(
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                    0, hasTypeLoc(loc(asString("double")))))))));
+  EXPECT_TRUE(matches(
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                    1, hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
+  EXPECT_TRUE(notMatches(
+      "template class A {}; A a;",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+              0, hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasTemplateArgumentLoc,
+     DoesNotBindToExplicitSpecializationWithIntArgument) {
+  EXPECT_TRUE(notMatches(
+      "template class A {}; template<> class A {};",
+      classTemplateSpecializationDecl(
+          hasName("A"),
+          hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+              0, hasTypeLoc(loc(asString("double")))))))));
+}
+
+TEST(HasTemplateArgumentLoc,
+     DoesNotBindToSpecializationWithMisplacedArguments) {
+  auto code = R"(
+  template class A {};
+  template<> class A {};
+  )";
+  EXPECT_TRUE(notMatches(
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                    1, hasTypeLoc(loc(asString("double")))))))));
+  EXPECT_TRUE(notMatches(
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                    0, hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
+  auto code = R"(
+  template class A {};
+  template<> class A {};
+  )";
+  EXPECT_TRUE(notMatches(
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                    -1, hasTypeLoc(loc(asString("double")))))))));
+  EXPECT_TRUE(notMatches(
+      code, classTemplateSpecializationDecl(
+                hasName("A"),
+                hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+                    100, hasTypeLoc(loc(asString("int")))))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {
+  EXPECT_TRUE(matches(R"(
+      template T f(T t) { return t; }
+      int g() { int i = f(3); return i; }
+      )",
+                      declRefExpr(to(functionDecl(hasName("f"))),
+                                  hasTemplateArgumentLoc(
+                                      0, hasTypeLoc(loc(asString("int")))))));
+}
+
+TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithDoubleArgument) {
+  EXPECT_TRUE(matches(
+      R"(
+      template T f(T t) { return t; }
+      double g() { double i = f(3.0); return i; }
+      )",
+      declRefExpr(
+          to(functionDecl(hasName("f"))),
+          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
+}
+
+TEST(HasTemplateArgumentLoc, DoesNotBindToDeclRefExprWithDoubleArgument) {
+  EXPECT_TRUE(notMatches(
+      R"(
+      template T f(T t) { return t; }
+      double g() { double i = f(3.0); return i; }
+      )",
+      declRefExpr(
+          to(functionDecl(hasName("f"))),
+          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
+}
+
+TEST(HasNamedTypeLoc, BindsToElaboratedObjectDeclaration) {
+  EXPECT_TRUE(matches(
+      R"(
+      template 
+      class C {};
+      class C c;
+      )",
+      varDecl(hasName("c"),
+              hasTypeLoc(elaboratedTypeLoc(
+                  hasNamedTypeLoc(templateSpecializationTypeLoc(
+                      hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
+}
+
+TEST(HasNamedTypeLoc, DoesNotBindToNonElaboratedObjectDeclaration) {
+  EXPECT_TRUE(notMatches(
+      R"(
+      template 
+      class C {};
+      C c;
+      )",
+      varDecl(hasName("c"),
+              hasTypeLoc(elaboratedTypeLoc(
+                  hasNamedTypeLoc(templateSpecializationTypeLoc(
+                      hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
+}
+
 } // namespace ast_matchers
 } // namespace clang