brintos

brintos / llvm-project-archived public Read only

0
0
Text · 241.3 KiB · c0a03de Raw
6702 lines · cpp
1//= unittests/ASTMatchers/ASTMatchersTraversalTest.cpp - matchers unit tests =//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ASTMatchersTest.h"10#include "clang/AST/Attrs.inc"11#include "clang/AST/DeclCXX.h"12#include "clang/AST/PrettyPrinter.h"13#include "clang/ASTMatchers/ASTMatchFinder.h"14#include "clang/ASTMatchers/ASTMatchers.h"15#include "clang/Tooling/Tooling.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/TargetParser/Host.h"18#include "llvm/TargetParser/Triple.h"19#include "gtest/gtest.h"20 21namespace clang {22namespace ast_matchers {23 24TEST(DeclarationMatcher, hasMethod) {25  EXPECT_TRUE(matches("class A { void func(); };",26                      cxxRecordDecl(hasMethod(hasName("func")))));27  EXPECT_TRUE(notMatches("class A { void func(); };",28                         cxxRecordDecl(hasMethod(isPublic()))));29}30 31TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {32  EXPECT_TRUE(matches(33    "template <typename T> struct A {"34      "  template <typename T2> struct F {};"35      "};"36      "template <typename T> struct B : A<T>::template F<T> {};"37      "B<int> b;",38    cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));39}40 41TEST(DeclarationMatcher, hasDeclContext) {42  EXPECT_TRUE(matches(43    "namespace N {"44      "  namespace M {"45      "    class D {};"46      "  }"47      "}",48    recordDecl(hasDeclContext(namespaceDecl(hasName("M"))))));49  EXPECT_TRUE(notMatches(50    "namespace N {"51      "  namespace M {"52      "    class D {};"53      "  }"54      "}",55    recordDecl(hasDeclContext(namespaceDecl(hasName("N"))))));56 57  EXPECT_TRUE(matches("namespace {"58                        "  namespace M {"59                        "    class D {};"60                        "  }"61                        "}",62                      recordDecl(hasDeclContext(namespaceDecl(63                        hasName("M"), hasDeclContext(namespaceDecl()))))));64 65  EXPECT_TRUE(matches("class D{};", decl(hasDeclContext(decl()))));66}67 68TEST(HasDescendant, MatchesDescendantTypes) {69  EXPECT_TRUE(matches("void f() { int i = 3; }",70                      decl(hasDescendant(loc(builtinType())))));71  EXPECT_TRUE(matches("void f() { int i = 3; }",72                      stmt(hasDescendant(builtinType()))));73 74  EXPECT_TRUE(matches("void f() { int i = 3; }",75                      stmt(hasDescendant(loc(builtinType())))));76  EXPECT_TRUE(matches("void f() { int i = 3; }",77                      stmt(hasDescendant(qualType(builtinType())))));78 79  EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }",80                         stmt(hasDescendant(isInteger()))));81 82  EXPECT_TRUE(matchAndVerifyResultTrue(83    "void f() { int a; float c; int d; int e; }",84    functionDecl(forEachDescendant(85      varDecl(hasDescendant(isInteger())).bind("x"))),86    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 3)));87}88 89TEST(HasDescendant, MatchesDescendantsOfTypes) {90  EXPECT_TRUE(matches("void f() { int*** i; }",91                      qualType(hasDescendant(builtinType()))));92  EXPECT_TRUE(matches("void f() { int*** i; }",93                      qualType(hasDescendant(94                        pointerType(pointee(builtinType()))))));95  EXPECT_TRUE(matches("void f() { int*** i; }",96                      typeLoc(hasDescendant(loc(builtinType())))));97 98  EXPECT_TRUE(matchAndVerifyResultTrue(99    "void f() { int*** i; }",100    qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))),101    std::make_unique<VerifyIdIsBoundTo<Type>>("x", 2)));102}103 104 105TEST(Has, MatchesChildrenOfTypes) {106  EXPECT_TRUE(matches("int i;",107                      varDecl(hasName("i"), has(isInteger()))));108  EXPECT_TRUE(notMatches("int** i;",109                         varDecl(hasName("i"), has(isInteger()))));110  EXPECT_TRUE(matchAndVerifyResultTrue(111    "int (*f)(float, int);",112    qualType(functionType(), forEach(qualType(isInteger()).bind("x"))),113    std::make_unique<VerifyIdIsBoundTo<QualType>>("x", 2)));114}115 116TEST(Has, MatchesChildTypes) {117  EXPECT_TRUE(matches(118    "int* i;",119    varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));120  EXPECT_TRUE(notMatches(121    "int* i;",122    varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));123}124 125TEST(StatementMatcher, Has) {126  StatementMatcher HasVariableI =127      expr(hasType(pointsTo(recordDecl(hasName("X")))),128           has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i")))))));129 130  EXPECT_TRUE(matches(131    "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));132  EXPECT_TRUE(notMatches(133    "class X; X *x(int); void c() { int i; x(42); }", HasVariableI));134}135 136TEST(StatementMatcher, HasDescendant) {137  StatementMatcher HasDescendantVariableI =138    expr(hasType(pointsTo(recordDecl(hasName("X")))),139         hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));140 141  EXPECT_TRUE(matches(142    "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",143    HasDescendantVariableI));144  EXPECT_TRUE(notMatches(145    "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",146    HasDescendantVariableI));147}148 149TEST(TypeMatcher, MatchesClassType) {150  TypeMatcher TypeA = hasDeclaration(recordDecl(hasName("A")));151 152  EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));153  EXPECT_TRUE(notMatches("class A {};", TypeA));154 155  TypeMatcher TypeDerivedFromA =156    hasDeclaration(cxxRecordDecl(isDerivedFrom("A")));157 158  EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",159                      TypeDerivedFromA));160  EXPECT_TRUE(notMatches("class A {};", TypeA));161 162  TypeMatcher TypeAHasClassB = hasDeclaration(163    recordDecl(hasName("A"), has(recordDecl(hasName("B")))));164 165  EXPECT_TRUE(166    matches("class A { public: A *a; class B {}; };", TypeAHasClassB));167 168  EXPECT_TRUE(matchesC("struct S {}; void f(void) { struct S s; }",169                       varDecl(hasType(namedDecl(hasName("S"))))));170}171 172TEST(TypeMatcher, MatchesDeclTypes) {173  // TypedefType -> TypedefNameDecl174  EXPECT_TRUE(matches("typedef int I; void f(I i);",175                      parmVarDecl(hasType(namedDecl(hasName("I"))))));176  // ObjCObjectPointerType177  EXPECT_TRUE(matchesObjC("@interface Foo @end void f(Foo *f);",178                          parmVarDecl(hasType(objcObjectPointerType()))));179  // ObjCObjectPointerType -> ObjCInterfaceType -> ObjCInterfaceDecl180  EXPECT_TRUE(matchesObjC(181    "@interface Foo @end void f(Foo *f);",182    parmVarDecl(hasType(pointsTo(objcInterfaceDecl(hasName("Foo")))))));183  // TemplateTypeParmType184  EXPECT_TRUE(matches("template <typename T> void f(T t);",185                      parmVarDecl(hasType(templateTypeParmType()))));186  // TemplateTypeParmType -> TemplateTypeParmDecl187  EXPECT_TRUE(matches("template <typename T> void f(T t);",188                      parmVarDecl(hasType(namedDecl(hasName("T"))))));189  // InjectedClassNameType190  EXPECT_TRUE(matches("template <typename T> struct S {"191                      "  void f(S s);"192                      "};",193                      parmVarDecl(hasType(injectedClassNameType()))));194  EXPECT_TRUE(notMatches("template <typename T> struct S {"195                         "  void g(S<T> s);"196                         "};",197                         parmVarDecl(hasType(injectedClassNameType()))));198  // InjectedClassNameType -> CXXRecordDecl199  EXPECT_TRUE(matches("template <typename T> struct S {"200                        "  void f(S s);"201                        "};",202                      parmVarDecl(hasType(namedDecl(hasName("S"))))));203 204  static const char Using[] = "template <typename T>"205    "struct Base {"206    "  typedef T Foo;"207    "};"208    ""209    "template <typename T>"210    "struct S : private Base<T> {"211    "  using typename Base<T>::Foo;"212    "  void f(Foo);"213    "};";214  // UnresolvedUsingTypenameDecl215  EXPECT_TRUE(matches(Using, unresolvedUsingTypenameDecl(hasName("Foo"))));216  // UnresolvedUsingTypenameType -> UnresolvedUsingTypenameDecl217  EXPECT_TRUE(matches(Using, parmVarDecl(hasType(namedDecl(hasName("Foo"))))));218}219 220TEST(HasDeclaration, HasDeclarationOfEnumType) {221  EXPECT_TRUE(matches("enum X {}; void y(X *x) { x; }",222                      expr(hasType(pointsTo(223                        qualType(hasDeclaration(enumDecl(hasName("X")))))))));224}225 226TEST(HasDeclaration, HasGetDeclTraitTest) {227  static_assert(internal::has_getDecl<TypedefType>,228                "Expected TypedefType to have a getDecl.");229  static_assert(!internal::has_getDecl<TemplateSpecializationType>,230                "Expected TemplateSpecializationType to *not* have a getDecl.");231}232 233TEST(HasDeclaration, ElaboratedType) {234  static const char Elaborated[] = "namespace n { struct X {}; }"235                                   "void f(n::X);";236  EXPECT_TRUE(237      matches(Elaborated,238              parmVarDecl(hasType(qualType(hasDeclaration(cxxRecordDecl()))))));239  EXPECT_TRUE(matches(Elaborated, parmVarDecl(hasType(recordType(240                                      hasDeclaration(cxxRecordDecl()))))));241}242 243TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) {244  EXPECT_TRUE(matches(245      "typedef int X; X a;",246      varDecl(hasName("a"), hasType(typedefType(hasDeclaration(decl()))))));247 248  // FIXME: Add tests for other types with getDecl() (e.g. RecordType)249}250 251TEST(HasDeclaration, HasDeclarationOfTemplateSpecializationType) {252  EXPECT_TRUE(matches("template <typename T> class A {}; A<int> a;",253                      varDecl(hasType(templateSpecializationType(254                          hasDeclaration(namedDecl(hasName("A"))))))));255  EXPECT_TRUE(matches("template <typename T> class A {};"256                      "template <typename T> class B { A<T> a; };",257                      fieldDecl(hasType(templateSpecializationType(258                          hasDeclaration(namedDecl(hasName("A"))))))));259  EXPECT_TRUE(matches("template <typename T> class A {}; A<int> a;",260                      varDecl(hasType(templateSpecializationType(261                          hasDeclaration(cxxRecordDecl()))))));262}263 264TEST(HasDeclaration, HasDeclarationOfCXXNewExpr) {265  EXPECT_TRUE(266      matches("int *A = new int();",267              cxxNewExpr(hasDeclaration(functionDecl(parameterCountIs(1))))));268}269 270TEST(HasDeclaration, HasDeclarationOfTypeAlias) {271  EXPECT_TRUE(matches("template <typename T> using C = T; C<int> c;",272                      varDecl(hasType(templateSpecializationType(273                          hasDeclaration(typeAliasTemplateDecl()))))));274}275 276TEST(HasDeclaration, HasDeclarationOfObjCInterface) {277  EXPECT_TRUE(matchesObjC("@interface BaseClass @end void f() {BaseClass* b;}",278                          varDecl(hasType(objcObjectPointerType(279                              pointee(hasDeclaration(objcInterfaceDecl())))))));280}281 282TEST(HasUnqualifiedDesugaredType, DesugarsUsing) {283  EXPECT_TRUE(284      matches("struct A {}; using B = A; B b;",285              varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));286  EXPECT_TRUE(287      matches("struct A {}; using B = A; using C = B; C b;",288              varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));289}290 291TEST(HasUnderlyingDecl, Matches) {292  EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }"293                      "template <class T> void g() { using N::f; f(T()); }",294                      unresolvedLookupExpr(hasAnyDeclaration(295                          namedDecl(hasUnderlyingDecl(hasName("::N::f")))))));296  EXPECT_TRUE(matches(297      "namespace N { template <class T> void f(T t); }"298      "template <class T> void g() { N::f(T()); }",299      unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));300  EXPECT_TRUE(notMatches(301      "namespace N { template <class T> void f(T t); }"302      "template <class T> void g() { using N::f; f(T()); }",303      unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));304}305 306TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {307  TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));308  EXPECT_TRUE(309    matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));310  EXPECT_TRUE(311    notMatches("class X {}; void y(X *x) { x; }",312               expr(hasType(ClassX))));313  EXPECT_TRUE(314    matches("class X {}; void y(X *x) { x; }",315            expr(hasType(pointsTo(ClassX)))));316}317 318TEST(HasType, TakesQualTypeMatcherAndMatchesValueDecl) {319  TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));320  EXPECT_TRUE(321    matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));322  EXPECT_TRUE(323    notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));324  EXPECT_TRUE(325    matches("class X {}; void y() { X *x; }",326            varDecl(hasType(pointsTo(ClassX)))));327}328 329TEST(HasType, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier) {330  TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));331  CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX));332  DeclarationMatcher ClassHasBaseClassX =333      cxxRecordDecl(hasDirectBase(BaseClassX));334  EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX));335  EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX));336}337 338TEST(HasType, TakesDeclMatcherAndMatchesExpr) {339  DeclarationMatcher ClassX = recordDecl(hasName("X"));340  EXPECT_TRUE(341    matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));342  EXPECT_TRUE(343    notMatches("class X {}; void y(X *x) { x; }",344               expr(hasType(ClassX))));345}346 347TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {348  DeclarationMatcher ClassX = recordDecl(hasName("X"));349  EXPECT_TRUE(350    matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));351  EXPECT_TRUE(352    notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));353}354 355TEST(HasType, TakesDeclMatcherAndMatchesCXXBaseSpecifier) {356  DeclarationMatcher ClassX = recordDecl(hasName("X"));357  CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX));358  DeclarationMatcher ClassHasBaseClassX =359      cxxRecordDecl(hasDirectBase(BaseClassX));360  EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX));361  EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX));362}363 364TEST(HasType, MatchesTypedefDecl) {365  EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));366  EXPECT_TRUE(matches("typedef const int T;",367                      typedefDecl(hasType(asString("const int")))));368  EXPECT_TRUE(notMatches("typedef const int T;",369                         typedefDecl(hasType(asString("int")))));370  EXPECT_TRUE(matches("typedef int foo; typedef foo bar;",371                      typedefDecl(hasType(asString("foo")), hasName("bar"))));372}373 374TEST(HasType, MatchesTypedefNameDecl) {375  EXPECT_TRUE(matches("using X = int;", typedefNameDecl(hasType(asString("int")))));376  EXPECT_TRUE(matches("using T = const int;",377                      typedefNameDecl(hasType(asString("const int")))));378  EXPECT_TRUE(notMatches("using T = const int;",379                         typedefNameDecl(hasType(asString("int")))));380  EXPECT_TRUE(matches("using foo = int; using bar = foo;",381                      typedefNameDecl(hasType(asString("foo")), hasName("bar"))));382}383 384TEST(HasTypeLoc, MatchesBlockDecl) {385  EXPECT_TRUE(matchesConditionally(386      "auto x = ^int (int a, int b) { return a + b; };",387      blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true,388      {"-fblocks"}));389}390 391TEST(HasTypeLoc, MatchesCXXBaseSpecifierAndCtorInitializer) {392  llvm::StringRef code = R"cpp(393  class Foo {};394  class Bar : public Foo {395    Bar() : Foo() {}396  };397  )cpp";398 399  EXPECT_TRUE(matches(400      code, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("Foo")))))));401  EXPECT_TRUE(402      matches(code, cxxCtorInitializer(hasTypeLoc(loc(asString("Foo"))))));403}404 405TEST(HasTypeLoc, MatchesCXXFunctionalCastExpr) {406  EXPECT_TRUE(matches("auto x = int(3);",407                      cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int"))))));408}409 410TEST(HasTypeLoc, MatchesCXXNewExpr) {411  EXPECT_TRUE(matches("auto* x = new int(3);",412                      cxxNewExpr(hasTypeLoc(loc(asString("int"))))));413  EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();",414                      cxxNewExpr(hasTypeLoc(loc(asString("Foo"))))));415}416 417TEST(HasTypeLoc, MatchesCXXTemporaryObjectExpr) {418  EXPECT_TRUE(419      matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",420              cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("Foo"))))));421}422 423TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) {424  EXPECT_TRUE(425      matches("template <typename T> T make() { return T(); }",426              cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));427}428 429TEST(HasTypeLoc, MatchesCompoundLiteralExpr) {430  EXPECT_TRUE(431      matches("int* x = (int[2]) { 0, 1 };",432              compoundLiteralExpr(hasTypeLoc(loc(asString("int[2]"))))));433}434 435TEST(HasTypeLoc, MatchesDeclaratorDecl) {436  EXPECT_TRUE(matches("int x;",437                      varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));438  EXPECT_TRUE(matches("int x(3);",439                      varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));440  EXPECT_TRUE(matches("struct Foo { Foo(int, int); }; Foo x(1, 2);",441                      varDecl(hasName("x"), hasTypeLoc(loc(asString("Foo"))))));442 443  // Make sure we don't crash on implicit constructors.444  EXPECT_TRUE(notMatches("class X {}; X x;",445                         declaratorDecl(hasTypeLoc(loc(asString("int"))))));446}447 448TEST(HasTypeLoc, MatchesExplicitCastExpr) {449  EXPECT_TRUE(matches("auto x = (int) 3;",450                      explicitCastExpr(hasTypeLoc(loc(asString("int"))))));451  EXPECT_TRUE(matches("auto x = static_cast<int>(3);",452                      explicitCastExpr(hasTypeLoc(loc(asString("int"))))));453}454 455TEST(HasTypeLoc, MatchesObjCPropertyDecl) {456  EXPECT_TRUE(matchesObjC(R"objc(457      @interface Foo458      @property int enabled;459      @end460    )objc",461                          objcPropertyDecl(hasTypeLoc(loc(asString("int"))))));462}463 464TEST(HasTypeLoc, MatchesTemplateArgumentLoc) {465  EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;",466                      templateArgumentLoc(hasTypeLoc(loc(asString("int"))))));467}468 469TEST(HasTypeLoc, MatchesTypedefNameDecl) {470  EXPECT_TRUE(matches("typedef int X;",471                      typedefNameDecl(hasTypeLoc(loc(asString("int"))))));472  EXPECT_TRUE(matches("using X = int;",473                      typedefNameDecl(hasTypeLoc(loc(asString("int"))))));474}475 476TEST(Callee, MatchesDeclarations) {477  StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x"))));478 479  EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));480  EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));481 482  CallMethodX = traverse(TK_AsIs, callExpr(callee(cxxConversionDecl())));483  EXPECT_TRUE(484    matches("struct Y { operator int() const; }; int i = Y();", CallMethodX));485  EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",486                         CallMethodX));487}488 489TEST(Callee, MatchesMemberExpressions) {490  EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",491                      callExpr(callee(memberExpr()))));492  EXPECT_TRUE(493    notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));494}495 496TEST(Matcher, Argument) {497  StatementMatcher CallArgumentY = callExpr(498    hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));499 500  EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY));501  EXPECT_TRUE(502    matches("class X { void x(int) { int y; x(y); } };", CallArgumentY));503  EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY));504 505  StatementMatcher WrongIndex = callExpr(506    hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));507  EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex));508}509 510TEST(Matcher, AnyArgument) {511  auto HasArgumentY = hasAnyArgument(512      ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));513  StatementMatcher CallArgumentY = callExpr(HasArgumentY);514  StatementMatcher CtorArgumentY = cxxConstructExpr(HasArgumentY);515  StatementMatcher UnresolvedCtorArgumentY =516      cxxUnresolvedConstructExpr(HasArgumentY);517  StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);518  EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));519  EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));520  EXPECT_TRUE(matches("struct Y { Y(int, int); };"521                      "void x() { int y; (void)Y(1, y); }",522                      CtorArgumentY));523  EXPECT_TRUE(matches("struct Y { Y(int, int); };"524                      "void x() { int y; (void)Y(y, 42); }",525                      CtorArgumentY));526  EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",527                      UnresolvedCtorArgumentY));528  EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",529                      UnresolvedCtorArgumentY));530  EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "531                          "void x(I* i) { int y; [i f:y]; }",532                          ObjCCallArgumentY));533  EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "534                           "void x(I* i) { int z; [i f:z]; }",535                           ObjCCallArgumentY));536  EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));537  EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"538                         "void x() { int y; (void)Y(1, 2); }",539                         CtorArgumentY));540  EXPECT_TRUE(notMatches("template <class Y>"541                         "void x() { int y; (void)Y(1, 2); }",542                         UnresolvedCtorArgumentY));543 544  StatementMatcher ImplicitCastedArgument =545      traverse(TK_AsIs, callExpr(hasAnyArgument(implicitCastExpr())));546  EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument));547}548 549TEST(Matcher, HasReceiver) {550  EXPECT_TRUE(matchesObjC(551      "@interface NSString @end "552      "void f(NSString *x) {"553      "[x containsString];"554      "}",555      objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));556 557  EXPECT_FALSE(matchesObjC(558      "@interface NSString +(NSString *) stringWithFormat; @end "559      "void f() { [NSString stringWithFormat]; }",560      objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));561}562 563TEST(Matcher, MatchesMethodsOnLambda) {564  StringRef Code = R"cpp(565struct A {566  ~A() {}567};568void foo()569{570  A a;571  auto l = [a] { };572  auto lCopy = l;573  auto lPtrDecay = +[] { };574  (void)lPtrDecay;575}576)cpp";577 578  EXPECT_TRUE(matches(579      Code, cxxConstructorDecl(580                hasBody(compoundStmt()),581                hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),582                isCopyConstructor())));583  EXPECT_TRUE(matches(584      Code, cxxConstructorDecl(585                hasBody(compoundStmt()),586                hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),587                isMoveConstructor())));588  EXPECT_TRUE(matches(589      Code, cxxDestructorDecl(590                hasBody(compoundStmt()),591                hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))))));592  EXPECT_TRUE(matches(593      Code, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt(594                                  hasReturnValue(implicitCastExpr()))))),595                              hasAncestor(lambdaExpr(hasAncestor(596                                  varDecl(hasName("lPtrDecay"))))))));597}598 599TEST(Matcher, MatchesCoroutine) {600  FileContentMappings M;601  M.push_back(std::make_pair("/coro_header", R"cpp(602namespace std {603 604template <class... Args>605struct void_t_imp {606  using type = void;607};608template <class... Args>609using void_t = typename void_t_imp<Args...>::type;610 611template <class T, class = void>612struct traits_sfinae_base {};613 614template <class T>615struct traits_sfinae_base<T, void_t<typename T::promise_type>> {616  using promise_type = typename T::promise_type;617};618 619template <class Ret, class... Args>620struct coroutine_traits : public traits_sfinae_base<Ret> {};621}  // namespace std622struct awaitable {623  bool await_ready() noexcept;624  template <typename F>625  void await_suspend(F) noexcept;626  void await_resume() noexcept;627} a;628struct promise {629  void get_return_object();630  awaitable initial_suspend();631  awaitable final_suspend() noexcept;632  awaitable yield_value(int); // expected-note 2{{candidate}}633  void return_value(int); // expected-note 2{{here}}634  void unhandled_exception();635};636template <typename... T>637struct std::coroutine_traits<void, T...> { using promise_type = promise; };638namespace std {639template <class PromiseType = void>640struct coroutine_handle {641  static coroutine_handle from_address(void *) noexcept;642};643} // namespace std644)cpp"));645  StringRef CoReturnCode = R"cpp(646#include <coro_header>647void check_match_co_return() {648  co_return 1;649}650)cpp";651  EXPECT_TRUE(matchesConditionally(CoReturnCode,652                                   coreturnStmt(isExpansionInMainFile()), true,653                                   {"-std=c++20", "-I/"}, M));654  StringRef CoAwaitCode = R"cpp(655#include <coro_header>656void check_match_co_await() {657  co_await a;658  co_return 1;659}660)cpp";661  EXPECT_TRUE(matchesConditionally(CoAwaitCode,662                                   coawaitExpr(isExpansionInMainFile()), true,663                                   {"-std=c++20", "-I/"}, M));664  StringRef CoYieldCode = R"cpp(665#include <coro_header>666void check_match_co_yield() {667  co_yield 1.0;668  co_return 1;669}670)cpp";671  EXPECT_TRUE(matchesConditionally(CoYieldCode,672                                   coyieldExpr(isExpansionInMainFile()), true,673                                   {"-std=c++20", "-I/"}, M));674 675  StringRef NonCoroCode = R"cpp(676#include <coro_header>677void non_coro_function() {678}679)cpp";680 681  EXPECT_TRUE(matchesConditionally(CoReturnCode, coroutineBodyStmt(), true,682                                   {"-std=c++20", "-I/"}, M));683  EXPECT_TRUE(matchesConditionally(CoAwaitCode, coroutineBodyStmt(), true,684                                   {"-std=c++20", "-I/"}, M));685  EXPECT_TRUE(matchesConditionally(CoYieldCode, coroutineBodyStmt(), true,686                                   {"-std=c++20", "-I/"}, M));687 688  EXPECT_FALSE(matchesConditionally(NonCoroCode, coroutineBodyStmt(), true,689                                    {"-std=c++20", "-I/"}, M));690 691  StringRef CoroWithDeclCode = R"cpp(692#include <coro_header>693void coro() {694  int thevar;695  co_return 1;696}697)cpp";698  EXPECT_TRUE(matchesConditionally(699      CoroWithDeclCode,700      coroutineBodyStmt(hasBody(compoundStmt(701          has(declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))),702      true, {"-std=c++20", "-I/"}, M));703 704  StringRef CoroWithTryCatchDeclCode = R"cpp(705#include <coro_header>706void coro() try {707  int thevar;708  co_return 1;709} catch (...) { co_return 1; }710)cpp";711  EXPECT_TRUE(matchesConditionally(712      CoroWithTryCatchDeclCode,713      coroutineBodyStmt(hasBody(compoundStmt(has(cxxTryStmt(has(compoundStmt(has(714          declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))))),715      true, {"-std=c++20", "-I/"}, M));716}717 718TEST(Matcher, isClassMessage) {719  EXPECT_TRUE(matchesObjC(720      "@interface NSString +(NSString *) stringWithFormat; @end "721      "void f() { [NSString stringWithFormat]; }",722      objcMessageExpr(isClassMessage())));723 724  EXPECT_FALSE(matchesObjC(725      "@interface NSString @end "726      "void f(NSString *x) {"727      "[x containsString];"728      "}",729      objcMessageExpr(isClassMessage())));730}731 732TEST(Matcher, isInstanceMessage) {733  EXPECT_TRUE(matchesObjC(734      "@interface NSString @end "735      "void f(NSString *x) {"736      "[x containsString];"737      "}",738      objcMessageExpr(isInstanceMessage())));739 740  EXPECT_FALSE(matchesObjC(741      "@interface NSString +(NSString *) stringWithFormat; @end "742      "void f() { [NSString stringWithFormat]; }",743      objcMessageExpr(isInstanceMessage())));744 745}746 747TEST(Matcher, isClassMethod) {748  EXPECT_TRUE(matchesObjC(749    "@interface Bar + (void)bar; @end",750    objcMethodDecl(isClassMethod())));751 752  EXPECT_TRUE(matchesObjC(753    "@interface Bar @end"754    "@implementation Bar + (void)bar {} @end",755    objcMethodDecl(isClassMethod())));756 757  EXPECT_FALSE(matchesObjC(758    "@interface Foo - (void)foo; @end",759    objcMethodDecl(isClassMethod())));760 761  EXPECT_FALSE(matchesObjC(762    "@interface Foo @end "763    "@implementation Foo - (void)foo {} @end",764    objcMethodDecl(isClassMethod())));765}766 767TEST(Matcher, isInstanceMethod) {768  EXPECT_TRUE(matchesObjC(769    "@interface Foo - (void)foo; @end",770    objcMethodDecl(isInstanceMethod())));771 772  EXPECT_TRUE(matchesObjC(773    "@interface Foo @end "774    "@implementation Foo - (void)foo {} @end",775    objcMethodDecl(isInstanceMethod())));776 777  EXPECT_FALSE(matchesObjC(778    "@interface Bar + (void)bar; @end",779    objcMethodDecl(isInstanceMethod())));780 781  EXPECT_FALSE(matchesObjC(782    "@interface Bar @end"783    "@implementation Bar + (void)bar {} @end",784    objcMethodDecl(isInstanceMethod())));785}786 787TEST(MatcherCXXMemberCallExpr, On) {788  StringRef Snippet1 = R"cc(789        struct Y {790          void m();791        };792        void z(Y y) { y.m(); }793      )cc";794  StringRef Snippet2 = R"cc(795        struct Y {796          void m();797        };798        struct X : public Y {};799        void z(X x) { x.m(); }800      )cc";801  auto MatchesY = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))));802  EXPECT_TRUE(matches(Snippet1, MatchesY));803  EXPECT_TRUE(notMatches(Snippet2, MatchesY));804 805  auto MatchesX = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))));806  EXPECT_TRUE(matches(Snippet2, MatchesX));807 808  // Parens are ignored.809  StringRef Snippet3 = R"cc(810    struct Y {811      void m();812    };813    Y g();814    void z(Y y) { (g()).m(); }815  )cc";816  auto MatchesCall = cxxMemberCallExpr(on(callExpr()));817  EXPECT_TRUE(matches(Snippet3, MatchesCall));818}819 820TEST(MatcherCXXMemberCallExpr, OnImplicitObjectArgument) {821  StringRef Snippet1 = R"cc(822    struct Y {823      void m();824    };825    void z(Y y) { y.m(); }826  )cc";827  StringRef Snippet2 = R"cc(828    struct Y {829      void m();830    };831    struct X : public Y {};832    void z(X x) { x.m(); }833  )cc";834  auto MatchesY = traverse(TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(835                                        hasType(cxxRecordDecl(hasName("Y"))))));836  EXPECT_TRUE(matches(Snippet1, MatchesY));837  EXPECT_TRUE(matches(Snippet2, MatchesY));838 839  auto MatchesX = traverse(TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(840                                        hasType(cxxRecordDecl(hasName("X"))))));841  EXPECT_TRUE(notMatches(Snippet2, MatchesX));842 843  // Parens are not ignored.844  StringRef Snippet3 = R"cc(845    struct Y {846      void m();847    };848    Y g();849    void z(Y y) { (g()).m(); }850  )cc";851  auto MatchesCall = traverse(852      TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(callExpr())));853  EXPECT_TRUE(notMatches(Snippet3, MatchesCall));854}855 856TEST(Matcher, HasObjectExpr) {857  StringRef Snippet1 = R"cc(858        struct X {859          int m;860          int f(X x) { return x.m; }861        };862      )cc";863  StringRef Snippet2 = R"cc(864        struct X {865          int m;866          int f(X x) { return m; }867        };868      )cc";869  auto MatchesX =870      memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))));871  EXPECT_TRUE(matches(Snippet1, MatchesX));872  EXPECT_TRUE(notMatches(Snippet2, MatchesX));873 874  auto MatchesXPointer = memberExpr(875      hasObjectExpression(hasType(pointsTo(cxxRecordDecl(hasName("X"))))));876  EXPECT_TRUE(notMatches(Snippet1, MatchesXPointer));877  EXPECT_TRUE(matches(Snippet2, MatchesXPointer));878}879 880TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) {881  StatementMatcher ArgumentY =882    declRefExpr(to(varDecl(hasName("y")))).bind("arg");883  DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");884  StatementMatcher CallExpr =885    callExpr(forEachArgumentWithParam(ArgumentY, IntParam));886 887  // IntParam does not match.888  EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));889  // ArgumentY does not match.890  EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));891}892 893TEST(ForEachArgumentWithParam, MatchesCXXMemberCallExpr) {894  StatementMatcher ArgumentY =895    declRefExpr(to(varDecl(hasName("y")))).bind("arg");896  DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");897  StatementMatcher CallExpr =898    callExpr(forEachArgumentWithParam(ArgumentY, IntParam));899  EXPECT_TRUE(matchAndVerifyResultTrue(900    "struct S {"901      "  const S& operator[](int i) { return *this; }"902      "};"903      "void f(S S1) {"904      "  int y = 1;"905      "  S1[y];"906      "}",907    CallExpr, std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 1)));908 909  StatementMatcher CallExpr2 =910    callExpr(forEachArgumentWithParam(ArgumentY, IntParam));911  EXPECT_TRUE(matchAndVerifyResultTrue(912    "struct S {"913      "  static void g(int i);"914      "};"915      "void f() {"916      "  int y = 1;"917      "  S::g(y);"918      "}",919    CallExpr2, std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 1)));920}921 922TEST(ForEachArgumentWithParam, MatchesCallExpr) {923  StatementMatcher ArgumentY =924    declRefExpr(to(varDecl(hasName("y")))).bind("arg");925  DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");926  StatementMatcher CallExpr =927    callExpr(forEachArgumentWithParam(ArgumentY, IntParam));928 929  EXPECT_TRUE(930    matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,931                             std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>(932                               "param")));933  EXPECT_TRUE(934    matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,935                             std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>(936                               "arg")));937 938  EXPECT_TRUE(matchAndVerifyResultTrue(939    "void f(int i, int j) { int y; f(y, y); }", CallExpr,940    std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 2)));941  EXPECT_TRUE(matchAndVerifyResultTrue(942    "void f(int i, int j) { int y; f(y, y); }", CallExpr,943    std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));944}945 946TEST(ForEachArgumentWithParam, MatchesConstructExpr) {947  StatementMatcher ArgumentY =948    declRefExpr(to(varDecl(hasName("y")))).bind("arg");949  DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");950  StatementMatcher ConstructExpr = traverse(951      TK_AsIs, cxxConstructExpr(forEachArgumentWithParam(ArgumentY, IntParam)));952 953  EXPECT_TRUE(matchAndVerifyResultTrue(954    "struct C {"955      "  C(int i) {}"956      "};"957      "int y = 0;"958      "C Obj(y);",959    ConstructExpr,960    std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param")));961}962 963TEST(ForEachArgumentWithParam, HandlesBoundNodesForNonMatches) {964  EXPECT_TRUE(matchAndVerifyResultTrue(965    "void g(int i, int j) {"966      "  int a;"967      "  int b;"968      "  int c;"969      "  g(a, 0);"970      "  g(a, b);"971      "  g(0, b);"972      "}",973    functionDecl(974      forEachDescendant(varDecl().bind("v")),975      forEachDescendant(callExpr(forEachArgumentWithParam(976        declRefExpr(to(decl(equalsBoundNode("v")))), parmVarDecl())))),977    std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));978}979 980TEST_P(ASTMatchersTest,981       ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls) {982  if (!GetParam().isCXX23OrLater()) {983    return;984  }985 986  auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");987  auto SelfParam = parmVarDecl().bind("param");988  StatementMatcher CallExpr =989      callExpr(forEachArgumentWithParam(DeclRef, SelfParam));990 991  StringRef S = R"cpp(992  struct A {993    int operator()(this const A &self);994  };995  A obj;996  int global = obj();997  )cpp";998 999  auto Args = GetParam().getCommandLineArgs();1000  auto Filename = getFilenameForTesting(GetParam().Language);1001 1002  EXPECT_TRUE(matchAndVerifyResultTrue(1003      S, CallExpr,1004      std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", "self"), Args,1005      Filename));1006  EXPECT_TRUE(matchAndVerifyResultTrue(1007      S, CallExpr,1008      std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args,1009      Filename));1010}1011 1012TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) {1013  StatementMatcher ArgumentY =1014      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1015  TypeMatcher IntType = qualType(isInteger()).bind("type");1016  StatementMatcher CallExpr =1017      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1018 1019  // IntParam does not match.1020  EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));1021  // ArgumentY does not match.1022  EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));1023}1024 1025TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) {1026  StatementMatcher ArgumentY =1027      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1028  TypeMatcher IntType = qualType(isInteger()).bind("type");1029  StatementMatcher CallExpr =1030      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1031  EXPECT_TRUE(matchAndVerifyResultTrue(1032      "struct S {"1033      "  const S& operator[](int i) { return *this; }"1034      "};"1035      "void f(S S1) {"1036      "  int y = 1;"1037      "  S1[y];"1038      "}",1039      CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));1040 1041  StatementMatcher CallExpr2 =1042      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1043  EXPECT_TRUE(matchAndVerifyResultTrue(1044      "struct S {"1045      "  static void g(int i);"1046      "};"1047      "void f() {"1048      "  int y = 1;"1049      "  S::g(y);"1050      "}",1051      CallExpr2, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));1052}1053 1054TEST(ForEachArgumentWithParamType, MatchesCallExpr) {1055  StatementMatcher ArgumentY =1056      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1057  TypeMatcher IntType = qualType(isInteger()).bind("type");1058  StatementMatcher CallExpr =1059      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1060 1061  EXPECT_TRUE(matchAndVerifyResultTrue(1062      "void f(int i) { int y; f(y); }", CallExpr,1063      std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1064  EXPECT_TRUE(matchAndVerifyResultTrue(1065      "void f(int i) { int y; f(y); }", CallExpr,1066      std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1067 1068  EXPECT_TRUE(matchAndVerifyResultTrue(1069      "void f(int i, int j) { int y; f(y, y); }", CallExpr,1070      std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 2)));1071  EXPECT_TRUE(matchAndVerifyResultTrue(1072      "void f(int i, int j) { int y; f(y, y); }", CallExpr,1073      std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));1074}1075 1076TEST(ForEachArgumentWithParamType, MatchesConstructExpr) {1077  StatementMatcher ArgumentY =1078      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1079  TypeMatcher IntType = qualType(isInteger()).bind("type");1080  StatementMatcher ConstructExpr =1081      cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType));1082 1083  EXPECT_TRUE(matchAndVerifyResultTrue(1084      "struct C {"1085      "  C(int i) {}"1086      "};"1087      "int y = 0;"1088      "C Obj(y);",1089      ConstructExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1090  EXPECT_TRUE(matchAndVerifyResultTrue(1091      "struct C {"1092      "  C(int i) {}"1093      "};"1094      "int y = 0;"1095      "C Obj(y);",1096      ConstructExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1097}1098 1099TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) {1100  StatementMatcher ArgumentY =1101      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1102  TypeMatcher IntType = qualType(isInteger()).bind("type");1103  StatementMatcher CallExpr =1104      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1105 1106  EXPECT_TRUE(matchesC("void f();\n"1107                       "void call_it(void) { int x, y; f(x, y); }\n"1108                       "void f(a, b) int a, b; {}\n"1109                       "void call_it2(void) { int x, y; f(x, y); }",1110                       CallExpr));1111}1112 1113TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) {1114  EXPECT_TRUE(matchAndVerifyResultTrue(1115      "void g(int i, int j) {"1116      "  int a;"1117      "  int b;"1118      "  int c;"1119      "  g(a, 0);"1120      "  g(a, b);"1121      "  g(0, b);"1122      "}",1123      functionDecl(1124          forEachDescendant(varDecl().bind("v")),1125          forEachDescendant(callExpr(forEachArgumentWithParamType(1126              declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),1127      std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));1128}1129 1130TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) {1131  StatementMatcher ArgumentY =1132      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1133  TypeMatcher IntType = qualType(builtinType()).bind("type");1134  StatementMatcher CallExpr =1135      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1136 1137  EXPECT_TRUE(matchAndVerifyResultTrue(1138      "void f(int i) {"1139      "void (*f_ptr)(int) = f; int y; f_ptr(y); }",1140      CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1141  EXPECT_TRUE(matchAndVerifyResultTrue(1142      "void f(int i) {"1143      "void (*f_ptr)(int) = f; int y; f_ptr(y); }",1144      CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1145}1146 1147TEST(ForEachArgumentWithParamType, MatchesMemberFunctionPtrCalls) {1148  StatementMatcher ArgumentY =1149      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1150  TypeMatcher IntType = qualType(builtinType()).bind("type");1151  StatementMatcher CallExpr =1152      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1153 1154  StringRef S = "struct A {\n"1155                "  int f(int i) { return i + 1; }\n"1156                "  int (A::*x)(int);\n"1157                "};\n"1158                "void f() {\n"1159                "  int y = 42;\n"1160                "  A a;\n"1161                "  a.x = &A::f;\n"1162                "  (a.*(a.x))(y);\n"1163                "}";1164  EXPECT_TRUE(matchAndVerifyResultTrue(1165      S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1166  EXPECT_TRUE(matchAndVerifyResultTrue(1167      S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1168}1169 1170TEST(ForEachArgumentWithParamType, MatchesVariadicFunctionPtrCalls) {1171  StatementMatcher ArgumentY =1172      declRefExpr(to(varDecl(hasName("y")))).bind("arg");1173  TypeMatcher IntType = qualType(builtinType()).bind("type");1174  StatementMatcher CallExpr =1175      callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1176 1177  StringRef S = R"cpp(1178    void fcntl(int fd, int cmd, ...) {}1179 1180    template <typename Func>1181    void f(Func F) {1182      int y = 42;1183      F(y, 1, 3);1184    }1185 1186    void g() { f(fcntl); }1187  )cpp";1188 1189  EXPECT_TRUE(matchAndVerifyResultTrue(1190      S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1191  EXPECT_TRUE(matchAndVerifyResultTrue(1192      S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1193}1194 1195TEST_P(ASTMatchersTest,1196       ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls) {1197  if (!GetParam().isCXX23OrLater()) {1198    return;1199  }1200 1201  auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");1202  auto SelfTy = qualType(asString("const A &")).bind("selfType");1203  StatementMatcher CallExpr =1204      callExpr(forEachArgumentWithParamType(DeclRef, SelfTy));1205 1206  StringRef S = R"cpp(1207  struct A {1208    int operator()(this const A &self);1209  };1210  A obj;1211  int global = obj();1212  )cpp";1213 1214  auto Args = GetParam().getCommandLineArgs();1215  auto Filename = getFilenameForTesting(GetParam().Language);1216 1217  EXPECT_TRUE(matchAndVerifyResultTrue(1218      S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("selfType"),1219      Args, Filename));1220  EXPECT_TRUE(matchAndVerifyResultTrue(1221      S, CallExpr,1222      std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args,1223      Filename));1224}1225 1226TEST(QualType, hasCanonicalType) {1227  EXPECT_TRUE(notMatches("typedef int &int_ref;"1228                           "int a;"1229                           "int_ref b = a;",1230                         varDecl(hasType(qualType(referenceType())))));1231  EXPECT_TRUE(1232    matches("typedef int &int_ref;"1233              "int a;"1234              "int_ref b = a;",1235            varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));1236}1237 1238TEST(HasParameter, CallsInnerMatcher) {1239  EXPECT_TRUE(matches("class X { void x(int) {} };",1240                      cxxMethodDecl(hasParameter(0, varDecl()))));1241  EXPECT_TRUE(notMatches("class X { void x(int) {} };",1242                         cxxMethodDecl(hasParameter(0, hasName("x")))));1243  EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",1244                          objcMethodDecl(hasParameter(0, hasName("x")))));1245  EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",1246                          blockDecl(hasParameter(0, hasName("p")))));1247}1248 1249TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {1250  EXPECT_TRUE(notMatches("class X { void x(int) {} };",1251                         cxxMethodDecl(hasParameter(42, varDecl()))));1252}1253 1254TEST(HasType, MatchesParameterVariableTypesStrictly) {1255  EXPECT_TRUE(matches(1256    "class X { void x(X x) {} };",1257    cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));1258  EXPECT_TRUE(notMatches(1259    "class X { void x(const X &x) {} };",1260    cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));1261  EXPECT_TRUE(matches("class X { void x(const X *x) {} };",1262                      cxxMethodDecl(hasParameter(1263                        0, hasType(pointsTo(recordDecl(hasName("X"))))))));1264  EXPECT_TRUE(matches("class X { void x(const X &x) {} };",1265                      cxxMethodDecl(hasParameter(1266                        0, hasType(references(recordDecl(hasName("X"))))))));1267}1268 1269TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {1270  EXPECT_TRUE(matches(1271    "class Y {}; class X { void x(X x, Y y) {} };",1272    cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));1273  EXPECT_TRUE(matches(1274    "class Y {}; class X { void x(Y y, X x) {} };",1275    cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));1276  EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",1277                          objcMethodDecl(hasAnyParameter(hasName("x")))));1278  EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",1279                          blockDecl(hasAnyParameter(hasName("p")))));1280}1281 1282TEST(Returns, MatchesReturnTypes) {1283  EXPECT_TRUE(matches("class Y { int f() { return 1; } };",1284                      functionDecl(returns(asString("int")))));1285  EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",1286                         functionDecl(returns(asString("float")))));1287  EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",1288                      functionDecl(returns(hasDeclaration(1289                        recordDecl(hasName("Y")))))));1290}1291 1292TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {1293  EXPECT_TRUE(notMatches(1294    "class Y {}; class X { void x(int) {} };",1295    cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));1296}1297 1298TEST(HasAnyParameter, DoesNotMatchThisPointer) {1299  EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",1300                         cxxMethodDecl(hasAnyParameter(1301                           hasType(pointsTo(recordDecl(hasName("X"))))))));1302}1303 1304TEST(HasName, MatchesParameterVariableDeclarations) {1305  EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",1306                      cxxMethodDecl(hasAnyParameter(hasName("x")))));1307  EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",1308                         cxxMethodDecl(hasAnyParameter(hasName("x")))));1309}1310 1311TEST(Matcher, MatchesTypeTemplateArgument) {1312  EXPECT_TRUE(matches(1313    "template<typename T> struct B {};"1314      "B<int> b;",1315    classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(1316      asString("int"))))));1317}1318 1319TEST(Matcher, MatchesTemplateTemplateArgument) {1320  EXPECT_TRUE(matches("template<template <typename> class S> class X {};"1321                      "template<typename T> class Y {};"1322                      "X<Y> xi;",1323                      classTemplateSpecializationDecl(hasAnyTemplateArgument(1324                          refersToTemplate(templateName())))));1325}1326 1327TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {1328  EXPECT_TRUE(matches(1329    "struct B { int next; };"1330      "template<int(B::*next_ptr)> struct A {};"1331      "A<&B::next> a;",1332    classTemplateSpecializationDecl(hasAnyTemplateArgument(1333      refersToDeclaration(fieldDecl(hasName("next")))))));1334 1335  EXPECT_TRUE(notMatches(1336    "template <typename T> struct A {};"1337      "A<int> a;",1338    classTemplateSpecializationDecl(hasAnyTemplateArgument(1339      refersToDeclaration(decl())))));1340 1341  EXPECT_TRUE(matches(1342    "struct B { int next; };"1343      "template<int(B::*next_ptr)> struct A {};"1344      "A<&B::next> a;",1345    templateSpecializationType(hasAnyTemplateArgument(isExpr(1346      hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));1347 1348  EXPECT_TRUE(notMatches(1349    "template <typename T> struct A {};"1350      "A<int> a;",1351    templateSpecializationType(hasAnyTemplateArgument(1352      refersToDeclaration(decl())))));1353}1354 1355 1356TEST(Matcher, MatchesSpecificArgument) {1357  EXPECT_TRUE(matches(1358    "template<typename T, typename U> class A {};"1359      "A<bool, int> a;",1360    classTemplateSpecializationDecl(hasTemplateArgument(1361      1, refersToType(asString("int"))))));1362  EXPECT_TRUE(notMatches(1363    "template<typename T, typename U> class A {};"1364      "A<int, bool> a;",1365    classTemplateSpecializationDecl(hasTemplateArgument(1366      1, refersToType(asString("int"))))));1367 1368  EXPECT_TRUE(matches(1369    "template<typename T, typename U> class A {};"1370      "A<bool, int> a;",1371    templateSpecializationType(hasTemplateArgument(1372      1, refersToType(asString("int"))))));1373  EXPECT_TRUE(notMatches(1374    "template<typename T, typename U> class A {};"1375      "A<int, bool> a;",1376    templateSpecializationType(hasTemplateArgument(1377      1, refersToType(asString("int"))))));1378 1379  EXPECT_TRUE(matches(1380    "template<typename T> void f() {};"1381      "void func() { f<int>(); }",1382    functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));1383  EXPECT_TRUE(notMatches(1384    "template<typename T> void f() {};",1385    functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));1386}1387 1388TEST(TemplateArgument, Matches) {1389  EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",1390                      classTemplateSpecializationDecl(1391                        hasAnyTemplateArgument(templateArgument()))));1392  EXPECT_TRUE(matches(1393    "template<typename T> struct C {}; C<int> c;",1394    templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));1395 1396  EXPECT_TRUE(matches(1397    "template<typename T> void f() {};"1398      "void func() { f<int>(); }",1399    functionDecl(hasAnyTemplateArgument(templateArgument()))));1400}1401 1402TEST(TemplateTypeParmDecl, CXXMethodDecl) {1403  const char input[] =1404      "template<typename T>\n"1405      "class Class {\n"1406      "  void method();\n"1407      "};\n"1408      "template<typename U>\n"1409      "void Class<U>::method() {}\n";1410  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1411  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1412}1413 1414TEST(TemplateTypeParmDecl, VarDecl) {1415  const char input[] =1416      "template<typename T>\n"1417      "class Class {\n"1418      "  static T pi;\n"1419      "};\n"1420      "template<typename U>\n"1421      "U Class<U>::pi = U(3.1415926535897932385);\n";1422  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1423  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1424}1425 1426TEST(TemplateTypeParmDecl, VarTemplatePartialSpecializationDecl) {1427  const char input[] =1428      "template<typename T>\n"1429      "struct Struct {\n"1430      "  template<typename T2> static int field;\n"1431      "};\n"1432      "template<typename U>\n"1433      "template<typename U2>\n"1434      "int Struct<U>::field<U2*> = 123;\n";1435  EXPECT_TRUE(1436      matches(input, templateTypeParmDecl(hasName("T")), langCxx14OrLater()));1437  EXPECT_TRUE(1438      matches(input, templateTypeParmDecl(hasName("T2")), langCxx14OrLater()));1439  EXPECT_TRUE(1440      matches(input, templateTypeParmDecl(hasName("U")), langCxx14OrLater()));1441  EXPECT_TRUE(1442      matches(input, templateTypeParmDecl(hasName("U2")), langCxx14OrLater()));1443}1444 1445TEST(TemplateTypeParmDecl, ClassTemplatePartialSpecializationDecl) {1446  const char input[] =1447      "template<typename T>\n"1448      "class Class {\n"1449      "  template<typename T2> struct Struct;\n"1450      "};\n"1451      "template<typename U>\n"1452      "template<typename U2>\n"1453      "struct Class<U>::Struct<U2*> {};\n";1454  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1455  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));1456  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1457  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));1458}1459 1460TEST(TemplateTypeParmDecl, EnumDecl) {1461  const char input[] =1462      "template<typename T>\n"1463      "struct Struct {\n"1464      "  enum class Enum : T;\n"1465      "};\n"1466      "template<typename U>\n"1467      "enum class Struct<U>::Enum : U {\n"1468      "  e1,\n"1469      "  e2\n"1470      "};\n";1471  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1472  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1473}1474 1475TEST(TemplateTypeParmDecl, RecordDecl) {1476  const char input[] =1477      "template<typename T>\n"1478      "class Class {\n"1479      "  struct Struct;\n"1480      "};\n"1481      "template<typename U>\n"1482      "struct Class<U>::Struct {\n"1483      "  U field;\n"1484      "};\n";1485  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1486  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1487}1488 1489TEST(RefersToIntegralType, Matches) {1490  EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",1491                      classTemplateSpecializationDecl(1492                        hasAnyTemplateArgument(refersToIntegralType(1493                          asString("int"))))));1494  EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",1495                         classTemplateSpecializationDecl(hasAnyTemplateArgument(1496                           refersToIntegralType(asString("int"))))));1497}1498 1499TEST(ConstructorDeclaration, SimpleCase) {1500  EXPECT_TRUE(matches("class Foo { Foo(int i); };",1501                      cxxConstructorDecl(ofClass(hasName("Foo")))));1502  EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",1503                         cxxConstructorDecl(ofClass(hasName("Bar")))));1504}1505 1506TEST(DestructorDeclaration, MatchesVirtualDestructor) {1507  EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",1508                      cxxDestructorDecl(ofClass(hasName("Foo")))));1509}1510 1511TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {1512  EXPECT_TRUE(notMatches("class Foo {};",1513                         cxxDestructorDecl(ofClass(hasName("Foo")))));1514}1515 1516TEST(HasAnyConstructorInitializer, SimpleCase) {1517  EXPECT_TRUE(1518    notMatches("class Foo { Foo() { } };",1519               cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));1520  EXPECT_TRUE(1521    matches("class Foo {"1522              "  Foo() : foo_() { }"1523              "  int foo_;"1524              "};",1525            cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));1526}1527 1528TEST(HasAnyConstructorInitializer, ForField) {1529  static const char Code[] =1530    "class Baz { };"1531      "class Foo {"1532      "  Foo() : foo_(), bar_() { }"1533      "  Baz foo_;"1534      "  struct {"1535      "    Baz bar_;"1536      "  };"1537      "};";1538  EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1539    forField(hasType(recordDecl(hasName("Baz"))))))));1540  EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1541    forField(hasName("foo_"))))));1542  EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1543    forField(hasName("bar_"))))));1544  EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1545    forField(hasType(recordDecl(hasName("Bar"))))))));1546}1547 1548TEST(HasAnyConstructorInitializer, WithInitializer) {1549  static const char Code[] =1550    "class Foo {"1551      "  Foo() : foo_(0) { }"1552      "  int foo_;"1553      "};";1554  EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1555    withInitializer(integerLiteral(equals(0)))))));1556  EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1557    withInitializer(integerLiteral(equals(1)))))));1558}1559 1560TEST(HasAnyConstructorInitializer, IsWritten) {1561  static const char Code[] =1562    "struct Bar { Bar(){} };"1563      "class Foo {"1564      "  Foo() : foo_() { }"1565      "  Bar foo_;"1566      "  Bar bar_;"1567      "};";1568  EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1569    allOf(forField(hasName("foo_")), isWritten())))));1570  EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1571    allOf(forField(hasName("bar_")), isWritten())))));1572  EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1573    allOf(forField(hasName("bar_")), unless(isWritten()))))));1574}1575 1576TEST(HasAnyConstructorInitializer, IsBaseInitializer) {1577  static const char Code[] =1578    "struct B {};"1579      "struct D : B {"1580      "  int I;"1581      "  D(int i) : I(i) {}"1582      "};"1583      "struct E : B {"1584      "  E() : B() {}"1585      "};";1586  EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(1587    hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),1588    hasName("E")))));1589  EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(1590    hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),1591    hasName("D")))));1592  EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(1593    hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),1594    hasName("D")))));1595  EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(1596    hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),1597    hasName("E")))));1598}1599 1600TEST(IfStmt, ChildTraversalMatchers) {1601  EXPECT_TRUE(matches("void f() { if (false) true; else false; }",1602                      ifStmt(hasThen(cxxBoolLiteral(equals(true))))));1603  EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",1604                         ifStmt(hasThen(cxxBoolLiteral(equals(true))))));1605  EXPECT_TRUE(matches("void f() { if (false) false; else true; }",1606                      ifStmt(hasElse(cxxBoolLiteral(equals(true))))));1607  EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",1608                         ifStmt(hasElse(cxxBoolLiteral(equals(true))))));1609}1610 1611TEST(MatchBinaryOperator, HasOperatorName) {1612  StatementMatcher OperatorOr = binaryOperator(hasOperatorName("||"));1613 1614  EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr));1615  EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr));1616}1617 1618TEST(MatchBinaryOperator, HasAnyOperatorName) {1619  StatementMatcher Matcher =1620      binaryOperator(hasAnyOperatorName("+", "-", "*", "/"));1621 1622  EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher));1623  EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher));1624  EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher));1625  EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher));1626  EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher));1627  // Ensure '+= isn't mistaken.1628  EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher));1629}1630 1631TEST(MatchBinaryOperator, HasLHSAndHasRHS) {1632  StatementMatcher OperatorTrueFalse =1633    binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),1634                   hasRHS(cxxBoolLiteral(equals(false))));1635 1636  EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));1637  EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));1638  EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse));1639 1640  StatementMatcher OperatorIntPointer = arraySubscriptExpr(1641      hasLHS(hasType(isInteger())),1642      traverse(TK_AsIs, hasRHS(hasType(pointsTo(qualType())))));1643  EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer));1644  EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer));1645 1646  StringRef Code = R"cpp(1647struct HasOpEqMem1648{1649    bool operator==(const HasOpEqMem& other) const1650    {1651        return true;1652    }1653};1654 1655struct HasOpFree1656{1657};1658bool operator==(const HasOpFree& lhs, const HasOpFree& rhs)1659{1660    return true;1661}1662 1663void opMem()1664{1665    HasOpEqMem s1;1666    HasOpEqMem s2;1667    if (s1 == s2)1668        return;1669}1670 1671void opFree()1672{1673    HasOpFree s1;1674    HasOpFree s2;1675    if (s1 == s2)1676        return;1677}1678)cpp";1679  auto s1Expr = declRefExpr(to(varDecl(hasName("s1"))));1680  auto s2Expr = declRefExpr(to(varDecl(hasName("s2"))));1681  EXPECT_TRUE(matches(1682      Code,1683      traverse(TK_IgnoreUnlessSpelledInSource,1684               cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),1685                                   hasOperatorName("=="), hasLHS(s1Expr),1686                                   hasRHS(s2Expr)))));1687  EXPECT_TRUE(matches(1688      Code, traverse(TK_IgnoreUnlessSpelledInSource,1689                     cxxOperatorCallExpr(1690                         forFunction(functionDecl(hasName("opMem"))),1691                         hasAnyOperatorName("!=", "=="), hasLHS(s1Expr)))));1692  EXPECT_TRUE(matches(1693      Code, traverse(TK_IgnoreUnlessSpelledInSource,1694                     cxxOperatorCallExpr(1695                         forFunction(functionDecl(hasName("opMem"))),1696                         hasOperatorName("=="), hasOperands(s1Expr, s2Expr)))));1697  EXPECT_TRUE(matches(1698      Code, traverse(TK_IgnoreUnlessSpelledInSource,1699                     cxxOperatorCallExpr(1700                         forFunction(functionDecl(hasName("opMem"))),1701                         hasOperatorName("=="), hasEitherOperand(s2Expr)))));1702 1703  EXPECT_TRUE(matches(1704      Code,1705      traverse(TK_IgnoreUnlessSpelledInSource,1706               cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),1707                                   hasOperatorName("=="), hasLHS(s1Expr),1708                                   hasRHS(s2Expr)))));1709  EXPECT_TRUE(matches(1710      Code, traverse(TK_IgnoreUnlessSpelledInSource,1711                     cxxOperatorCallExpr(1712                         forFunction(functionDecl(hasName("opFree"))),1713                         hasAnyOperatorName("!=", "=="), hasLHS(s1Expr)))));1714  EXPECT_TRUE(matches(1715      Code, traverse(TK_IgnoreUnlessSpelledInSource,1716                     cxxOperatorCallExpr(1717                         forFunction(functionDecl(hasName("opFree"))),1718                         hasOperatorName("=="), hasOperands(s1Expr, s2Expr)))));1719  EXPECT_TRUE(matches(1720      Code, traverse(TK_IgnoreUnlessSpelledInSource,1721                     cxxOperatorCallExpr(1722                         forFunction(functionDecl(hasName("opFree"))),1723                         hasOperatorName("=="), hasEitherOperand(s2Expr)))));1724}1725 1726TEST(MatchBinaryOperator, HasEitherOperand) {1727  StatementMatcher HasOperand =1728    binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));1729 1730  EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));1731  EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));1732  EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand));1733}1734 1735TEST(MatchBinaryOperator, HasOperands) {1736  StatementMatcher HasOperands = binaryOperator(1737      hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2))));1738  EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands));1739  EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands));1740  EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands));1741  EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands));1742  EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands));1743  EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands));1744}1745 1746TEST(MatchBinaryOperator, HasOperandsEnsureOrdering) {1747  StatementMatcher HasOperandsWithBindings = binaryOperator(hasOperands(1748      cStyleCastExpr(has(declRefExpr(hasDeclaration(valueDecl().bind("d"))))),1749      declRefExpr(hasDeclaration(valueDecl(equalsBoundNode("d"))))));1750  EXPECT_TRUE(matches(1751      "int a; int b = ((int) a) + a;",1752      traverse(TK_IgnoreUnlessSpelledInSource, HasOperandsWithBindings)));1753  EXPECT_TRUE(matches(1754      "int a; int b = a + ((int) a);",1755      traverse(TK_IgnoreUnlessSpelledInSource, HasOperandsWithBindings)));1756}1757 1758TEST(Matcher, BinaryOperatorTypes) {1759  // Integration test that verifies the AST provides all binary operators in1760  // a way we expect.1761  // FIXME: Operator ','1762  EXPECT_TRUE(1763    matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));1764  EXPECT_TRUE(1765    matches("bool b; bool c = (b = true);",1766            binaryOperator(hasOperatorName("="))));1767  EXPECT_TRUE(1768    matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));1769  EXPECT_TRUE(1770    matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));1771  EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));1772  EXPECT_TRUE(1773    matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));1774  EXPECT_TRUE(1775    matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));1776  EXPECT_TRUE(1777    matches("int i = 1; int j = (i <<= 2);",1778            binaryOperator(hasOperatorName("<<="))));1779  EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));1780  EXPECT_TRUE(1781    matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));1782  EXPECT_TRUE(1783    matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));1784  EXPECT_TRUE(1785    matches("int i = 1; int j = (i >>= 2);",1786            binaryOperator(hasOperatorName(">>="))));1787  EXPECT_TRUE(1788    matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));1789  EXPECT_TRUE(1790    matches("int i = 42; int j = (i ^= 42);",1791            binaryOperator(hasOperatorName("^="))));1792  EXPECT_TRUE(1793    matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));1794  EXPECT_TRUE(1795    matches("int i = 42; int j = (i %= 42);",1796            binaryOperator(hasOperatorName("%="))));1797  EXPECT_TRUE(1798    matches("bool b = 42  &23;", binaryOperator(hasOperatorName("&"))));1799  EXPECT_TRUE(1800    matches("bool b = true && false;",1801            binaryOperator(hasOperatorName("&&"))));1802  EXPECT_TRUE(1803    matches("bool b = true; bool c = (b &= false);",1804            binaryOperator(hasOperatorName("&="))));1805  EXPECT_TRUE(1806    matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));1807  EXPECT_TRUE(1808    matches("bool b = true || false;",1809            binaryOperator(hasOperatorName("||"))));1810  EXPECT_TRUE(1811    matches("bool b = true; bool c = (b |= false);",1812            binaryOperator(hasOperatorName("|="))));1813  EXPECT_TRUE(1814    matches("int i = 42  *23;", binaryOperator(hasOperatorName("*"))));1815  EXPECT_TRUE(1816    matches("int i = 42; int j = (i *= 23);",1817            binaryOperator(hasOperatorName("*="))));1818  EXPECT_TRUE(1819    matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));1820  EXPECT_TRUE(1821    matches("int i = 42; int j = (i /= 23);",1822            binaryOperator(hasOperatorName("/="))));1823  EXPECT_TRUE(1824    matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));1825  EXPECT_TRUE(1826    matches("int i = 42; int j = (i += 23);",1827            binaryOperator(hasOperatorName("+="))));1828  EXPECT_TRUE(1829    matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));1830  EXPECT_TRUE(1831    matches("int i = 42; int j = (i -= 23);",1832            binaryOperator(hasOperatorName("-="))));1833  EXPECT_TRUE(1834    matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",1835            binaryOperator(hasOperatorName("->*"))));1836  EXPECT_TRUE(1837    matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",1838            binaryOperator(hasOperatorName(".*"))));1839 1840  // Member expressions as operators are not supported in matches.1841  EXPECT_TRUE(1842    notMatches("struct A { void x(A *a) { a->x(this); } };",1843               binaryOperator(hasOperatorName("->"))));1844 1845  // Initializer assignments are not represented as operator equals.1846  EXPECT_TRUE(1847    notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));1848 1849  // Array indexing is not represented as operator.1850  EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));1851 1852  // Overloaded operators do not match at all.1853  EXPECT_TRUE(notMatches(1854    "struct A { bool operator&&(const A &a) const { return false; } };"1855      "void x() { A a, b; a && b; }",1856    binaryOperator()));1857}1858 1859TEST(MatchUnaryOperator, HasOperatorName) {1860  StatementMatcher OperatorNot = unaryOperator(hasOperatorName("!"));1861 1862  EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot));1863  EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot));1864}1865 1866TEST(MatchUnaryOperator, HasAnyOperatorName) {1867  StatementMatcher Matcher = unaryOperator(hasAnyOperatorName("-", "*", "++"));1868 1869  EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher));1870  EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher));1871  EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher));1872  EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher));1873  EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher));1874  EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher));1875  EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher));1876}1877 1878TEST(MatchUnaryOperator, HasUnaryOperand) {1879  StatementMatcher OperatorOnFalse =1880    unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));1881 1882  EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));1883  EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));1884 1885  StringRef Code = R"cpp(1886struct HasOpBangMem1887{1888    bool operator!() const1889    {1890        return false;1891    }1892};1893struct HasOpBangFree1894{1895};1896bool operator!(HasOpBangFree const&)1897{1898    return false;1899}1900 1901void opMem()1902{1903    HasOpBangMem s1;1904    if (!s1)1905        return;1906}1907void opFree()1908{1909    HasOpBangFree s1;1910    if (!s1)1911        return;1912}1913)cpp";1914  auto s1Expr = declRefExpr(to(varDecl(hasName("s1"))));1915  EXPECT_TRUE(matches(1916      Code, traverse(TK_IgnoreUnlessSpelledInSource,1917                     cxxOperatorCallExpr(1918                         forFunction(functionDecl(hasName("opMem"))),1919                         hasOperatorName("!"), hasUnaryOperand(s1Expr)))));1920  EXPECT_TRUE(matches(1921      Code,1922      traverse(TK_IgnoreUnlessSpelledInSource,1923               cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),1924                                   hasAnyOperatorName("+", "!"),1925                                   hasUnaryOperand(s1Expr)))));1926 1927  EXPECT_TRUE(matches(1928      Code, traverse(TK_IgnoreUnlessSpelledInSource,1929                     cxxOperatorCallExpr(1930                         forFunction(functionDecl(hasName("opFree"))),1931                         hasOperatorName("!"), hasUnaryOperand(s1Expr)))));1932  EXPECT_TRUE(matches(1933      Code,1934      traverse(TK_IgnoreUnlessSpelledInSource,1935               cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),1936                                   hasAnyOperatorName("+", "!"),1937                                   hasUnaryOperand(s1Expr)))));1938 1939  Code = R"cpp(1940struct HasIncOperatorsMem1941{1942    HasIncOperatorsMem& operator++();1943    HasIncOperatorsMem operator++(int);1944};1945struct HasIncOperatorsFree1946{1947};1948HasIncOperatorsFree& operator++(HasIncOperatorsFree&);1949HasIncOperatorsFree operator++(HasIncOperatorsFree&, int);1950 1951void prefixIncOperatorMem()1952{1953    HasIncOperatorsMem s1;1954    ++s1;1955}1956void prefixIncOperatorFree()1957{1958    HasIncOperatorsFree s1;1959    ++s1;1960}1961void postfixIncOperatorMem()1962{1963    HasIncOperatorsMem s1;1964    s1++;1965}1966void postfixIncOperatorFree()1967{1968    HasIncOperatorsFree s1;1969    s1++;1970}1971 1972struct HasOpPlusInt1973{1974    HasOpPlusInt& operator+(int);1975};1976void plusIntOperator()1977{1978    HasOpPlusInt s1;1979    s1+1;1980}1981)cpp";1982 1983  EXPECT_TRUE(matches(1984      Code,1985      traverse(TK_IgnoreUnlessSpelledInSource,1986               cxxOperatorCallExpr(1987                   forFunction(functionDecl(hasName("prefixIncOperatorMem"))),1988                   hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));1989 1990  EXPECT_TRUE(matches(1991      Code,1992      traverse(TK_IgnoreUnlessSpelledInSource,1993               cxxOperatorCallExpr(1994                   forFunction(functionDecl(hasName("prefixIncOperatorFree"))),1995                   hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));1996 1997  EXPECT_TRUE(matches(1998      Code,1999      traverse(TK_IgnoreUnlessSpelledInSource,2000               cxxOperatorCallExpr(2001                   forFunction(functionDecl(hasName("postfixIncOperatorMem"))),2002                   hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));2003 2004  EXPECT_TRUE(matches(2005      Code,2006      traverse(TK_IgnoreUnlessSpelledInSource,2007               cxxOperatorCallExpr(2008                   forFunction(functionDecl(hasName("postfixIncOperatorFree"))),2009                   hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));2010 2011  EXPECT_FALSE(matches(2012      Code, traverse(TK_IgnoreUnlessSpelledInSource,2013                     cxxOperatorCallExpr(2014                         forFunction(functionDecl(hasName("plusIntOperator"))),2015                         hasOperatorName("+"), hasUnaryOperand(expr())))));2016 2017  Code = R"cpp(2018struct S {2019  void foo(int);2020};2021struct HasOpStar2022{2023    int& operator*();2024};2025struct HasOpArrow2026{2027    S* operator->();2028};2029void hasOpStarMem(HasOpStar s)2030{2031    *s;2032}2033void hasOpArrowMem(HasOpArrow a)2034{2035    a->foo(42);2036}2037)cpp";2038 2039  EXPECT_TRUE(2040      matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2041                             cxxOperatorCallExpr(hasOperatorName("*"),2042                                                 hasUnaryOperand(expr())))));2043  EXPECT_TRUE(matches(2044      Code, traverse(TK_IgnoreUnlessSpelledInSource,2045                     cxxOperatorCallExpr(hasOperatorName("->"),2046                                         hasUnaryOperand(declRefExpr(2047                                             to(varDecl(hasName("a")))))))));2048}2049 2050TEST(Matcher, UnaryOperatorTypes) {2051  // Integration test that verifies the AST provides all unary operators in2052  // a way we expect.2053  EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));2054  EXPECT_TRUE(2055    matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));2056  EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));2057  EXPECT_TRUE(2058    matches("bool *p; bool b = *p;", unaryOperator(hasOperatorName("*"))));2059  EXPECT_TRUE(2060    matches("int i; int j = +i;", unaryOperator(hasOperatorName("+"))));2061  EXPECT_TRUE(2062    matches("int i; int j = -i;", unaryOperator(hasOperatorName("-"))));2063  EXPECT_TRUE(2064    matches("int i; int j = ++i;", unaryOperator(hasOperatorName("++"))));2065  EXPECT_TRUE(2066    matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));2067  EXPECT_TRUE(2068    matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));2069  EXPECT_TRUE(2070    matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));2071 2072  // We don't match conversion operators.2073  EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));2074 2075  // Function calls are not represented as operator.2076  EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));2077 2078  // Overloaded operators do not match at all.2079  // FIXME: We probably want to add that.2080  EXPECT_TRUE(notMatches(2081    "struct A { bool operator!() const { return false; } };"2082      "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));2083}2084 2085TEST_P(ASTMatchersTest, HasInit) {2086  if (!GetParam().isCXX11OrLater()) {2087    // FIXME: Add a test for `hasInit()` that does not depend on C++.2088    return;2089  }2090 2091  EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));2092  EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));2093  EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));2094}2095 2096TEST_P(ASTMatchersTest, HasFoldInit) {2097  if (!GetParam().isCXX17OrLater()) {2098    return;2099  }2100 2101  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2102                      "return (0 + ... + args); }",2103                      cxxFoldExpr(hasFoldInit(expr()))));2104  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2105                      "return (args + ... + 0); }",2106                      cxxFoldExpr(hasFoldInit(expr()))));2107  EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2108                       "return (... + args); };",2109                       cxxFoldExpr(hasFoldInit(expr()))));2110}2111 2112TEST_P(ASTMatchersTest, HasPattern) {2113  if (!GetParam().isCXX17OrLater()) {2114    return;2115  }2116 2117  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2118                      "return (0 + ... + args); }",2119                      cxxFoldExpr(hasPattern(expr()))));2120  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2121                      "return (args + ... + 0); }",2122                      cxxFoldExpr(hasPattern(expr()))));2123  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2124                      "return (... + args); };",2125                      cxxFoldExpr(hasPattern(expr()))));2126}2127 2128TEST_P(ASTMatchersTest, HasLHSAndHasRHS) {2129  if (!GetParam().isCXX17OrLater()) {2130    return;2131  }2132 2133  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2134                      "return (0 + ... + args); }",2135                      cxxFoldExpr(hasLHS(expr()))));2136  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2137                      "return (args + ... + 0); }",2138                      cxxFoldExpr(hasLHS(expr()))));2139  EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2140                       "return (... + args); };",2141                       cxxFoldExpr(hasLHS(expr()))));2142  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2143                      "return (args + ...); };",2144                      cxxFoldExpr(hasLHS(expr()))));2145 2146  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2147                      "return (0 + ... + args); }",2148                      cxxFoldExpr(hasRHS(expr()))));2149  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2150                      "return (args + ... + 0); }",2151                      cxxFoldExpr(hasRHS(expr()))));2152  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2153                      "return (... + args); };",2154                      cxxFoldExpr(hasRHS(expr()))));2155  EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2156                       "return (args + ...); };",2157                       cxxFoldExpr(hasRHS(expr()))));2158}2159 2160TEST_P(ASTMatchersTest, HasEitherOperandAndHasOperands) {2161  if (!GetParam().isCXX17OrLater()) {2162    return;2163  }2164 2165  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2166                      "return (0 + ... + args); }",2167                      cxxFoldExpr(hasEitherOperand(integerLiteral()))));2168  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2169                      "return (args + ... + 0); }",2170                      cxxFoldExpr(hasEitherOperand(integerLiteral()))));2171 2172  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2173                      "return (0 + ... + args); }",2174                      cxxFoldExpr(hasEitherOperand(2175                          declRefExpr(to(namedDecl(hasName("args"))))))));2176  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2177                      "return (args + ... + 0); }",2178                      cxxFoldExpr(hasEitherOperand(2179                          declRefExpr(to(namedDecl(hasName("args"))))))));2180  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2181                      "return (... + args); };",2182                      cxxFoldExpr(hasEitherOperand(2183                          declRefExpr(to(namedDecl(hasName("args"))))))));2184  EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2185                      "return (args + ...); };",2186                      cxxFoldExpr(hasEitherOperand(2187                          declRefExpr(to(namedDecl(hasName("args"))))))));2188 2189  EXPECT_TRUE(matches(2190      "template <typename... Args> auto sum(Args... args) { "2191      "return (0 + ... + args); }",2192      cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2193                              integerLiteral()))));2194  EXPECT_TRUE(matches(2195      "template <typename... Args> auto sum(Args... args) { "2196      "return (args + ... + 0); }",2197      cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2198                              integerLiteral()))));2199  EXPECT_FALSE(matches(2200      "template <typename... Args> auto sum(Args... args) { "2201      "return (... + args); };",2202      cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2203                              integerLiteral()))));2204  EXPECT_FALSE(matches(2205      "template <typename... Args> auto sum(Args... args) { "2206      "return (args + ...); };",2207      cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2208                              integerLiteral()))));2209}2210 2211TEST_P(ASTMatchersTest, Callee) {2212  if (!GetParam().isCXX17OrLater()) {2213    return;2214  }2215 2216  EXPECT_TRUE(matches(2217      "struct Dummy {}; Dummy operator+(Dummy, Dummy); template "2218      "<typename... Args> auto sum(Args... args) { return (0 + ... + args); }",2219      cxxFoldExpr(callee(expr()))));2220  EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2221                       "return (0 + ... + args); }",2222                       cxxFoldExpr(callee(expr()))));2223}2224 2225TEST(ArraySubscriptMatchers, ArrayIndex) {2226  EXPECT_TRUE(matches(2227    "int i[2]; void f() { i[1] = 1; }",2228    arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));2229  EXPECT_TRUE(matches(2230    "int i[2]; void f() { 1[i] = 1; }",2231    arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));2232  EXPECT_TRUE(notMatches(2233    "int i[2]; void f() { i[1] = 1; }",2234    arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));2235}2236 2237TEST(ArraySubscriptMatchers, MatchesArrayBase) {2238  EXPECT_TRUE(2239      matches("int i[2]; void f() { i[1] = 2; }",2240              traverse(TK_AsIs, arraySubscriptExpr(hasBase(implicitCastExpr(2241                                    hasSourceExpression(declRefExpr())))))));2242}2243 2244TEST(Matcher, OfClass) {2245  StatementMatcher Constructor = cxxConstructExpr(hasDeclaration(cxxMethodDecl(2246    ofClass(hasName("X")))));2247 2248  EXPECT_TRUE(2249    matches("class X { public: X(); }; void x(int) { X x; }", Constructor));2250  EXPECT_TRUE(2251    matches("class X { public: X(); }; void x(int) { X x = X(); }",2252            Constructor));2253  EXPECT_TRUE(2254    notMatches("class Y { public: Y(); }; void x(int) { Y y; }",2255               Constructor));2256}2257 2258TEST(Matcher, VisitsTemplateInstantiations) {2259  EXPECT_TRUE(matches(2260    "class A { public: void x(); };"2261      "template <typename T> class B { public: void y() { T t; t.x(); } };"2262      "void f() { B<A> b; b.y(); }",2263    callExpr(callee(cxxMethodDecl(hasName("x"))))));2264 2265  EXPECT_TRUE(matches(2266    "class A { public: void x(); };"2267      "class C {"2268      " public:"2269      "  template <typename T> class B { public: void y() { T t; t.x(); } };"2270      "};"2271      "void f() {"2272      "  C::B<A> b; b.y();"2273      "}",2274    recordDecl(hasName("C"), hasDescendant(callExpr(2275      callee(cxxMethodDecl(hasName("x"))))))));2276}2277 2278TEST(Matcher, HasCondition) {2279  StatementMatcher IfStmt =2280    ifStmt(hasCondition(cxxBoolLiteral(equals(true))));2281  EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt));2282  EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt));2283 2284  StatementMatcher ForStmt =2285    forStmt(hasCondition(cxxBoolLiteral(equals(true))));2286  EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt));2287  EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt));2288 2289  StatementMatcher WhileStmt =2290    whileStmt(hasCondition(cxxBoolLiteral(equals(true))));2291  EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt));2292  EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt));2293 2294  StatementMatcher SwitchStmt =2295    switchStmt(hasCondition(integerLiteral(equals(42))));2296  EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt));2297  EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt));2298}2299 2300TEST(For, ForLoopInternals) {2301  EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",2302                      forStmt(hasCondition(anything()))));2303  EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",2304                      forStmt(hasLoopInit(anything()))));2305}2306 2307TEST(For, ForRangeLoopInternals) {2308  EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",2309                      cxxForRangeStmt(hasLoopVariable(anything()))));2310  EXPECT_TRUE(matches(2311    "void f(){ int a[] {1, 2}; for (int i : a); }",2312    cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));2313}2314 2315TEST(For, NegativeForLoopInternals) {2316  EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",2317                         forStmt(hasCondition(expr()))));2318  EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",2319                         forStmt(hasLoopInit(anything()))));2320}2321 2322TEST(HasBody, FindsBodyOfForWhileDoLoops) {2323  EXPECT_TRUE(matches("void f() { for(;;) {} }",2324                      forStmt(hasBody(compoundStmt()))));2325  EXPECT_TRUE(notMatches("void f() { for(;;); }",2326                         forStmt(hasBody(compoundStmt()))));2327  EXPECT_TRUE(matches("void f() { while(true) {} }",2328                      whileStmt(hasBody(compoundStmt()))));2329  EXPECT_TRUE(matches("void f() { do {} while(true); }",2330                      doStmt(hasBody(compoundStmt()))));2331  EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",2332                      cxxForRangeStmt(hasBody(compoundStmt()))));2333}2334 2335TEST(HasBody, FindsBodyOfFunctions) {2336  EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));2337  EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));2338  EXPECT_TRUE(matchAndVerifyResultTrue(2339      "void f(); void f() {}",2340      functionDecl(hasBody(compoundStmt())).bind("func"),2341      std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 1)));2342  EXPECT_TRUE(matchAndVerifyResultTrue(2343      "class C { void f(); }; void C::f() {}",2344      cxxMethodDecl(hasBody(compoundStmt())).bind("met"),2345      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 1)));2346  EXPECT_TRUE(matchAndVerifyResultTrue(2347      "class C { C(); }; C::C() {}",2348      cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),2349      std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 1)));2350  EXPECT_TRUE(matchAndVerifyResultTrue(2351      "class C { ~C(); }; C::~C() {}",2352      cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),2353      std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 1)));2354}2355 2356TEST(HasAnyBody, FindsAnyBodyOfFunctions) {2357  EXPECT_TRUE(matches("void f() {}", functionDecl(hasAnyBody(compoundStmt()))));2358  EXPECT_TRUE(notMatches("void f();",2359                         functionDecl(hasAnyBody(compoundStmt()))));2360  EXPECT_TRUE(matchAndVerifyResultTrue(2361      "void f(); void f() {}",2362      functionDecl(hasAnyBody(compoundStmt())).bind("func"),2363      std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 2)));2364  EXPECT_TRUE(matchAndVerifyResultTrue(2365      "class C { void f(); }; void C::f() {}",2366      cxxMethodDecl(hasAnyBody(compoundStmt())).bind("met"),2367      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 2)));2368  EXPECT_TRUE(matchAndVerifyResultTrue(2369      "class C { C(); }; C::C() {}",2370      cxxConstructorDecl(hasAnyBody(compoundStmt())).bind("ctr"),2371      std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 2)));2372  EXPECT_TRUE(matchAndVerifyResultTrue(2373      "class C { ~C(); }; C::~C() {}",2374      cxxDestructorDecl(hasAnyBody(compoundStmt())).bind("dtr"),2375      std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 2)));2376}2377 2378TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {2379  // The simplest case: every compound statement is in a function2380  // definition, and the function body itself must be a compound2381  // statement.2382  EXPECT_TRUE(matches("void f() { for (;;); }",2383                      compoundStmt(hasAnySubstatement(forStmt()))));2384}2385 2386TEST(HasAnySubstatement, IsNotRecursive) {2387  // It's really "has any immediate substatement".2388  EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",2389                         compoundStmt(hasAnySubstatement(forStmt()))));2390}2391 2392TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {2393  EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",2394                      compoundStmt(hasAnySubstatement(forStmt()))));2395}2396 2397TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {2398  EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",2399                      compoundStmt(hasAnySubstatement(forStmt()))));2400}2401 2402TEST(Member, MatchesMemberAllocationFunction) {2403  // Fails in C++11 mode2404  EXPECT_TRUE(matchesConditionally(2405      "namespace std { typedef typeof(sizeof(int)) size_t; }"2406      "class X { void *operator new(std::size_t); };",2407      cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));2408 2409  EXPECT_TRUE(matches("class X { void operator delete(void*); };",2410                      cxxMethodDecl(ofClass(hasName("X")))));2411 2412  // Fails in C++11 mode2413  EXPECT_TRUE(matchesConditionally(2414      "namespace std { typedef typeof(sizeof(int)) size_t; }"2415      "class X { void operator delete[](void*, std::size_t); };",2416      cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));2417}2418 2419TEST(HasDestinationType, MatchesSimpleCase) {2420  EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",2421                      cxxStaticCastExpr(hasDestinationType(2422                        pointsTo(TypeMatcher(anything()))))));2423}2424 2425TEST(HasImplicitDestinationType, MatchesSimpleCase) {2426  // This test creates an implicit const cast.2427  EXPECT_TRUE(matches(2428      "int x; const int i = x;",2429      traverse(TK_AsIs,2430               implicitCastExpr(hasImplicitDestinationType(isInteger())))));2431  // This test creates an implicit array-to-pointer cast.2432  EXPECT_TRUE(2433      matches("int arr[3]; int *p = arr;",2434              traverse(TK_AsIs, implicitCastExpr(hasImplicitDestinationType(2435                                    pointsTo(TypeMatcher(anything())))))));2436}2437 2438TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {2439  // This test creates an implicit cast from int to char.2440  EXPECT_TRUE(notMatches("char c = 0;",2441                         implicitCastExpr(hasImplicitDestinationType(2442                           unless(anything())))));2443  // This test creates an implicit array-to-pointer cast.2444  EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",2445                         implicitCastExpr(hasImplicitDestinationType(2446                           unless(anything())))));2447}2448 2449TEST(Matcher, IgnoresElidableConstructors) {2450  EXPECT_TRUE(2451      matches("struct H {};"2452              "template<typename T> H B(T A);"2453              "void f() {"2454              "  H D1;"2455              "  D1 = B(B(1));"2456              "}",2457              cxxOperatorCallExpr(hasArgument(2458                  1, callExpr(hasArgument(2459                         0, ignoringElidableConstructorCall(callExpr()))))),2460              langCxx11OrLater()));2461  EXPECT_TRUE(2462      matches("struct H {};"2463              "template<typename T> H B(T A);"2464              "void f() {"2465              "  H D1;"2466              "  D1 = B(1);"2467              "}",2468              cxxOperatorCallExpr(hasArgument(2469                  1, callExpr(hasArgument(0, ignoringElidableConstructorCall(2470                                                 integerLiteral()))))),2471              langCxx11OrLater()));2472  EXPECT_TRUE(matches(2473      "struct H {};"2474      "H G();"2475      "void f() {"2476      "  H D = G();"2477      "}",2478      varDecl(hasInitializer(anyOf(2479          ignoringElidableConstructorCall(callExpr()),2480          exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())))))),2481      langCxx11OrLater()));2482}2483 2484TEST(Matcher, IgnoresElidableInReturn) {2485  auto matcher = expr(ignoringElidableConstructorCall(declRefExpr()));2486  EXPECT_TRUE(matches("struct H {};"2487                      "H f() {"2488                      "  H g;"2489                      "  return g;"2490                      "}",2491                      matcher, langCxx11OrLater()));2492  EXPECT_TRUE(notMatches("struct H {};"2493                         "H f() {"2494                         "  return H();"2495                         "}",2496                         matcher, langCxx11OrLater()));2497}2498 2499TEST(Matcher, IgnoreElidableConstructorDoesNotMatchConstructors) {2500  EXPECT_TRUE(matches("struct H {};"2501                      "void f() {"2502                      "  H D;"2503                      "}",2504                      varDecl(hasInitializer(2505                          ignoringElidableConstructorCall(cxxConstructExpr()))),2506                      langCxx11OrLater()));2507}2508 2509TEST(Matcher, IgnoresElidableDoesNotPreventMatches) {2510  EXPECT_TRUE(matches("void f() {"2511                      "  int D = 10;"2512                      "}",2513                      expr(ignoringElidableConstructorCall(integerLiteral())),2514                      langCxx11OrLater()));2515}2516 2517TEST(Matcher, IgnoresElidableInVarInit) {2518  auto matcher =2519      varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())));2520  EXPECT_TRUE(matches("struct H {};"2521                      "H G();"2522                      "void f(H D = G()) {"2523                      "  return;"2524                      "}",2525                      matcher, langCxx11OrLater()));2526  EXPECT_TRUE(matches("struct H {};"2527                      "H G();"2528                      "void f() {"2529                      "  H D = G();"2530                      "}",2531                      matcher, langCxx11OrLater()));2532}2533 2534TEST(IgnoringImplicit, MatchesImplicit) {2535  EXPECT_TRUE(matches("class C {}; C a = C();",2536                      varDecl(has(ignoringImplicit(cxxConstructExpr())))));2537}2538 2539TEST(IgnoringImplicit, MatchesNestedImplicit) {2540  StringRef Code = R"(2541 2542struct OtherType;2543 2544struct SomeType2545{2546    SomeType() {}2547    SomeType(const OtherType&) {}2548    SomeType& operator=(OtherType const&) { return *this; }2549};2550 2551struct OtherType2552{2553    OtherType() {}2554    ~OtherType() {}2555};2556 2557OtherType something()2558{2559    return {};2560}2561 2562int main()2563{2564    SomeType i = something();2565}2566)";2567  EXPECT_TRUE(matches(2568      Code,2569      traverse(TK_AsIs,2570               varDecl(hasName("i"),2571                       hasInitializer(exprWithCleanups(has(cxxConstructExpr(2572                           has(expr(ignoringImplicit(cxxConstructExpr(has(2573                               expr(ignoringImplicit(callExpr())))))))))))))));2574}2575 2576TEST(IgnoringImplicit, DoesNotMatchIncorrectly) {2577  EXPECT_TRUE(notMatches("class C {}; C a = C();",2578                         traverse(TK_AsIs, varDecl(has(cxxConstructExpr())))));2579}2580 2581TEST(Traversal, traverseMatcher) {2582 2583  StringRef VarDeclCode = R"cpp(2584void foo()2585{2586  int i = 3.0;2587}2588)cpp";2589 2590  auto Matcher = varDecl(hasInitializer(floatLiteral()));2591 2592  EXPECT_TRUE(notMatches(VarDeclCode, traverse(TK_AsIs, Matcher)));2593  EXPECT_TRUE(2594      matches(VarDeclCode, traverse(TK_IgnoreUnlessSpelledInSource, Matcher)));2595 2596  auto ParentMatcher = floatLiteral(hasParent(varDecl(hasName("i"))));2597 2598  EXPECT_TRUE(notMatches(VarDeclCode, traverse(TK_AsIs, ParentMatcher)));2599  EXPECT_TRUE(matches(VarDeclCode,2600                      traverse(TK_IgnoreUnlessSpelledInSource, ParentMatcher)));2601 2602  EXPECT_TRUE(matches(2603      VarDeclCode, decl(traverse(TK_AsIs, anyOf(cxxRecordDecl(), varDecl())))));2604 2605  EXPECT_TRUE(2606      matches(VarDeclCode,2607              floatLiteral(traverse(TK_AsIs, hasParent(implicitCastExpr())))));2608 2609  EXPECT_TRUE(2610      matches(VarDeclCode, floatLiteral(traverse(TK_IgnoreUnlessSpelledInSource,2611                                                 hasParent(varDecl())))));2612 2613  EXPECT_TRUE(2614      matches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,2615                                            unless(parmVarDecl())))));2616 2617  EXPECT_TRUE(2618      notMatches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,2619                                               has(implicitCastExpr())))));2620 2621  EXPECT_TRUE(matches(VarDeclCode,2622                      varDecl(traverse(TK_AsIs, has(implicitCastExpr())))));2623 2624  EXPECT_TRUE(matches(2625      VarDeclCode, traverse(TK_IgnoreUnlessSpelledInSource,2626                            // The has() below strips away the ImplicitCastExpr2627                            // before the traverse(AsIs) gets to process it.2628                            varDecl(has(traverse(TK_AsIs, floatLiteral()))))));2629 2630  EXPECT_TRUE(2631      matches(VarDeclCode, functionDecl(traverse(TK_AsIs, hasName("foo")))));2632 2633  EXPECT_TRUE(matches(2634      VarDeclCode,2635      functionDecl(traverse(TK_IgnoreUnlessSpelledInSource, hasName("foo")))));2636 2637  EXPECT_TRUE(matches(2638      VarDeclCode, functionDecl(traverse(TK_AsIs, hasAnyName("foo", "bar")))));2639 2640  EXPECT_TRUE(2641      matches(VarDeclCode, functionDecl(traverse(TK_IgnoreUnlessSpelledInSource,2642                                                 hasAnyName("foo", "bar")))));2643 2644  StringRef Code = R"cpp(2645void foo(int a)2646{2647  int i = 3.0 + a;2648}2649void bar()2650{2651  foo(7.0);2652}2653)cpp";2654  EXPECT_TRUE(2655      matches(Code, callExpr(traverse(TK_IgnoreUnlessSpelledInSource,2656                                      hasArgument(0, floatLiteral())))));2657 2658  EXPECT_TRUE(2659      matches(Code, callExpr(traverse(TK_IgnoreUnlessSpelledInSource,2660                                      hasAnyArgument(floatLiteral())))));2661 2662  EXPECT_TRUE(matches(2663      R"cpp(2664void takesBool(bool){}2665 2666template <typename T>2667void neverInstantiatedTemplate() {2668  takesBool(T{});2669}2670)cpp",2671      traverse(TK_IgnoreUnlessSpelledInSource,2672               callExpr(unless(callExpr(hasDeclaration(functionDecl())))))));2673 2674  EXPECT_TRUE(2675      matches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,2676                                            hasType(builtinType())))));2677 2678  EXPECT_TRUE(2679      matches(VarDeclCode,2680              functionDecl(hasName("foo"),2681                           traverse(TK_AsIs, hasDescendant(floatLiteral())))));2682 2683  EXPECT_TRUE(notMatches(2684      Code, traverse(TK_AsIs, floatLiteral(hasParent(callExpr(2685                                  callee(functionDecl(hasName("foo")))))))));2686  EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2687                                     floatLiteral(hasParent(callExpr(callee(2688                                         functionDecl(hasName("foo")))))))));2689 2690  Code = R"cpp(2691void foo()2692{2693  int i = (3);2694}2695)cpp";2696  EXPECT_TRUE(matches(2697      Code, traverse(TK_IgnoreUnlessSpelledInSource,2698                     varDecl(hasInitializer(integerLiteral(equals(3)))))));2699  EXPECT_TRUE(matches(2700      Code,2701      traverse(TK_IgnoreUnlessSpelledInSource,2702               integerLiteral(equals(3), hasParent(varDecl(hasName("i")))))));2703 2704  Code = R"cpp(2705const char *SomeString{"str"};2706)cpp";2707  EXPECT_TRUE(2708      matches(Code, traverse(TK_AsIs, stringLiteral(hasParent(implicitCastExpr(2709                                          hasParent(initListExpr())))))));2710  EXPECT_TRUE(2711      matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2712                             stringLiteral(hasParent(initListExpr())))));2713 2714  Code = R"cpp(2715struct String2716{2717    String(const char*, int = -1) {}2718};2719 2720void stringConstruct()2721{2722    String s = "foo";2723    s = "bar";2724}2725)cpp";2726  EXPECT_TRUE(matches(2727      Code,2728      traverse(2729          TK_AsIs,2730          functionDecl(2731              hasName("stringConstruct"),2732              hasDescendant(varDecl(2733                  hasName("s"),2734                  hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(2735                      0, ignoringImplicit(cxxConstructExpr(hasArgument(2736                             0, ignoringImplicit(stringLiteral()))))))))))))));2737 2738  EXPECT_TRUE(matches(2739      Code,2740      traverse(2741          TK_AsIs,2742          functionDecl(hasName("stringConstruct"),2743                       hasDescendant(cxxOperatorCallExpr(2744                           isAssignmentOperator(),2745                           hasArgument(1, ignoringImplicit(2746                            cxxConstructExpr(hasArgument(2747                               0, ignoringImplicit(stringLiteral())))))2748                           ))))));2749 2750  EXPECT_TRUE(matches(2751      Code, traverse(TK_IgnoreUnlessSpelledInSource,2752                     functionDecl(hasName("stringConstruct"),2753                                  hasDescendant(varDecl(2754                                      hasName("s"),2755                                      hasInitializer(stringLiteral())))))));2756 2757  EXPECT_TRUE(2758      matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2759                             functionDecl(hasName("stringConstruct"),2760                                          hasDescendant(cxxOperatorCallExpr(2761                                              isAssignmentOperator(),2762                                              hasArgument(1, stringLiteral())))))));2763 2764  Code = R"cpp(2765 2766struct C1 {};2767struct C2 { operator C1(); };2768 2769void conversionOperator()2770{2771    C2* c2;2772    C1 c1 = (*c2);2773}2774 2775)cpp";2776  EXPECT_TRUE(matches(2777      Code,2778      traverse(2779          TK_AsIs,2780          functionDecl(2781              hasName("conversionOperator"),2782              hasDescendant(2783                  varDecl(2784                      hasName("c1"),2785                      hasInitializer(2786                          ignoringImplicit(cxxConstructExpr(hasArgument(2787                              0, ignoringImplicit(2788                                     cxxMemberCallExpr(onImplicitObjectArgument(2789                                         ignoringParenImpCasts(unaryOperator(2790                                             hasOperatorName("*")))))))))))2791                      .bind("c1"))))));2792 2793  EXPECT_TRUE(matches(2794      Code,2795      traverse(TK_IgnoreUnlessSpelledInSource,2796               functionDecl(hasName("conversionOperator"),2797                            hasDescendant(varDecl(2798                                hasName("c1"), hasInitializer(unaryOperator(2799                                                   hasOperatorName("*")))))))));2800 2801  Code = R"cpp(2802 2803template <unsigned alignment>2804void template_test() {2805  static_assert(alignment, "");2806}2807void actual_template_test() {2808  template_test<4>();2809}2810 2811)cpp";2812  EXPECT_TRUE(matches(2813      Code,2814      traverse(TK_AsIs,2815               staticAssertDecl(has(implicitCastExpr(has(2816                   substNonTypeTemplateParmExpr(has(integerLiteral())))))))));2817  EXPECT_TRUE(matches(2818      Code, traverse(TK_IgnoreUnlessSpelledInSource,2819                     staticAssertDecl(has(declRefExpr(2820                         to(nonTypeTemplateParmDecl(hasName("alignment"))),2821                         hasType(asString("unsigned int"))))))));2822 2823  EXPECT_TRUE(matches(Code, traverse(TK_AsIs, staticAssertDecl(hasDescendant(2824                                                  integerLiteral())))));2825  EXPECT_FALSE(matches(2826      Code, traverse(TK_IgnoreUnlessSpelledInSource,2827                     staticAssertDecl(hasDescendant(integerLiteral())))));2828 2829  Code = R"cpp(2830 2831struct OneParamCtor {2832  explicit OneParamCtor(int);2833};2834struct TwoParamCtor {2835  explicit TwoParamCtor(int, int);2836};2837 2838void varDeclCtors() {2839  {2840  auto var1 = OneParamCtor(5);2841  auto var2 = TwoParamCtor(6, 7);2842  }2843  {2844  OneParamCtor var3(5);2845  TwoParamCtor var4(6, 7);2846  }2847  int i = 0;2848  {2849  auto var5 = OneParamCtor(i);2850  auto var6 = TwoParamCtor(i, 7);2851  }2852  {2853  OneParamCtor var7(i);2854  TwoParamCtor var8(i, 7);2855  }2856}2857 2858)cpp";2859  EXPECT_TRUE(matches(2860      Code,2861      traverse(TK_AsIs, varDecl(hasName("var1"), hasInitializer(hasDescendant(2862                                                     cxxConstructExpr()))))));2863  EXPECT_TRUE(matches(2864      Code,2865      traverse(TK_AsIs, varDecl(hasName("var2"), hasInitializer(hasDescendant(2866                                                     cxxConstructExpr()))))));2867  EXPECT_TRUE(matches(2868      Code, traverse(TK_AsIs, varDecl(hasName("var3"),2869                                      hasInitializer(cxxConstructExpr())))));2870  EXPECT_TRUE(matches(2871      Code, traverse(TK_AsIs, varDecl(hasName("var4"),2872                                      hasInitializer(cxxConstructExpr())))));2873  EXPECT_TRUE(matches(2874      Code,2875      traverse(TK_AsIs, varDecl(hasName("var5"), hasInitializer(hasDescendant(2876                                                     cxxConstructExpr()))))));2877  EXPECT_TRUE(matches(2878      Code,2879      traverse(TK_AsIs, varDecl(hasName("var6"), hasInitializer(hasDescendant(2880                                                     cxxConstructExpr()))))));2881  EXPECT_TRUE(matches(2882      Code, traverse(TK_AsIs, varDecl(hasName("var7"),2883                                      hasInitializer(cxxConstructExpr())))));2884  EXPECT_TRUE(matches(2885      Code, traverse(TK_AsIs, varDecl(hasName("var8"),2886                                      hasInitializer(cxxConstructExpr())))));2887 2888  EXPECT_TRUE(matches(2889      Code,2890      traverse(TK_IgnoreUnlessSpelledInSource,2891               varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));2892  EXPECT_TRUE(matches(2893      Code,2894      traverse(TK_IgnoreUnlessSpelledInSource,2895               varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));2896  EXPECT_TRUE(matches(2897      Code,2898      traverse(TK_IgnoreUnlessSpelledInSource,2899               varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));2900  EXPECT_TRUE(matches(2901      Code,2902      traverse(TK_IgnoreUnlessSpelledInSource,2903               varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));2904  EXPECT_TRUE(matches(2905      Code,2906      traverse(TK_IgnoreUnlessSpelledInSource,2907               varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));2908  EXPECT_TRUE(matches(2909      Code,2910      traverse(TK_IgnoreUnlessSpelledInSource,2911               varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));2912  EXPECT_TRUE(matches(2913      Code,2914      traverse(TK_IgnoreUnlessSpelledInSource,2915               varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));2916  EXPECT_TRUE(matches(2917      Code,2918      traverse(TK_IgnoreUnlessSpelledInSource,2919               varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));2920 2921  Code = R"cpp(2922 2923template<typename T>2924struct TemplStruct {2925  TemplStruct() {}2926  ~TemplStruct() {}2927 2928  void outOfLine(T);2929 2930private:2931  T m_t;2932};2933 2934template<typename T>2935void TemplStruct<T>::outOfLine(T)2936{2937 2938}2939 2940template<typename T>2941T timesTwo(T input)2942{2943  return input * 2;2944}2945 2946void instantiate()2947{2948  TemplStruct<int> ti;2949  TemplStruct<double> td;2950  (void)timesTwo<int>(2);2951  (void)timesTwo<double>(2);2952}2953 2954template class TemplStruct<float>;2955 2956extern template class TemplStruct<long>;2957 2958template<> class TemplStruct<bool> {2959  TemplStruct() {}2960  ~TemplStruct() {}2961 2962  void boolSpecializationMethodOnly() {}2963private:2964  bool m_t;2965};2966 2967template float timesTwo(float);2968template<> bool timesTwo<bool>(bool){2969  return true;2970}2971)cpp";2972  {2973    auto M = cxxRecordDecl(hasName("TemplStruct"),2974                           has(fieldDecl(hasType(asString("int")))));2975    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2976    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2977  }2978  {2979    auto M = cxxRecordDecl(hasName("TemplStruct"),2980                           has(fieldDecl(hasType(asString("double")))));2981    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2982    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2983  }2984  {2985    auto M =2986        functionDecl(hasName("timesTwo"),2987                     hasParameter(0, parmVarDecl(hasType(asString("int")))));2988    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2989    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2990  }2991  {2992    auto M =2993        functionDecl(hasName("timesTwo"),2994                     hasParameter(0, parmVarDecl(hasType(asString("double")))));2995    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2996    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2997  }2998  {2999    // Match on the integer literal in the explicit instantiation:3000    auto MDef =3001        functionDecl(hasName("timesTwo"),3002                     hasParameter(0, parmVarDecl(hasType(asString("float")))),3003                     hasDescendant(integerLiteral(equals(2))));3004    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));3005    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));3006 3007    auto MTempl =3008        functionDecl(hasName("timesTwo"),3009                     hasTemplateArgument(0, refersToType(asString("float"))));3010    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MTempl)));3011    // TODO: If we could match on explicit instantiations of function templates,3012    // this would be EXPECT_TRUE. See Sema::ActOnExplicitInstantiation.3013    EXPECT_FALSE(3014        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MTempl)));3015  }3016  {3017    auto M = functionDecl(hasName("timesTwo"),3018                          hasParameter(0, parmVarDecl(hasType(booleanType()))));3019    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3020    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3021  }3022  {3023    // Match on the field within the explicit instantiation:3024    auto MRecord = cxxRecordDecl(hasName("TemplStruct"),3025                                 has(fieldDecl(hasType(asString("float")))));3026    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MRecord)));3027    EXPECT_FALSE(3028        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MRecord)));3029 3030    // Match on the explicit template instantiation itself:3031    auto MTempl = classTemplateSpecializationDecl(3032        hasName("TemplStruct"),3033        hasTemplateArgument(0,3034                            templateArgument(refersToType(asString("float")))));3035    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MTempl)));3036    EXPECT_TRUE(3037        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MTempl)));3038  }3039  {3040    // The template argument is matchable, but the instantiation is not:3041    auto M = classTemplateSpecializationDecl(3042        hasName("TemplStruct"),3043        hasTemplateArgument(0,3044                            templateArgument(refersToType(asString("float")))),3045        has(cxxConstructorDecl(hasName("TemplStruct"))));3046    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3047    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3048  }3049  {3050    // The template argument is matchable, but the instantiation is not:3051    auto M = classTemplateSpecializationDecl(3052        hasName("TemplStruct"),3053        hasTemplateArgument(0,3054                            templateArgument(refersToType(asString("long")))),3055        has(cxxConstructorDecl(hasName("TemplStruct"))));3056    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3057    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3058  }3059  {3060    // Instantiated, out-of-line methods are not matchable.3061    auto M =3062        cxxMethodDecl(hasName("outOfLine"), isDefinition(),3063                      hasParameter(0, parmVarDecl(hasType(asString("float")))));3064    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3065    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3066  }3067  {3068    // Explicit specialization is written in source and it matches:3069    auto M = classTemplateSpecializationDecl(3070        hasName("TemplStruct"),3071        hasTemplateArgument(0, templateArgument(refersToType(booleanType()))),3072        has(cxxConstructorDecl(hasName("TemplStruct"))),3073        has(cxxMethodDecl(hasName("boolSpecializationMethodOnly"))));3074    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3075    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3076  }3077 3078  Code = R"cpp(3079struct B {3080  B(int);3081};3082 3083B func1() { return 42; }3084  )cpp";3085  {3086    auto M = expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit")));3087    EXPECT_TRUE(matchAndVerifyResultTrue(3088        Code, traverse(TK_AsIs, M),3089        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3090    EXPECT_TRUE(matchAndVerifyResultTrue(3091        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3092        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3093  }3094  {3095    auto M = expr(unless(integerLiteral(equals(24)))).bind("intLit");3096    EXPECT_TRUE(matchAndVerifyResultTrue(3097        Code, traverse(TK_AsIs, M),3098        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 6),3099        {"-std=c++11"}));3100 3101    EXPECT_TRUE(matchAndVerifyResultTrue(3102        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3103        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1),3104        {"-std=c++11"}));3105  }3106  {3107    auto M =3108        expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr())));3109    EXPECT_TRUE(matchAndVerifyResultTrue(3110        Code, traverse(TK_AsIs, M),3111        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3112    EXPECT_TRUE(matchAndVerifyResultTrue(3113        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3114        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3115  }3116  {3117    auto M = expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr()));3118    EXPECT_TRUE(matchAndVerifyResultTrue(3119        Code, traverse(TK_AsIs, M),3120        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3121    EXPECT_TRUE(matchAndVerifyResultTrue(3122        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3123        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3124  }3125  {3126    auto M = expr(integerLiteral(equals(42)).bind("intLit"), expr());3127    EXPECT_TRUE(matchAndVerifyResultTrue(3128        Code, traverse(TK_AsIs, M),3129        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3130    EXPECT_TRUE(matchAndVerifyResultTrue(3131        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3132        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3133  }3134  {3135    auto M = expr(optionally(integerLiteral(equals(42)).bind("intLit")));3136    EXPECT_TRUE(matchAndVerifyResultTrue(3137        Code, traverse(TK_AsIs, M),3138        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3139    EXPECT_TRUE(matchAndVerifyResultTrue(3140        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3141        std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3142  }3143  {3144    auto M = expr().bind("allExprs");3145    EXPECT_TRUE(matchAndVerifyResultTrue(3146        Code, traverse(TK_AsIs, M),3147        std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 6),3148        {"-std=c++11"}));3149    EXPECT_TRUE(matchAndVerifyResultTrue(3150        Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3151        std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 1)));3152  }3153 3154  Code = R"cpp(3155void foo()3156{3157    int arr[3];3158    auto &[f, s, t] = arr;3159 3160    f = 42;3161}3162  )cpp";3163  {3164    auto M = bindingDecl(hasName("f"));3165    EXPECT_TRUE(3166        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3167    EXPECT_TRUE(3168        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3169                             true, {"-std=c++17"}));3170  }3171  {3172    auto M = bindingDecl(hasName("f"), has(expr()));3173    EXPECT_TRUE(3174        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3175    EXPECT_FALSE(3176        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3177                             true, {"-std=c++17"}));3178  }3179  {3180    auto M = integerLiteral(hasAncestor(bindingDecl(hasName("f"))));3181    EXPECT_TRUE(3182        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3183    EXPECT_FALSE(3184        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3185                             true, {"-std=c++17"}));3186  }3187  {3188    auto M = declRefExpr(hasAncestor(bindingDecl(hasName("f"))));3189    EXPECT_TRUE(3190        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3191    EXPECT_FALSE(3192        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3193                             true, {"-std=c++17"}));3194  }3195}3196 3197TEST(Traversal, traverseNoImplicit) {3198  StringRef Code = R"cpp(3199struct NonTrivial {3200    NonTrivial() {}3201    NonTrivial(const NonTrivial&) {}3202    NonTrivial& operator=(const NonTrivial&) { return *this; }3203 3204    ~NonTrivial() {}3205};3206 3207struct NoSpecialMethods {3208    NonTrivial nt;3209};3210 3211struct ContainsArray {3212    NonTrivial arr[2];3213    ContainsArray& operator=(const ContainsArray &other) = default;3214};3215 3216void copyIt()3217{3218    NoSpecialMethods nc1;3219    NoSpecialMethods nc2(nc1);3220    nc2 = nc1;3221 3222    ContainsArray ca;3223    ContainsArray ca2;3224    ca2 = ca;3225}3226 3227struct HasCtorInits : NoSpecialMethods, NonTrivial3228{3229  int m_i;3230  NonTrivial m_nt;3231  HasCtorInits() : NoSpecialMethods(), m_i(42) {}3232};3233 3234struct CtorInitsNonTrivial : NonTrivial3235{3236  int m_i;3237  NonTrivial m_nt;3238  CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}3239};3240 3241)cpp";3242  {3243    auto M = cxxRecordDecl(hasName("NoSpecialMethods"),3244                           has(cxxRecordDecl(hasName("NoSpecialMethods"))));3245    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3246    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3247 3248    M = cxxRecordDecl(hasName("NoSpecialMethods"),3249                      has(cxxConstructorDecl(isCopyConstructor())));3250    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3251    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3252 3253    M = cxxRecordDecl(hasName("NoSpecialMethods"),3254                      has(cxxMethodDecl(isCopyAssignmentOperator())));3255    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3256    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3257 3258    M = cxxRecordDecl(hasName("NoSpecialMethods"),3259                      has(cxxConstructorDecl(isDefaultConstructor())));3260    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3261    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3262 3263    M = cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));3264    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3265    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3266 3267    M = cxxRecordDecl(hasName("NoSpecialMethods"),3268                      hasMethod(cxxConstructorDecl(isCopyConstructor())));3269    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3270    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3271 3272    M = cxxRecordDecl(hasName("NoSpecialMethods"),3273                      hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));3274    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3275    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3276 3277    M = cxxRecordDecl(hasName("NoSpecialMethods"),3278                      hasMethod(cxxConstructorDecl(isDefaultConstructor())));3279    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3280    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3281 3282    M = cxxRecordDecl(hasName("NoSpecialMethods"),3283                      hasMethod(cxxDestructorDecl()));3284    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3285    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3286  }3287  {3288    // Because the copy-assignment operator is not spelled in the3289    // source (ie, isImplicit()), we don't match it3290    auto M =3291        cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),3292                            callee(cxxMethodDecl(isCopyAssignmentOperator())));3293    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3294    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3295  }3296  {3297    // Compiler generates a forStmt to copy the array3298    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, forStmt())));3299    EXPECT_FALSE(3300        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, forStmt())));3301  }3302  {3303    // The defaulted method declaration can be matched, but not its3304    // definition, in IgnoreUnlessSpelledInSource mode3305    auto MDecl = cxxMethodDecl(ofClass(cxxRecordDecl(hasName("ContainsArray"))),3306                               isCopyAssignmentOperator(), isDefaulted());3307 3308    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDecl)));3309    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDecl)));3310 3311    auto MDef = cxxMethodDecl(MDecl, has(compoundStmt()));3312 3313    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));3314    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));3315 3316    auto MBody = cxxMethodDecl(MDecl, hasBody(compoundStmt()));3317 3318    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MBody)));3319    EXPECT_FALSE(3320        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MBody)));3321 3322    auto MIsDefn = cxxMethodDecl(MDecl, isDefinition());3323 3324    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MIsDefn)));3325    EXPECT_TRUE(3326        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsDefn)));3327 3328    auto MIsInline = cxxMethodDecl(MDecl, isInline());3329 3330    EXPECT_FALSE(matches(Code, traverse(TK_AsIs, MIsInline)));3331    EXPECT_FALSE(3332        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsInline)));3333 3334    // The parameter of the defaulted method can still be matched.3335    auto MParm =3336        cxxMethodDecl(MDecl, hasParameter(0, parmVarDecl(hasName("other"))));3337 3338    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MParm)));3339    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MParm)));3340  }3341  {3342    auto M =3343        cxxConstructorDecl(hasName("HasCtorInits"),3344                           has(cxxCtorInitializer(forField(hasName("m_i")))));3345    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3346    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3347  }3348  {3349    auto M =3350        cxxConstructorDecl(hasName("HasCtorInits"),3351                           has(cxxCtorInitializer(forField(hasName("m_nt")))));3352    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3353    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3354  }3355  {3356    auto M = cxxConstructorDecl(hasName("HasCtorInits"),3357                                hasAnyConstructorInitializer(cxxCtorInitializer(3358                                    forField(hasName("m_nt")))));3359    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3360    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3361  }3362  {3363    auto M =3364        cxxConstructorDecl(hasName("HasCtorInits"),3365                           forEachConstructorInitializer(3366                               cxxCtorInitializer(forField(hasName("m_nt")))));3367    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3368    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3369  }3370  {3371    auto M = cxxConstructorDecl(3372        hasName("CtorInitsNonTrivial"),3373        has(cxxCtorInitializer(withInitializer(cxxConstructExpr(3374            hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));3375    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3376    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3377  }3378  {3379    auto M = cxxConstructorDecl(3380        hasName("HasCtorInits"),3381        has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(3382            cxxConstructorDecl(hasName("NoSpecialMethods"))))))));3383    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3384    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3385  }3386  {3387    auto M = cxxCtorInitializer(forField(hasName("m_nt")));3388    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3389    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3390  }3391 3392  Code = R"cpp(3393  void rangeFor()3394  {3395    int arr[2];3396    for (auto i : arr)3397    {3398      if (true)3399      {3400      }3401    }3402  }3403  )cpp";3404  {3405    auto M = cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));3406    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3407    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3408  }3409  {3410    auto M =3411        cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));3412    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3413    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3414  }3415  {3416    auto M =3417        cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));3418    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3419    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3420  }3421  {3422    auto M = cxxForRangeStmt(has(declStmt()));3423    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3424    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3425  }3426  {3427    auto M =3428        cxxForRangeStmt(hasLoopVariable(varDecl(hasName("i"))),3429                        hasRangeInit(declRefExpr(to(varDecl(hasName("arr"))))));3430    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3431    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3432  }3433  {3434    auto M = cxxForRangeStmt(unless(hasInitStatement(stmt())));3435    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3436    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3437  }3438  {3439    auto M = cxxForRangeStmt(hasBody(stmt()));3440    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3441    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3442  }3443  {3444    auto M = cxxForRangeStmt(hasDescendant(ifStmt()));3445    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3446    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3447  }3448  {3449    EXPECT_TRUE(matches(3450        Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(3451                                    hasSingleDecl(varDecl(hasName("i")))))))));3452    EXPECT_TRUE(3453        matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,3454                               cxxForRangeStmt(has(varDecl(hasName("i")))))));3455  }3456  {3457    EXPECT_TRUE(matches(3458        Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(hasSingleDecl(3459                                    varDecl(hasInitializer(declRefExpr(3460                                        to(varDecl(hasName("arr")))))))))))));3461    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,3462                                       cxxForRangeStmt(has(declRefExpr(3463                                           to(varDecl(hasName("arr")))))))));3464  }3465  {3466    auto M = cxxForRangeStmt(has(compoundStmt()));3467    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3468    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3469  }3470  {3471    auto M = binaryOperator(hasOperatorName("!="));3472    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3473    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3474  }3475  {3476    auto M = unaryOperator(hasOperatorName("++"));3477    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3478    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3479  }3480  {3481    auto M = declStmt(hasSingleDecl(varDecl(matchesName("__range"))));3482    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3483    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3484  }3485  {3486    auto M = declStmt(hasSingleDecl(varDecl(matchesName("__begin"))));3487    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3488    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3489  }3490  {3491    auto M = declStmt(hasSingleDecl(varDecl(matchesName("__end"))));3492    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3493    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3494  }3495  {3496    auto M = ifStmt(hasParent(compoundStmt(hasParent(cxxForRangeStmt()))));3497    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3498    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3499  }3500  {3501    auto M = cxxForRangeStmt(3502        has(varDecl(hasName("i"), hasParent(cxxForRangeStmt()))));3503    EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));3504    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3505  }3506  {3507    auto M = cxxForRangeStmt(hasDescendant(varDecl(3508        hasName("i"), hasParent(declStmt(hasParent(cxxForRangeStmt()))))));3509    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3510    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3511  }3512  {3513    auto M = cxxForRangeStmt(hasRangeInit(declRefExpr(3514        to(varDecl(hasName("arr"))), hasParent(cxxForRangeStmt()))));3515    EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));3516    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3517  }3518 3519  {3520    auto M = cxxForRangeStmt(hasRangeInit(declRefExpr(3521        to(varDecl(hasName("arr"))), hasParent(varDecl(hasParent(declStmt(3522                                         hasParent(cxxForRangeStmt()))))))));3523    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3524    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3525  }3526 3527  Code = R"cpp(3528  struct Range {3529    int* begin() const;3530    int* end() const;3531  };3532  Range getRange(int);3533 3534  void rangeFor()3535  {3536    for (auto i : getRange(42))3537    {3538    }3539  }3540  )cpp";3541  {3542    auto M = integerLiteral(equals(42));3543    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3544    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3545  }3546  {3547    auto M = callExpr(hasDescendant(integerLiteral(equals(42))));3548    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3549    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3550  }3551  {3552    auto M = compoundStmt(hasDescendant(integerLiteral(equals(42))));3553    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3554    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3555  }3556 3557  Code = R"cpp(3558  void rangeFor()3559  {3560    int arr[2];3561    for (auto& a = arr; auto i : a)3562    {3563 3564    }3565  }3566  )cpp";3567  {3568    auto M = cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));3569    EXPECT_TRUE(3570        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3571    EXPECT_FALSE(3572        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3573                             true, {"-std=c++20"}));3574  }3575  {3576    auto M =3577        cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));3578    EXPECT_TRUE(3579        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3580    EXPECT_FALSE(3581        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3582                             true, {"-std=c++20"}));3583  }3584  {3585    auto M =3586        cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));3587    EXPECT_TRUE(3588        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3589    EXPECT_FALSE(3590        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3591                             true, {"-std=c++20"}));3592  }3593  {3594    auto M =3595        cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i"))))));3596    EXPECT_TRUE(3597        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3598    EXPECT_FALSE(3599        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3600                             true, {"-std=c++20"}));3601  }3602  {3603    auto M = cxxForRangeStmt(3604        hasInitStatement(declStmt(hasSingleDecl(varDecl(3605            hasName("a"),3606            hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),3607        hasLoopVariable(varDecl(hasName("i"))),3608        hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));3609    EXPECT_TRUE(3610        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3611    EXPECT_TRUE(3612        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3613                             true, {"-std=c++20"}));3614  }3615  {3616    auto M = cxxForRangeStmt(3617        has(declStmt(hasSingleDecl(varDecl(3618            hasName("a"),3619            hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),3620        hasLoopVariable(varDecl(hasName("i"))),3621        hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));3622    EXPECT_TRUE(3623        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3624    EXPECT_TRUE(3625        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3626                             true, {"-std=c++20"}));3627  }3628  {3629    auto M = cxxForRangeStmt(hasInitStatement(declStmt(3630        hasSingleDecl(varDecl(hasName("a"))), hasParent(cxxForRangeStmt()))));3631    EXPECT_TRUE(3632        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3633    EXPECT_TRUE(3634        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3635                             true, {"-std=c++20"}));3636  }3637 3638  Code = R"cpp(3639  struct Range {3640    int* begin() const;3641    int* end() const;3642  };3643  Range getRange(int);3644 3645  int getNum(int);3646 3647  void rangeFor()3648  {3649    for (auto j = getNum(42); auto i : getRange(j))3650    {3651    }3652  }3653  )cpp";3654  {3655    auto M = integerLiteral(equals(42));3656    EXPECT_TRUE(3657        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3658    EXPECT_TRUE(3659        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3660                             true, {"-std=c++20"}));3661  }3662  {3663    auto M = compoundStmt(hasDescendant(integerLiteral(equals(42))));3664    EXPECT_TRUE(3665        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3666    EXPECT_TRUE(3667        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3668                             true, {"-std=c++20"}));3669  }3670 3671  Code = R"cpp(3672void hasDefaultArg(int i, int j = 0)3673{3674}3675void callDefaultArg()3676{3677  hasDefaultArg(42);3678}3679)cpp";3680  auto hasDefaultArgCall = [](auto InnerMatcher) {3681    return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),3682                    InnerMatcher);3683  };3684  {3685    auto M = hasDefaultArgCall(has(integerLiteral(equals(42))));3686    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3687    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3688  }3689  {3690    auto M = hasDefaultArgCall(has(cxxDefaultArgExpr()));3691    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3692    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3693  }3694  {3695    auto M = hasDefaultArgCall(argumentCountIs(2));3696    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3697    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3698  }3699  {3700    auto M = hasDefaultArgCall(argumentCountIs(1));3701    EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));3702    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3703  }3704  {3705    auto M = hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));3706    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3707    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3708  }3709  {3710    auto M = hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));3711    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3712    EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3713  }3714  Code = R"cpp(3715struct A3716{3717    ~A();3718private:3719    int i;3720};3721 3722A::~A() = default;3723)cpp";3724  {3725    auto M = cxxDestructorDecl(isDefaulted(),3726                               ofClass(cxxRecordDecl(has(fieldDecl()))));3727    EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3728    EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3729  }3730  Code = R"cpp(3731struct S3732{3733    static constexpr bool getTrue() { return true; }3734};3735 3736struct A3737{3738    explicit(S::getTrue()) A();3739};3740 3741A::A() = default;3742)cpp";3743  {3744    EXPECT_TRUE(matchesConditionally(3745        Code,3746        traverse(TK_AsIs,3747                 cxxConstructorDecl(3748                     isDefaulted(),3749                     hasExplicitSpecifier(expr(ignoringImplicit(3750                         callExpr(has(ignoringImplicit(declRefExpr())))))))),3751        true, {"-std=c++20"}));3752    EXPECT_TRUE(matchesConditionally(3753        Code,3754        traverse(TK_IgnoreUnlessSpelledInSource,3755                 cxxConstructorDecl(3756                     isDefaulted(),3757                     hasExplicitSpecifier(callExpr(has(declRefExpr()))))),3758        true, {"-std=c++20"}));3759  }3760}3761 3762template <typename MatcherT>3763bool matcherTemplateWithBinding(StringRef Code, const MatcherT &M) {3764  return matchAndVerifyResultTrue(3765      Code, M.bind("matchedStmt"),3766      std::make_unique<VerifyIdIsBoundTo<ReturnStmt>>("matchedStmt", 1));3767}3768 3769TEST(Traversal, traverseWithBinding) {3770  // Some existing matcher code expects to take a matcher as a3771  // template arg and bind to it.  Verify that that works.3772 3773  llvm::StringRef Code = R"cpp(3774int foo()3775{3776  return 42.0;3777}3778)cpp";3779  EXPECT_TRUE(matcherTemplateWithBinding(3780      Code, traverse(TK_AsIs,3781                     returnStmt(has(implicitCastExpr(has(floatLiteral())))))));3782}3783 3784TEST(Traversal, traverseMatcherNesting) {3785 3786  StringRef Code = R"cpp(3787float bar(int i)3788{3789  return i;3790}3791 3792void foo()3793{3794  bar(bar(3.0));3795}3796)cpp";3797 3798  EXPECT_TRUE(3799      matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,3800                             callExpr(has(callExpr(traverse(3801                                 TK_AsIs, callExpr(has(implicitCastExpr(3802                                              has(floatLiteral())))))))))));3803 3804  EXPECT_TRUE(matches(3805      Code,3806      traverse(TK_IgnoreUnlessSpelledInSource,3807               traverse(TK_AsIs, implicitCastExpr(has(floatLiteral()))))));3808}3809 3810TEST(Traversal, traverseMatcherThroughImplicit) {3811  StringRef Code = R"cpp(3812struct S {3813  S(int x);3814};3815 3816void constructImplicit() {3817  int a = 8;3818  S s(a);3819}3820  )cpp";3821 3822  auto Matcher = traverse(TK_IgnoreUnlessSpelledInSource, implicitCastExpr());3823 3824  // Verfiy that it does not segfault3825  EXPECT_FALSE(matches(Code, Matcher));3826}3827 3828TEST(Traversal, traverseMatcherThroughMemoization) {3829 3830  StringRef Code = R"cpp(3831void foo()3832{3833  int i = 3.0;3834}3835  )cpp";3836 3837  auto Matcher = varDecl(hasInitializer(floatLiteral()));3838 3839  // Matchers such as hasDescendant memoize their result regarding AST3840  // nodes. In the matcher below, the first use of hasDescendant(Matcher)3841  // fails, and the use of it inside the traverse() matcher should pass3842  // causing the overall matcher to be a true match.3843  // This test verifies that the first false result is not re-used, which3844  // would cause the overall matcher to be incorrectly false.3845 3846  EXPECT_TRUE(matches(3847      Code,3848      functionDecl(anyOf(hasDescendant(Matcher),3849                         traverse(TK_IgnoreUnlessSpelledInSource,3850                                  functionDecl(hasDescendant(Matcher)))))));3851}3852 3853TEST(Traversal, traverseUnlessSpelledInSource) {3854 3855  StringRef Code = R"cpp(3856 3857struct A3858{3859};3860 3861struct B3862{3863  B(int);3864  B(A const& a);3865  B();3866};3867 3868struct C3869{3870  operator B();3871};3872 3873B func1() {3874  return 42;3875}3876 3877B func2() {3878  return B{42};3879}3880 3881B func3() {3882  return B(42);3883}3884 3885B func4() {3886  return B();3887}3888 3889B func5() {3890  return B{};3891}3892 3893B func6() {3894  return C();3895}3896 3897B func7() {3898  return A();3899}3900 3901B func8() {3902  return C{};3903}3904 3905B func9() {3906  return A{};3907}3908 3909B func10() {3910  A a;3911  return a;3912}3913 3914B func11() {3915  B b;3916  return b;3917}3918 3919B func12() {3920  C c;3921  return c;3922}3923 3924void func13() {3925  int a = 0;3926  int c = 0;3927 3928  [a, b = c](int d) { int e = d; };3929}3930 3931void func14() {3932  [] <typename TemplateType> (TemplateType t, TemplateType u) { int e = t + u; };3933  float i = 42.0;3934}3935 3936void func15() {3937  int count = 0;3938  auto l = [&] { ++count; };3939  (void)l;3940}3941 3942)cpp";3943 3944  EXPECT_TRUE(3945      matches(Code,3946              traverse(TK_IgnoreUnlessSpelledInSource,3947                       returnStmt(forFunction(functionDecl(hasName("func1"))),3948                                  hasReturnValue(integerLiteral(equals(42))))),3949              langCxx20OrLater()));3950 3951  EXPECT_TRUE(3952      matches(Code,3953              traverse(TK_IgnoreUnlessSpelledInSource,3954                       integerLiteral(equals(42),3955                                      hasParent(returnStmt(forFunction(3956                                          functionDecl(hasName("func1"))))))),3957              langCxx20OrLater()));3958 3959  EXPECT_TRUE(matches(3960      Code,3961      traverse(TK_IgnoreUnlessSpelledInSource,3962               returnStmt(forFunction(functionDecl(hasName("func2"))),3963                          hasReturnValue(cxxTemporaryObjectExpr(3964                              hasArgument(0, integerLiteral(equals(42))))))),3965      langCxx20OrLater()));3966  EXPECT_TRUE(matches(3967      Code,3968      traverse(3969          TK_IgnoreUnlessSpelledInSource,3970          integerLiteral(equals(42),3971                         hasParent(cxxTemporaryObjectExpr(hasParent(returnStmt(3972                             forFunction(functionDecl(hasName("func2"))))))))),3973      langCxx20OrLater()));3974 3975  EXPECT_TRUE(3976      matches(Code,3977              traverse(TK_IgnoreUnlessSpelledInSource,3978                       returnStmt(forFunction(functionDecl(hasName("func3"))),3979                                  hasReturnValue(cxxConstructExpr(hasArgument(3980                                      0, integerLiteral(equals(42))))))),3981              langCxx20OrLater()));3982 3983  EXPECT_TRUE(matches(3984      Code,3985      traverse(3986          TK_IgnoreUnlessSpelledInSource,3987          integerLiteral(equals(42),3988                         hasParent(cxxConstructExpr(hasParent(returnStmt(3989                             forFunction(functionDecl(hasName("func3"))))))))),3990      langCxx20OrLater()));3991 3992  EXPECT_TRUE(3993      matches(Code,3994              traverse(TK_IgnoreUnlessSpelledInSource,3995                       returnStmt(forFunction(functionDecl(hasName("func4"))),3996                                  hasReturnValue(cxxTemporaryObjectExpr()))),3997              langCxx20OrLater()));3998 3999  EXPECT_TRUE(4000      matches(Code,4001              traverse(TK_IgnoreUnlessSpelledInSource,4002                       returnStmt(forFunction(functionDecl(hasName("func5"))),4003                                  hasReturnValue(cxxTemporaryObjectExpr()))),4004              langCxx20OrLater()));4005 4006  EXPECT_TRUE(4007      matches(Code,4008              traverse(TK_IgnoreUnlessSpelledInSource,4009                       returnStmt(forFunction(functionDecl(hasName("func6"))),4010                                  hasReturnValue(cxxTemporaryObjectExpr()))),4011              langCxx20OrLater()));4012 4013  EXPECT_TRUE(4014      matches(Code,4015              traverse(TK_IgnoreUnlessSpelledInSource,4016                       returnStmt(forFunction(functionDecl(hasName("func7"))),4017                                  hasReturnValue(cxxTemporaryObjectExpr()))),4018              langCxx20OrLater()));4019 4020  EXPECT_TRUE(4021      matches(Code,4022              traverse(TK_IgnoreUnlessSpelledInSource,4023                       returnStmt(forFunction(functionDecl(hasName("func8"))),4024                                  hasReturnValue(cxxFunctionalCastExpr(4025                                      hasSourceExpression(initListExpr()))))),4026              langCxx20OrLater()));4027 4028  EXPECT_TRUE(4029      matches(Code,4030              traverse(TK_IgnoreUnlessSpelledInSource,4031                       returnStmt(forFunction(functionDecl(hasName("func9"))),4032                                  hasReturnValue(cxxFunctionalCastExpr(4033                                      hasSourceExpression(initListExpr()))))),4034              langCxx20OrLater()));4035 4036  EXPECT_TRUE(matches(4037      Code,4038      traverse(4039          TK_IgnoreUnlessSpelledInSource,4040          returnStmt(forFunction(functionDecl(hasName("func10"))),4041                     hasReturnValue(declRefExpr(to(varDecl(hasName("a"))))))),4042      langCxx20OrLater()));4043 4044  EXPECT_TRUE(4045      matches(Code,4046              traverse(TK_IgnoreUnlessSpelledInSource,4047                       declRefExpr(to(varDecl(hasName("a"))),4048                                   hasParent(returnStmt(forFunction(4049                                       functionDecl(hasName("func10"))))))),4050              langCxx20OrLater()));4051 4052  EXPECT_TRUE(matches(4053      Code,4054      traverse(4055          TK_IgnoreUnlessSpelledInSource,4056          returnStmt(forFunction(functionDecl(hasName("func11"))),4057                     hasReturnValue(declRefExpr(to(varDecl(hasName("b"))))))),4058      langCxx20OrLater()));4059 4060  EXPECT_TRUE(4061      matches(Code,4062              traverse(TK_IgnoreUnlessSpelledInSource,4063                       declRefExpr(to(varDecl(hasName("b"))),4064                                   hasParent(returnStmt(forFunction(4065                                       functionDecl(hasName("func11"))))))),4066              langCxx20OrLater()));4067 4068  EXPECT_TRUE(matches(4069      Code,4070      traverse(4071          TK_IgnoreUnlessSpelledInSource,4072          returnStmt(forFunction(functionDecl(hasName("func12"))),4073                     hasReturnValue(declRefExpr(to(varDecl(hasName("c"))))))),4074      langCxx20OrLater()));4075 4076  EXPECT_TRUE(4077      matches(Code,4078              traverse(TK_IgnoreUnlessSpelledInSource,4079                       declRefExpr(to(varDecl(hasName("c"))),4080                                   hasParent(returnStmt(forFunction(4081                                       functionDecl(hasName("func12"))))))),4082              langCxx20OrLater()));4083 4084  EXPECT_TRUE(matches(4085      Code,4086      traverse(4087          TK_IgnoreUnlessSpelledInSource,4088          lambdaExpr(forFunction(functionDecl(hasName("func13"))),4089                     has(compoundStmt(hasDescendant(varDecl(hasName("e"))))),4090                     has(declRefExpr(to(varDecl(hasName("a"))))),4091                     has(varDecl(hasName("b"), hasInitializer(declRefExpr(to(4092                                                   varDecl(hasName("c"))))))),4093                     has(parmVarDecl(hasName("d"))))),4094      langCxx20OrLater()));4095 4096  EXPECT_TRUE(4097      matches(Code,4098              traverse(TK_IgnoreUnlessSpelledInSource,4099                       declRefExpr(to(varDecl(hasName("a"))),4100                                   hasParent(lambdaExpr(forFunction(4101                                       functionDecl(hasName("func13"))))))),4102              langCxx20OrLater()));4103 4104  EXPECT_TRUE(matches(4105      Code,4106      traverse(TK_IgnoreUnlessSpelledInSource,4107               varDecl(hasName("b"),4108                       hasInitializer(declRefExpr(to(varDecl(hasName("c"))))),4109                       hasParent(lambdaExpr(4110                           forFunction(functionDecl(hasName("func13"))))))),4111      langCxx20OrLater()));4112 4113  EXPECT_TRUE(matches(Code,4114                      traverse(TK_IgnoreUnlessSpelledInSource,4115                               compoundStmt(hasParent(lambdaExpr(forFunction(4116                                   functionDecl(hasName("func13"))))))),4117                      langCxx20OrLater()));4118 4119  EXPECT_TRUE(matches(4120      Code,4121      traverse(TK_IgnoreUnlessSpelledInSource,4122               templateTypeParmDecl(hasName("TemplateType"),4123                                    hasParent(lambdaExpr(forFunction(4124                                        functionDecl(hasName("func14"))))))),4125      langCxx20OrLater()));4126 4127  EXPECT_TRUE(matches(4128      Code,4129      traverse(TK_IgnoreUnlessSpelledInSource,4130               lambdaExpr(forFunction(functionDecl(hasName("func14"))),4131                          has(templateTypeParmDecl(hasName("TemplateType"))))),4132      langCxx20OrLater()));4133 4134  EXPECT_TRUE(matches(4135      Code,4136      traverse(TK_IgnoreUnlessSpelledInSource,4137               functionDecl(hasName("func14"), hasDescendant(floatLiteral()))),4138      langCxx20OrLater()));4139 4140  EXPECT_TRUE(matches(4141      Code,4142      traverse(TK_IgnoreUnlessSpelledInSource,4143               compoundStmt(4144                   hasDescendant(varDecl(hasName("count")).bind("countVar")),4145                   hasDescendant(4146                       declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))),4147      langCxx20OrLater()));4148 4149  Code = R"cpp(4150void foo() {4151    int explicit_captured = 0;4152    int implicit_captured = 0;4153    auto l = [&, explicit_captured](int i) {4154        if (i || explicit_captured || implicit_captured) return;4155    };4156}4157)cpp";4158 4159  EXPECT_TRUE(matches(Code, traverse(TK_AsIs, ifStmt())));4160  EXPECT_TRUE(4161      matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, ifStmt())));4162 4163  auto lambdaExplicitCapture = declRefExpr(4164      to(varDecl(hasName("explicit_captured"))), unless(hasAncestor(ifStmt())));4165  auto lambdaImplicitCapture = declRefExpr(4166      to(varDecl(hasName("implicit_captured"))), unless(hasAncestor(ifStmt())));4167 4168  EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaExplicitCapture)));4169  EXPECT_TRUE(matches(4170      Code, traverse(TK_IgnoreUnlessSpelledInSource, lambdaExplicitCapture)));4171 4172  EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaImplicitCapture)));4173  EXPECT_FALSE(matches(4174      Code, traverse(TK_IgnoreUnlessSpelledInSource, lambdaImplicitCapture)));4175 4176  Code = R"cpp(4177struct S {};4178 4179struct HasOpEq4180{4181    bool operator==(const S& other)4182    {4183        return true;4184    }4185};4186 4187void binop()4188{4189    HasOpEq s1;4190    S s2;4191    if (s1 != s2)4192        return;4193}4194)cpp";4195  {4196    auto M = unaryOperator(4197        hasOperatorName("!"),4198        has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="))));4199    EXPECT_TRUE(4200        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4201    EXPECT_FALSE(4202        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4203                             true, {"-std=c++20"}));4204  }4205  {4206    auto M = declRefExpr(to(varDecl(hasName("s1"))));4207    EXPECT_TRUE(4208        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4209    EXPECT_TRUE(4210        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4211                             true, {"-std=c++20"}));4212  }4213  {4214    auto M = cxxOperatorCallExpr(hasOverloadedOperatorName("=="));4215    EXPECT_TRUE(4216        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4217    EXPECT_FALSE(4218        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4219                             true, {"-std=c++20"}));4220  }4221  {4222    auto M = cxxOperatorCallExpr(hasOverloadedOperatorName("!="));4223    EXPECT_FALSE(4224        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4225    EXPECT_FALSE(4226        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4227                             true, {"-std=c++20"}));4228  }4229  auto withDescendants = [](StringRef lName, StringRef rName) {4230    return stmt(hasDescendant(declRefExpr(to(varDecl(hasName(lName))))),4231                hasDescendant(declRefExpr(to(varDecl(hasName(rName))))));4232  };4233  {4234    auto M = cxxRewrittenBinaryOperator(withDescendants("s1", "s2"));4235    EXPECT_TRUE(4236        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4237    EXPECT_TRUE(4238        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4239                             true, {"-std=c++20"}));4240  }4241  {4242    auto M = cxxRewrittenBinaryOperator(4243        has(declRefExpr(to(varDecl(hasName("s1"))))),4244        has(declRefExpr(to(varDecl(hasName("s2"))))));4245    EXPECT_FALSE(4246        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4247    EXPECT_TRUE(4248        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4249                             true, {"-std=c++20"}));4250  }4251  {4252    auto M = cxxRewrittenBinaryOperator(4253        hasLHS(expr(hasParent(cxxRewrittenBinaryOperator()))),4254        hasRHS(expr(hasParent(cxxRewrittenBinaryOperator()))));4255    EXPECT_FALSE(4256        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4257    EXPECT_TRUE(4258        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4259                             true, {"-std=c++20"}));4260  }4261  {4262    EXPECT_TRUE(matchesConditionally(4263        Code,4264        traverse(TK_AsIs,4265                 cxxRewrittenBinaryOperator(4266                     hasOperatorName("!="), hasAnyOperatorName("<", "!="),4267                     isComparisonOperator(),4268                     hasLHS(ignoringImplicit(4269                         declRefExpr(to(varDecl(hasName("s1")))))),4270                     hasRHS(ignoringImplicit(4271                         declRefExpr(to(varDecl(hasName("s2")))))),4272                     hasEitherOperand(ignoringImplicit(4273                         declRefExpr(to(varDecl(hasName("s2")))))),4274                     hasOperands(ignoringImplicit(4275                                     declRefExpr(to(varDecl(hasName("s1"))))),4276                                 ignoringImplicit(declRefExpr(4277                                     to(varDecl(hasName("s2")))))))),4278        true, {"-std=c++20"}));4279    EXPECT_TRUE(matchesConditionally(4280        Code,4281        traverse(TK_IgnoreUnlessSpelledInSource,4282                 cxxRewrittenBinaryOperator(4283                     hasOperatorName("!="), hasAnyOperatorName("<", "!="),4284                     isComparisonOperator(),4285                     hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),4286                     hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),4287                     hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),4288                     hasOperands(declRefExpr(to(varDecl(hasName("s1")))),4289                                 declRefExpr(to(varDecl(hasName("s2"))))))),4290        true, {"-std=c++20"}));4291  }4292 4293  Code = R"cpp(4294namespace std {4295struct strong_ordering {4296  int n;4297  constexpr operator int() const { return n; }4298  static const strong_ordering equal, greater, less;4299};4300constexpr strong_ordering strong_ordering::equal = {0};4301constexpr strong_ordering strong_ordering::greater = {1};4302constexpr strong_ordering strong_ordering::less = {-1};4303}4304 4305struct HasSpaceshipMem {4306  int a;4307  constexpr auto operator<=>(const HasSpaceshipMem&) const = default;4308};4309 4310void binop()4311{4312    HasSpaceshipMem hs1, hs2;4313    if (hs1 == hs2)4314        return;4315 4316    HasSpaceshipMem hs3, hs4;4317    if (hs3 != hs4)4318        return;4319 4320    HasSpaceshipMem hs5, hs6;4321    if (hs5 < hs6)4322        return;4323 4324    HasSpaceshipMem hs7, hs8;4325    if (hs7 > hs8)4326        return;4327 4328    HasSpaceshipMem hs9, hs10;4329    if (hs9 <= hs10)4330        return;4331 4332    HasSpaceshipMem hs11, hs12;4333    if (hs11 >= hs12)4334        return;4335}4336)cpp";4337  auto withArgs = [](StringRef lName, StringRef rName) {4338    return cxxOperatorCallExpr(4339        hasArgument(0, declRefExpr(to(varDecl(hasName(lName))))),4340        hasArgument(1, declRefExpr(to(varDecl(hasName(rName))))));4341  };4342  {4343    auto M = ifStmt(hasCondition(cxxOperatorCallExpr(4344        hasOverloadedOperatorName("=="), withArgs("hs1", "hs2"))));4345    EXPECT_TRUE(4346        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4347    EXPECT_TRUE(4348        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4349                             true, {"-std=c++20"}));4350  }4351  {4352    auto M =4353        unaryOperator(hasOperatorName("!"),4354                      has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),4355                                              withArgs("hs3", "hs4"))));4356    EXPECT_TRUE(4357        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4358    EXPECT_FALSE(4359        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4360                             true, {"-std=c++20"}));4361  }4362  {4363    auto M =4364        unaryOperator(hasOperatorName("!"),4365                      has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),4366                                              withArgs("hs3", "hs4"))));4367    EXPECT_TRUE(4368        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4369    EXPECT_FALSE(4370        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4371                             true, {"-std=c++20"}));4372  }4373  {4374    auto M = binaryOperator(4375        hasOperatorName("<"),4376        hasLHS(hasDescendant(cxxOperatorCallExpr(4377            hasOverloadedOperatorName("<=>"), withArgs("hs5", "hs6")))),4378        hasRHS(integerLiteral(equals(0))));4379    EXPECT_TRUE(4380        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4381    EXPECT_FALSE(4382        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4383                             true, {"-std=c++20"}));4384  }4385  {4386    auto M = cxxRewrittenBinaryOperator(withDescendants("hs3", "hs4"));4387    EXPECT_TRUE(4388        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4389    EXPECT_TRUE(4390        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4391                             true, {"-std=c++20"}));4392  }4393  {4394    auto M = declRefExpr(to(varDecl(hasName("hs3"))));4395    EXPECT_TRUE(4396        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4397    EXPECT_TRUE(4398        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4399                             true, {"-std=c++20"}));4400  }4401  {4402    auto M = cxxRewrittenBinaryOperator(has(4403        unaryOperator(hasOperatorName("!"), withDescendants("hs3", "hs4"))));4404    EXPECT_TRUE(4405        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4406    EXPECT_FALSE(4407        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4408                             true, {"-std=c++20"}));4409  }4410  {4411    auto M = cxxRewrittenBinaryOperator(4412        has(declRefExpr(to(varDecl(hasName("hs3"))))),4413        has(declRefExpr(to(varDecl(hasName("hs4"))))));4414    EXPECT_FALSE(4415        matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4416    EXPECT_TRUE(4417        matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4418                             true, {"-std=c++20"}));4419  }4420  {4421    EXPECT_TRUE(matchesConditionally(4422        Code,4423        traverse(TK_AsIs,4424                 cxxRewrittenBinaryOperator(4425                     hasOperatorName("!="), hasAnyOperatorName("<", "!="),4426                     isComparisonOperator(),4427                     hasLHS(ignoringImplicit(4428                         declRefExpr(to(varDecl(hasName("hs3")))))),4429                     hasRHS(ignoringImplicit(4430                         declRefExpr(to(varDecl(hasName("hs4")))))),4431                     hasEitherOperand(ignoringImplicit(4432                         declRefExpr(to(varDecl(hasName("hs3")))))),4433                     hasOperands(ignoringImplicit(4434                                     declRefExpr(to(varDecl(hasName("hs3"))))),4435                                 ignoringImplicit(declRefExpr(4436                                     to(varDecl(hasName("hs4")))))))),4437        true, {"-std=c++20"}));4438    EXPECT_TRUE(matchesConditionally(4439        Code,4440        traverse(TK_IgnoreUnlessSpelledInSource,4441                 cxxRewrittenBinaryOperator(4442                     hasOperatorName("!="), hasAnyOperatorName("<", "!="),4443                     isComparisonOperator(),4444                     hasLHS(declRefExpr(to(varDecl(hasName("hs3"))))),4445                     hasRHS(declRefExpr(to(varDecl(hasName("hs4"))))),4446                     hasEitherOperand(declRefExpr(to(varDecl(hasName("hs3"))))),4447                     hasOperands(declRefExpr(to(varDecl(hasName("hs3")))),4448                                 declRefExpr(to(varDecl(hasName("hs4"))))))),4449        true, {"-std=c++20"}));4450  }4451  {4452    EXPECT_TRUE(matchesConditionally(4453        Code,4454        traverse(TK_AsIs,4455                 cxxRewrittenBinaryOperator(4456                     hasOperatorName("<"), hasAnyOperatorName("<", "!="),4457                     isComparisonOperator(),4458                     hasLHS(ignoringImplicit(4459                         declRefExpr(to(varDecl(hasName("hs5")))))),4460                     hasRHS(ignoringImplicit(4461                         declRefExpr(to(varDecl(hasName("hs6")))))),4462                     hasEitherOperand(ignoringImplicit(4463                         declRefExpr(to(varDecl(hasName("hs5")))))),4464                     hasOperands(ignoringImplicit(4465                                     declRefExpr(to(varDecl(hasName("hs5"))))),4466                                 ignoringImplicit(declRefExpr(4467                                     to(varDecl(hasName("hs6")))))))),4468        true, {"-std=c++20"}));4469    EXPECT_TRUE(matchesConditionally(4470        Code,4471        traverse(TK_IgnoreUnlessSpelledInSource,4472                 cxxRewrittenBinaryOperator(4473                     hasOperatorName("<"), hasAnyOperatorName("<", "!="),4474                     isComparisonOperator(),4475                     hasLHS(declRefExpr(to(varDecl(hasName("hs5"))))),4476                     hasRHS(declRefExpr(to(varDecl(hasName("hs6"))))),4477                     hasEitherOperand(declRefExpr(to(varDecl(hasName("hs5"))))),4478                     hasOperands(declRefExpr(to(varDecl(hasName("hs5")))),4479                                 declRefExpr(to(varDecl(hasName("hs6"))))))),4480        true, {"-std=c++20"}));4481  }4482  {4483    EXPECT_TRUE(matchesConditionally(4484        Code,4485        traverse(TK_AsIs,4486                 cxxRewrittenBinaryOperator(4487                     hasOperatorName(">"), hasAnyOperatorName("<", ">"),4488                     isComparisonOperator(),4489                     hasLHS(ignoringImplicit(4490                         declRefExpr(to(varDecl(hasName("hs7")))))),4491                     hasRHS(ignoringImplicit(4492                         declRefExpr(to(varDecl(hasName("hs8")))))),4493                     hasEitherOperand(ignoringImplicit(4494                         declRefExpr(to(varDecl(hasName("hs7")))))),4495                     hasOperands(ignoringImplicit(4496                                     declRefExpr(to(varDecl(hasName("hs7"))))),4497                                 ignoringImplicit(declRefExpr(4498                                     to(varDecl(hasName("hs8")))))))),4499        true, {"-std=c++20"}));4500    EXPECT_TRUE(matchesConditionally(4501        Code,4502        traverse(TK_IgnoreUnlessSpelledInSource,4503                 cxxRewrittenBinaryOperator(4504                     hasOperatorName(">"), hasAnyOperatorName("<", ">"),4505                     isComparisonOperator(),4506                     hasLHS(declRefExpr(to(varDecl(hasName("hs7"))))),4507                     hasRHS(declRefExpr(to(varDecl(hasName("hs8"))))),4508                     hasEitherOperand(declRefExpr(to(varDecl(hasName("hs7"))))),4509                     hasOperands(declRefExpr(to(varDecl(hasName("hs7")))),4510                                 declRefExpr(to(varDecl(hasName("hs8"))))))),4511        true, {"-std=c++20"}));4512  }4513  {4514    EXPECT_TRUE(matchesConditionally(4515        Code,4516        traverse(TK_AsIs,4517                 cxxRewrittenBinaryOperator(4518                     hasOperatorName("<="), hasAnyOperatorName("<", "<="),4519                     isComparisonOperator(),4520                     hasLHS(ignoringImplicit(4521                         declRefExpr(to(varDecl(hasName("hs9")))))),4522                     hasRHS(ignoringImplicit(4523                         declRefExpr(to(varDecl(hasName("hs10")))))),4524                     hasEitherOperand(ignoringImplicit(4525                         declRefExpr(to(varDecl(hasName("hs9")))))),4526                     hasOperands(ignoringImplicit(4527                                     declRefExpr(to(varDecl(hasName("hs9"))))),4528                                 ignoringImplicit(declRefExpr(4529                                     to(varDecl(hasName("hs10")))))))),4530        true, {"-std=c++20"}));4531    EXPECT_TRUE(matchesConditionally(4532        Code,4533        traverse(TK_IgnoreUnlessSpelledInSource,4534                 cxxRewrittenBinaryOperator(4535                     hasOperatorName("<="), hasAnyOperatorName("<", "<="),4536                     isComparisonOperator(),4537                     hasLHS(declRefExpr(to(varDecl(hasName("hs9"))))),4538                     hasRHS(declRefExpr(to(varDecl(hasName("hs10"))))),4539                     hasEitherOperand(declRefExpr(to(varDecl(hasName("hs9"))))),4540                     hasOperands(declRefExpr(to(varDecl(hasName("hs9")))),4541                                 declRefExpr(to(varDecl(hasName("hs10"))))))),4542        true, {"-std=c++20"}));4543  }4544  {4545    EXPECT_TRUE(matchesConditionally(4546        Code,4547        traverse(TK_AsIs,4548                 cxxRewrittenBinaryOperator(4549                     hasOperatorName(">="), hasAnyOperatorName("<", ">="),4550                     isComparisonOperator(),4551                     hasLHS(ignoringImplicit(4552                         declRefExpr(to(varDecl(hasName("hs11")))))),4553                     hasRHS(ignoringImplicit(4554                         declRefExpr(to(varDecl(hasName("hs12")))))),4555                     hasEitherOperand(ignoringImplicit(4556                         declRefExpr(to(varDecl(hasName("hs11")))))),4557                     hasOperands(ignoringImplicit(4558                                     declRefExpr(to(varDecl(hasName("hs11"))))),4559                                 ignoringImplicit(declRefExpr(4560                                     to(varDecl(hasName("hs12")))))))),4561        true, {"-std=c++20"}));4562    EXPECT_TRUE(matchesConditionally(4563        Code,4564        traverse(4565            TK_IgnoreUnlessSpelledInSource,4566            cxxRewrittenBinaryOperator(4567                hasOperatorName(">="), hasAnyOperatorName("<", ">="),4568                isComparisonOperator(),4569                hasLHS(declRefExpr(to(varDecl(hasName("hs11"))))),4570                hasRHS(declRefExpr(to(varDecl(hasName("hs12"))))),4571                hasEitherOperand(declRefExpr(to(varDecl(hasName("hs11"))))),4572                hasOperands(declRefExpr(to(varDecl(hasName("hs11")))),4573                            declRefExpr(to(varDecl(hasName("hs12"))))))),4574        true, {"-std=c++20"}));4575  }4576 4577  Code = R"cpp(4578struct S {};4579 4580struct HasOpEq4581{4582    bool operator==(const S& other) const4583    {4584        return true;4585    }4586};4587 4588struct HasOpEqMem {4589  bool operator==(const HasOpEqMem&) const { return true; }4590};4591 4592struct HasOpEqFree {4593};4594bool operator==(const HasOpEqFree&, const HasOpEqFree&) { return true; }4595 4596void binop()4597{4598    {4599    HasOpEq s1;4600    S s2;4601    if (s1 != s2)4602        return;4603    }4604 4605    {4606      int i1;4607      int i2;4608      if (i1 != i2)4609          return;4610    }4611 4612    {4613      HasOpEqMem M1;4614      HasOpEqMem M2;4615      if (M1 == M2)4616          return;4617    }4618 4619    {4620      HasOpEqFree F1;4621      HasOpEqFree F2;4622      if (F1 == F2)4623          return;4624    }4625}4626)cpp";4627  {4628    EXPECT_TRUE(matchesConditionally(4629        Code,4630        traverse(TK_AsIs,4631                 binaryOperation(4632                     hasOperatorName("!="), hasAnyOperatorName("<", "!="),4633                     isComparisonOperator(),4634                     hasLHS(ignoringImplicit(4635                         declRefExpr(to(varDecl(hasName("s1")))))),4636                     hasRHS(ignoringImplicit(4637                         declRefExpr(to(varDecl(hasName("s2")))))),4638                     hasEitherOperand(ignoringImplicit(4639                         declRefExpr(to(varDecl(hasName("s2")))))),4640                     hasOperands(ignoringImplicit(4641                                     declRefExpr(to(varDecl(hasName("s1"))))),4642                                 ignoringImplicit(declRefExpr(4643                                     to(varDecl(hasName("s2")))))))),4644        true, {"-std=c++20"}));4645    EXPECT_TRUE(matchesConditionally(4646        Code,4647        traverse(TK_AsIs, binaryOperation(hasOperatorName("!="),4648                                          hasLHS(ignoringImplicit(declRefExpr(4649                                              to(varDecl(hasName("i1")))))),4650                                          hasRHS(ignoringImplicit(declRefExpr(4651                                              to(varDecl(hasName("i2")))))))),4652        true, {"-std=c++20"}));4653    EXPECT_TRUE(matchesConditionally(4654        Code,4655        traverse(TK_AsIs, binaryOperation(hasOperatorName("=="),4656                                          hasLHS(ignoringImplicit(declRefExpr(4657                                              to(varDecl(hasName("M1")))))),4658                                          hasRHS(ignoringImplicit(declRefExpr(4659                                              to(varDecl(hasName("M2")))))))),4660        true, {"-std=c++20"}));4661    EXPECT_TRUE(matchesConditionally(4662        Code,4663        traverse(TK_AsIs, binaryOperation(hasOperatorName("=="),4664                                          hasLHS(ignoringImplicit(declRefExpr(4665                                              to(varDecl(hasName("F1")))))),4666                                          hasRHS(ignoringImplicit(declRefExpr(4667                                              to(varDecl(hasName("F2")))))))),4668        true, {"-std=c++20"}));4669    EXPECT_TRUE(matchesConditionally(4670        Code,4671        traverse(TK_IgnoreUnlessSpelledInSource,4672                 binaryOperation(4673                     hasOperatorName("!="), hasAnyOperatorName("<", "!="),4674                     isComparisonOperator(),4675                     hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),4676                     hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),4677                     hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),4678                     hasOperands(declRefExpr(to(varDecl(hasName("s1")))),4679                                 declRefExpr(to(varDecl(hasName("s2"))))))),4680        true, {"-std=c++20"}));4681    EXPECT_TRUE(matchesConditionally(4682        Code,4683        traverse(4684            TK_IgnoreUnlessSpelledInSource,4685            binaryOperation(hasOperatorName("!="),4686                            hasLHS(declRefExpr(to(varDecl(hasName("i1"))))),4687                            hasRHS(declRefExpr(to(varDecl(hasName("i2"))))))),4688        true, {"-std=c++20"}));4689    EXPECT_TRUE(matchesConditionally(4690        Code,4691        traverse(4692            TK_IgnoreUnlessSpelledInSource,4693            binaryOperation(hasOperatorName("=="),4694                            hasLHS(declRefExpr(to(varDecl(hasName("M1"))))),4695                            hasRHS(declRefExpr(to(varDecl(hasName("M2"))))))),4696        true, {"-std=c++20"}));4697    EXPECT_TRUE(matchesConditionally(4698        Code,4699        traverse(4700            TK_IgnoreUnlessSpelledInSource,4701            binaryOperation(hasOperatorName("=="),4702                            hasLHS(declRefExpr(to(varDecl(hasName("F1"))))),4703                            hasRHS(declRefExpr(to(varDecl(hasName("F2"))))))),4704        true, {"-std=c++20"}));4705  }4706}4707 4708TEST(IgnoringImpCasts, PathologicalLambda) {4709 4710  // Test that deeply nested lambdas are not a performance penalty4711  StringRef Code = R"cpp(4712void f() {4713  [] {4714  [] {4715  [] {4716  [] {4717  [] {4718  [] {4719  [] {4720  [] {4721  [] {4722  [] {4723  [] {4724  [] {4725  [] {4726  [] {4727  [] {4728  [] {4729  [] {4730  [] {4731  [] {4732  [] {4733  [] {4734  [] {4735  [] {4736  [] {4737  [] {4738  [] {4739  [] {4740  [] {4741  [] {4742    int i = 42;4743    (void)i;4744  }();4745  }();4746  }();4747  }();4748  }();4749  }();4750  }();4751  }();4752  }();4753  }();4754  }();4755  }();4756  }();4757  }();4758  }();4759  }();4760  }();4761  }();4762  }();4763  }();4764  }();4765  }();4766  }();4767  }();4768  }();4769  }();4770  }();4771  }();4772  }();4773}4774  )cpp";4775 4776  EXPECT_TRUE(matches(Code, integerLiteral(equals(42))));4777  EXPECT_TRUE(matches(Code, functionDecl(hasDescendant(integerLiteral(equals(42))))));4778}4779 4780TEST(IgnoringImpCasts, MatchesImpCasts) {4781  // This test checks that ignoringImpCasts matches when implicit casts are4782  // present and its inner matcher alone does not match.4783  // Note that this test creates an implicit const cast.4784  EXPECT_TRUE(matches("int x = 0; const int y = x;",4785                      varDecl(hasInitializer(ignoringImpCasts(4786                        declRefExpr(to(varDecl(hasName("x")))))))));4787  // This test creates an implict cast from int to char.4788  EXPECT_TRUE(matches("char x = 0;",4789                      varDecl(hasInitializer(ignoringImpCasts(4790                        integerLiteral(equals(0)))))));4791}4792 4793TEST(IgnoringImpCasts, DoesNotMatchIncorrectly) {4794  // These tests verify that ignoringImpCasts does not match if the inner4795  // matcher does not match.4796  // Note that the first test creates an implicit const cast.4797  EXPECT_TRUE(notMatches("int x; const int y = x;",4798                         varDecl(hasInitializer(ignoringImpCasts(4799                           unless(anything()))))));4800  EXPECT_TRUE(notMatches("int x; int y = x;",4801                         varDecl(hasInitializer(ignoringImpCasts(4802                           unless(anything()))))));4803 4804  // These tests verify that ignoringImplictCasts does not look through explicit4805  // casts or parentheses.4806  EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",4807                         varDecl(hasInitializer(ignoringImpCasts(4808                           integerLiteral())))));4809  EXPECT_TRUE(notMatches(4810      "int i = (0);",4811      traverse(TK_AsIs,4812               varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))))));4813  EXPECT_TRUE(notMatches("float i = (float)0;",4814                         varDecl(hasInitializer(ignoringImpCasts(4815                           integerLiteral())))));4816  EXPECT_TRUE(notMatches("float i = float(0);",4817                         varDecl(hasInitializer(ignoringImpCasts(4818                           integerLiteral())))));4819}4820 4821TEST(IgnoringImpCasts, MatchesWithoutImpCasts) {4822  // This test verifies that expressions that do not have implicit casts4823  // still match the inner matcher.4824  EXPECT_TRUE(matches("int x = 0; int &y = x;",4825                      varDecl(hasInitializer(ignoringImpCasts(4826                        declRefExpr(to(varDecl(hasName("x")))))))));4827}4828 4829TEST(IgnoringParenCasts, MatchesParenCasts) {4830  // This test checks that ignoringParenCasts matches when parentheses and/or4831  // casts are present and its inner matcher alone does not match.4832  EXPECT_TRUE(matches("int x = (0);",4833                      varDecl(hasInitializer(ignoringParenCasts(4834                        integerLiteral(equals(0)))))));4835  EXPECT_TRUE(matches("int x = (((((0)))));",4836                      varDecl(hasInitializer(ignoringParenCasts(4837                        integerLiteral(equals(0)))))));4838 4839  // This test creates an implict cast from int to char in addition to the4840  // parentheses.4841  EXPECT_TRUE(matches("char x = (0);",4842                      varDecl(hasInitializer(ignoringParenCasts(4843                        integerLiteral(equals(0)))))));4844 4845  EXPECT_TRUE(matches("char x = (char)0;",4846                      varDecl(hasInitializer(ignoringParenCasts(4847                        integerLiteral(equals(0)))))));4848  EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",4849                      varDecl(hasInitializer(ignoringParenCasts(4850                        integerLiteral(equals(0)))))));4851}4852 4853TEST(IgnoringParenCasts, MatchesWithoutParenCasts) {4854  // This test verifies that expressions that do not have any casts still match.4855  EXPECT_TRUE(matches("int x = 0;",4856                      varDecl(hasInitializer(ignoringParenCasts(4857                        integerLiteral(equals(0)))))));4858}4859 4860TEST(IgnoringParenCasts, DoesNotMatchIncorrectly) {4861  // These tests verify that ignoringImpCasts does not match if the inner4862  // matcher does not match.4863  EXPECT_TRUE(notMatches("int x = ((0));",4864                         varDecl(hasInitializer(ignoringParenCasts(4865                           unless(anything()))))));4866 4867  // This test creates an implicit cast from int to char in addition to the4868  // parentheses.4869  EXPECT_TRUE(notMatches("char x = ((0));",4870                         varDecl(hasInitializer(ignoringParenCasts(4871                           unless(anything()))))));4872 4873  EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",4874                         varDecl(hasInitializer(ignoringParenCasts(4875                           unless(anything()))))));4876}4877 4878TEST(IgnoringParenAndImpCasts, MatchesParenImpCasts) {4879  // This test checks that ignoringParenAndImpCasts matches when4880  // parentheses and/or implicit casts are present and its inner matcher alone4881  // does not match.4882  // Note that this test creates an implicit const cast.4883  EXPECT_TRUE(matches("int x = 0; const int y = x;",4884                      varDecl(hasInitializer(ignoringParenImpCasts(4885                        declRefExpr(to(varDecl(hasName("x")))))))));4886  // This test creates an implicit cast from int to char.4887  EXPECT_TRUE(matches("const char x = (0);",4888                      varDecl(hasInitializer(ignoringParenImpCasts(4889                        integerLiteral(equals(0)))))));4890}4891 4892TEST(IgnoringParenAndImpCasts, MatchesWithoutParenImpCasts) {4893  // This test verifies that expressions that do not have parentheses or4894  // implicit casts still match.4895  EXPECT_TRUE(matches("int x = 0; int &y = x;",4896                      varDecl(hasInitializer(ignoringParenImpCasts(4897                        declRefExpr(to(varDecl(hasName("x")))))))));4898  EXPECT_TRUE(matches("int x = 0;",4899                      varDecl(hasInitializer(ignoringParenImpCasts(4900                        integerLiteral(equals(0)))))));4901}4902 4903TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {4904  // These tests verify that ignoringParenImpCasts does not match if4905  // the inner matcher does not match.4906  // This test creates an implicit cast.4907  EXPECT_TRUE(notMatches("char c = ((3));",4908                         varDecl(hasInitializer(ignoringParenImpCasts(4909                           unless(anything()))))));4910  // These tests verify that ignoringParenAndImplictCasts does not look4911  // through explicit casts.4912  EXPECT_TRUE(notMatches("float y = (float(0));",4913                         varDecl(hasInitializer(ignoringParenImpCasts(4914                           integerLiteral())))));4915  EXPECT_TRUE(notMatches("float y = (float)0;",4916                         varDecl(hasInitializer(ignoringParenImpCasts(4917                           integerLiteral())))));4918  EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",4919                         varDecl(hasInitializer(ignoringParenImpCasts(4920                           integerLiteral())))));4921}4922 4923TEST(HasSourceExpression, MatchesImplicitCasts) {4924  EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"4925                      "void r() {string a_string; URL url = a_string; }",4926                      traverse(TK_AsIs, implicitCastExpr(hasSourceExpression(4927                                            cxxConstructExpr())))));4928}4929 4930TEST(HasSourceExpression, MatchesExplicitCasts) {4931  EXPECT_TRUE(4932      matches("float x = static_cast<float>(42);",4933              traverse(TK_AsIs, explicitCastExpr(hasSourceExpression(4934                                    hasDescendant(expr(integerLiteral())))))));4935}4936 4937TEST(UsingDeclaration, MatchesSpecificTarget) {4938  EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",4939                      usingDecl(hasAnyUsingShadowDecl(4940                        hasTargetDecl(functionDecl())))));4941  EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",4942                         usingDecl(hasAnyUsingShadowDecl(4943                           hasTargetDecl(functionDecl())))));4944}4945 4946TEST(UsingDeclaration, ThroughUsingDeclaration) {4947  EXPECT_TRUE(matches(4948    "namespace a { void f(); } using a::f; void g() { f(); }",4949    declRefExpr(throughUsingDecl(anything()))));4950  EXPECT_TRUE(notMatches(4951    "namespace a { void f(); } using a::f; void g() { a::f(); }",4952    declRefExpr(throughUsingDecl(anything()))));4953}4954 4955TEST(SingleDecl, IsSingleDecl) {4956  StatementMatcher SingleDeclStmt =4957    declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));4958  EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt));4959  EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt));4960  EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",4961                         SingleDeclStmt));4962}4963 4964TEST(DeclStmt, ContainsDeclaration) {4965  DeclarationMatcher MatchesInit = varDecl(hasInitializer(anything()));4966 4967  EXPECT_TRUE(matches("void f() {int a = 4;}",4968                      declStmt(containsDeclaration(0, MatchesInit))));4969  EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",4970                      declStmt(containsDeclaration(0, MatchesInit),4971                               containsDeclaration(1, MatchesInit))));4972  unsigned WrongIndex = 42;4973  EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",4974                         declStmt(containsDeclaration(WrongIndex,4975                                                      MatchesInit))));4976}4977 4978TEST(SwitchCase, MatchesEachCase) {4979  EXPECT_TRUE(notMatches("void x() { switch(42); }",4980                         switchStmt(forEachSwitchCase(caseStmt()))));4981  EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",4982                      switchStmt(forEachSwitchCase(caseStmt()))));4983  EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",4984                      switchStmt(forEachSwitchCase(caseStmt()))));4985  EXPECT_TRUE(notMatches(4986    "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",4987    ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));4988  EXPECT_TRUE(matches(4989      "void x() { switch(42) { case 1+1: case 4:; } }",4990      traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(4991                            constantExpr(has(integerLiteral())))))))));4992  EXPECT_TRUE(notMatches(4993      "void x() { switch(42) { case 1+1: case 2+2:; } }",4994      traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(4995                            constantExpr(has(integerLiteral())))))))));4996  EXPECT_TRUE(notMatches(4997      "void x() { switch(42) { case 1 ... 2:; } }",4998      traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(4999                            constantExpr(has(integerLiteral())))))))));5000  EXPECT_TRUE(matchAndVerifyResultTrue(5001    "void x() { switch (42) { case 1: case 2: case 3: default:; } }",5002    switchStmt(forEachSwitchCase(caseStmt().bind("x"))),5003    std::make_unique<VerifyIdIsBoundTo<CaseStmt>>("x", 3)));5004}5005 5006TEST(Declaration, HasExplicitSpecifier) {5007 5008  EXPECT_TRUE(notMatches("void f();",5009                         functionDecl(hasExplicitSpecifier(constantExpr())),5010                         langCxx20OrLater()));5011  EXPECT_TRUE(5012      notMatches("template<bool b> struct S { explicit operator int(); };",5013                 cxxConversionDecl(5014                     hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),5015                 langCxx20OrLater()));5016  EXPECT_TRUE(5017      notMatches("template<bool b> struct S { explicit(b) operator int(); };",5018                 cxxConversionDecl(5019                     hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),5020                 langCxx20OrLater()));5021  EXPECT_TRUE(5022      matches("struct S { explicit(true) operator int(); };",5023              traverse(TK_AsIs, cxxConversionDecl(hasExplicitSpecifier(5024                                    constantExpr(has(cxxBoolLiteral()))))),5025              langCxx20OrLater()));5026  EXPECT_TRUE(5027      matches("struct S { explicit(false) operator int(); };",5028              traverse(TK_AsIs, cxxConversionDecl(hasExplicitSpecifier(5029                                    constantExpr(has(cxxBoolLiteral()))))),5030              langCxx20OrLater()));5031  EXPECT_TRUE(5032      notMatches("template<bool b> struct S { explicit(b) S(int); };",5033                 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(5034                                       constantExpr(has(cxxBoolLiteral()))))),5035                 langCxx20OrLater()));5036  EXPECT_TRUE(5037      matches("struct S { explicit(true) S(int); };",5038              traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(5039                                    constantExpr(has(cxxBoolLiteral()))))),5040              langCxx20OrLater()));5041  EXPECT_TRUE(5042      matches("struct S { explicit(false) S(int); };",5043              traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(5044                                    constantExpr(has(cxxBoolLiteral()))))),5045              langCxx20OrLater()));5046  EXPECT_TRUE(5047      notMatches("template<typename T> struct S { S(int); };"5048                 "template<bool b = true> explicit(b) S(int) -> S<int>;",5049                 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(5050                                       constantExpr(has(cxxBoolLiteral()))))),5051                 langCxx20OrLater()));5052  EXPECT_TRUE(5053      matches("template<typename T> struct S { S(int); };"5054              "explicit(true) S(int) -> S<int>;",5055              traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(5056                                    constantExpr(has(cxxBoolLiteral()))))),5057              langCxx20OrLater()));5058  EXPECT_TRUE(5059      matches("template<typename T> struct S { S(int); };"5060              "explicit(false) S(int) -> S<int>;",5061              traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(5062                                    constantExpr(has(cxxBoolLiteral()))))),5063              langCxx20OrLater()));5064}5065 5066TEST(ForEachConstructorInitializer, MatchesInitializers) {5067  EXPECT_TRUE(matches(5068    "struct X { X() : i(42), j(42) {} int i, j; };",5069    cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));5070}5071 5072TEST(LambdaCapture, InvalidLambdaCapture) {5073  // not crash5074  EXPECT_FALSE(matches(5075      R"(int main() {5076        struct A { A()=default; A(A const&)=delete; };5077        A a; [a]() -> void {}();5078        return 0;5079      })",5080      traverse(TK_IgnoreUnlessSpelledInSource,5081               lambdaExpr(has(lambdaCapture()))),5082      langCxx11OrLater()));5083}5084 5085TEST(ForEachLambdaCapture, MatchesCaptures) {5086  EXPECT_TRUE(matches(5087      "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",5088      lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));5089  auto matcher = lambdaExpr(forEachLambdaCapture(5090      lambdaCapture(capturesVar(varDecl(hasType(isInteger())))).bind("LC")));5091  EXPECT_TRUE(matchAndVerifyResultTrue(5092      "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",5093      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5094  EXPECT_TRUE(matchAndVerifyResultTrue(5095      "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "5096      "z; }; }",5097      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5098}5099 5100TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) {5101  auto matcher =5102      traverse(TK_IgnoreUnlessSpelledInSource,5103               lambdaExpr(forEachLambdaCapture(5104                   lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))5105                       .bind("LC"))));5106  EXPECT_TRUE(5107      notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",5108                 matcher, langCxx11OrLater()));5109  EXPECT_TRUE(5110      notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",5111                 matcher, langCxx11OrLater()));5112  EXPECT_TRUE(matchAndVerifyResultTrue(5113      R"cc(5114      int main() {5115        int x, y;5116        float z;5117        auto f = [=, &y]() { return x + y + z; };5118      }5119      )cc",5120      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));5121}5122 5123TEST(ForEachLambdaCapture, MatchImplicitCapturesOnly) {5124  auto matcher =5125      lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));5126  EXPECT_TRUE(matchAndVerifyResultTrue(5127      "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",5128      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5129  EXPECT_TRUE(matchAndVerifyResultTrue(5130      "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",5131      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5132}5133 5134TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) {5135  auto matcher = lambdaExpr(5136      forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));5137  EXPECT_TRUE(matchAndVerifyResultTrue(5138      "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",5139      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));5140  EXPECT_TRUE(matchAndVerifyResultTrue(5141      "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",5142      matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));5143}5144 5145TEST(ForEach, BindsOneNode) {5146  EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",5147                                       recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),5148                                       std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("x", 1)));5149}5150 5151TEST(ForEach, BindsMultipleNodes) {5152  EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",5153                                       recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),5154                                       std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 3)));5155}5156 5157TEST(ForEach, BindsRecursiveCombinations) {5158  EXPECT_TRUE(matchAndVerifyResultTrue(5159    "class C { class D { int x; int y; }; class E { int y; int z; }; };",5160    recordDecl(hasName("C"),5161               forEach(recordDecl(forEach(fieldDecl().bind("f"))))),5162    std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 4)));5163}5164 5165TEST(ForEach, DoesNotIgnoreImplicit) {5166  StringRef Code = R"cpp(5167void foo()5168{5169    int i = 0;5170    int b = 4;5171    i < b;5172}5173)cpp";5174  EXPECT_TRUE(matchAndVerifyResultFalse(5175      Code, binaryOperator(forEach(declRefExpr().bind("dre"))),5176      std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 0)));5177 5178  EXPECT_TRUE(matchAndVerifyResultTrue(5179      Code,5180      binaryOperator(forEach(5181          implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))),5182      std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));5183 5184  EXPECT_TRUE(matchAndVerifyResultTrue(5185      Code,5186      binaryOperator(5187          forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))),5188      std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));5189 5190  EXPECT_TRUE(matchAndVerifyResultTrue(5191      Code,5192      traverse(TK_IgnoreUnlessSpelledInSource,5193               binaryOperator(forEach(declRefExpr().bind("dre")))),5194      std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));5195}5196 5197TEST(ForEachDescendant, BindsOneNode) {5198  EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",5199                                       recordDecl(hasName("C"),5200                                                  forEachDescendant(fieldDecl(hasName("x")).bind("x"))),5201                                       std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("x", 1)));5202}5203 5204TEST(ForEachDescendant, NestedForEachDescendant) {5205  DeclarationMatcher m = recordDecl(5206    isDefinition(), decl().bind("x"), hasName("C"));5207  EXPECT_TRUE(matchAndVerifyResultTrue(5208    "class A { class B { class C {}; }; };",5209    recordDecl(hasName("A"), anyOf(m, forEachDescendant(m))),5210    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", "C")));5211 5212  // Check that a partial match of 'm' that binds 'x' in the5213  // first part of anyOf(m, anything()) will not overwrite the5214  // binding created by the earlier binding in the hasDescendant.5215  EXPECT_TRUE(matchAndVerifyResultTrue(5216    "class A { class B { class C {}; }; };",5217    recordDecl(hasName("A"), allOf(hasDescendant(m), anyOf(m, anything()))),5218    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", "C")));5219}5220 5221TEST(ForEachDescendant, BindsMultipleNodes) {5222  EXPECT_TRUE(matchAndVerifyResultTrue(5223    "class C { class D { int x; int y; }; "5224      "          class E { class F { int y; int z; }; }; };",5225    recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),5226    std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 4)));5227}5228 5229TEST(ForEachDescendant, BindsRecursiveCombinations) {5230  EXPECT_TRUE(matchAndVerifyResultTrue(5231    "class C { class D { "5232      "          class E { class F { class G { int y; int z; }; }; }; }; };",5233    recordDecl(hasName("C"), forEachDescendant(recordDecl(5234      forEachDescendant(fieldDecl().bind("f"))))),5235    std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 8)));5236}5237 5238TEST(ForEachDescendant, BindsCombinations) {5239  EXPECT_TRUE(matchAndVerifyResultTrue(5240    "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "5241      "(true) {} }",5242    compoundStmt(forEachDescendant(ifStmt().bind("if")),5243                 forEachDescendant(whileStmt().bind("while"))),5244    std::make_unique<VerifyIdIsBoundTo<IfStmt>>("if", 6)));5245}5246 5247TEST(ForEachTemplateArgument, OnFunctionDecl) {5248  const std::string Code = R"(5249template <typename T, typename U> void f(T, U) {}5250void test() {5251  int I = 1;5252  bool B = false;5253  f(I, B);5254})";5255  EXPECT_TRUE(matches(5256      Code, functionDecl(forEachTemplateArgument(refersToType(builtinType()))),5257      langCxx11OrLater()));5258  auto matcher =5259      functionDecl(forEachTemplateArgument(5260                       templateArgument(refersToType(builtinType().bind("BT")))5261                           .bind("TA")))5262          .bind("FN");5263 5264  EXPECT_TRUE(matchAndVerifyResultTrue(5265      Code, matcher,5266      std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("FN", 2)));5267  EXPECT_TRUE(matchAndVerifyResultTrue(5268      Code, matcher,5269      std::make_unique<VerifyIdIsBoundTo<TemplateArgument>>("TA", 2)));5270  EXPECT_TRUE(matchAndVerifyResultTrue(5271      Code, matcher,5272      std::make_unique<VerifyIdIsBoundTo<BuiltinType>>("BT", 2)));5273}5274 5275TEST(ForEachTemplateArgument, OnClassTemplateSpecialization) {5276  const std::string Code = R"(5277template <typename T, unsigned N, unsigned M>5278struct Matrix {};5279 5280static constexpr unsigned R = 2;5281 5282Matrix<int, R * 2, R * 4> M;5283)";5284  EXPECT_TRUE(matches(5285      Code, templateSpecializationType(forEachTemplateArgument(isExpr(expr()))),5286      langCxx11OrLater()));5287  auto matcher = templateSpecializationType(5288                     forEachTemplateArgument(5289                         templateArgument(isExpr(expr().bind("E"))).bind("TA")))5290                     .bind("TST");5291 5292  EXPECT_TRUE(matchAndVerifyResultTrue(5293      Code, matcher,5294      std::make_unique<VerifyIdIsBoundTo<TemplateSpecializationType>>("TST",5295                                                                      2)));5296  EXPECT_TRUE(matchAndVerifyResultTrue(5297      Code, matcher,5298      std::make_unique<VerifyIdIsBoundTo<TemplateArgument>>("TA", 2)));5299  EXPECT_TRUE(matchAndVerifyResultTrue(5300      Code, matcher, std::make_unique<VerifyIdIsBoundTo<Expr>>("E", 2)));5301}5302 5303TEST(Has, DoesNotDeleteBindings) {5304  EXPECT_TRUE(matchAndVerifyResultTrue(5305    "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),5306    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5307}5308 5309TEST(TemplateArgumentLoc, Matches) {5310  EXPECT_TRUE(matchAndVerifyResultTrue(5311      R"cpp(5312        template <typename A, int B, template <typename> class C> class X {};5313        class A {};5314        const int B = 42;5315        template <typename> class C {};5316        X<A, B, C> x;5317      )cpp",5318      templateArgumentLoc().bind("x"),5319      std::make_unique<VerifyIdIsBoundTo<TemplateArgumentLoc>>("x", 3)));5320}5321 5322TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {5323  // Those matchers cover all the cases where an inner matcher is called5324  // and there is not a 1:1 relationship between the match of the outer5325  // matcher and the match of the inner matcher.5326  // The pattern to look for is:5327  //   ... return InnerMatcher.matches(...); ...5328  // In which case no special handling is needed.5329  //5330  // On the other hand, if there are multiple alternative matches5331  // (for example forEach*) or matches might be discarded (for example has*)5332  // the implementation must make sure that the discarded matches do not5333  // affect the bindings.5334  // When new such matchers are added, add a test here that:5335  // - matches a simple node, and binds it as the first thing in the matcher:5336  //     recordDecl(decl().bind("x"), hasName("X")))5337  // - uses the matcher under test afterwards in a way that not the first5338  //   alternative is matched; for anyOf, that means the first branch5339  //   would need to return false; for hasAncestor, it means that not5340  //   the direct parent matches the inner matcher.5341 5342  EXPECT_TRUE(matchAndVerifyResultTrue(5343    "class X { int y; };",5344    recordDecl(5345      recordDecl().bind("x"), hasName("::X"),5346      anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),5347    std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));5348  EXPECT_TRUE(matchAndVerifyResultTrue(5349    "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),5350                              anyOf(unless(anything()), anything())),5351    std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));5352  EXPECT_TRUE(matchAndVerifyResultTrue(5353    "template<typename T1, typename T2> class X {}; X<float, int> x;",5354    classTemplateSpecializationDecl(5355      decl().bind("x"),5356      hasAnyTemplateArgument(refersToType(asString("int")))),5357    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5358  EXPECT_TRUE(matchAndVerifyResultTrue(5359    "class X { void f(); void g(); };",5360    cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),5361    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5362  EXPECT_TRUE(matchAndVerifyResultTrue(5363    "class X { X() : a(1), b(2) {} double a; int b; };",5364    recordDecl(decl().bind("x"),5365               has(cxxConstructorDecl(5366                 hasAnyConstructorInitializer(forField(hasName("b")))))),5367    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5368  EXPECT_TRUE(matchAndVerifyResultTrue(5369    "void x(int, int) { x(0, 42); }",5370    callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),5371    std::make_unique<VerifyIdIsBoundTo<Expr>>("x", 1)));5372  EXPECT_TRUE(matchAndVerifyResultTrue(5373    "void x(int, int y) {}",5374    functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),5375    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5376  EXPECT_TRUE(matchAndVerifyResultTrue(5377    "void x() { return; if (true) {} }",5378    functionDecl(decl().bind("x"),5379                 has(compoundStmt(hasAnySubstatement(ifStmt())))),5380    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5381  EXPECT_TRUE(matchAndVerifyResultTrue(5382    "namespace X { void b(int); void b(); }"5383      "using X::b;",5384    usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(5385      functionDecl(parameterCountIs(1))))),5386    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5387  EXPECT_TRUE(matchAndVerifyResultTrue(5388      "class A{}; class B{}; class C : B, A {};",5389      cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A"),5390                    unless(isImplicit())),5391      std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5392  EXPECT_TRUE(matchAndVerifyResultTrue(5393      "class A{}; typedef A B; typedef A C; typedef A D;"5394      "class E : A {};",5395      cxxRecordDecl(decl().bind("x"), isDerivedFrom("C"), unless(isImplicit())),5396      std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5397  EXPECT_TRUE(matchAndVerifyResultTrue(5398    "class A { class B { void f() {} }; };",5399    functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),5400    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5401  EXPECT_TRUE(matchAndVerifyResultTrue(5402    "template <typename T> struct A { struct B {"5403      "  void f() { if(true) {} }"5404      "}; };"5405      "void t() { A<int>::B b; b.f(); }",5406    ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),5407    std::make_unique<VerifyIdIsBoundTo<Stmt>>("x", 2)));5408  EXPECT_TRUE(matchAndVerifyResultTrue(5409    "class A {};",5410    recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),5411    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5412  EXPECT_TRUE(matchAndVerifyResultTrue(5413    "class A { A() : s(), i(42) {} const char *s; int i; };",5414    cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),5415                       forEachConstructorInitializer(forField(hasName("i")))),5416    std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5417}5418 5419TEST(ForEachDescendant, BindsCorrectNodes) {5420  EXPECT_TRUE(matchAndVerifyResultTrue(5421    "class C { void f(); int i; };",5422    recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),5423    std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("decl", 1)));5424  EXPECT_TRUE(matchAndVerifyResultTrue(5425    "class C { void f() {} int i; };",5426    recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),5427    std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("decl", 1)));5428}5429 5430TEST(FindAll, BindsNodeOnMatch) {5431  EXPECT_TRUE(matchAndVerifyResultTrue(5432    "class A {};",5433    recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),5434    std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("v", 1)));5435}5436 5437TEST(FindAll, BindsDescendantNodeOnMatch) {5438  EXPECT_TRUE(matchAndVerifyResultTrue(5439    "class A { int a; int b; };",5440    recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),5441    std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 2)));5442}5443 5444TEST(FindAll, BindsNodeAndDescendantNodesOnOneMatch) {5445  EXPECT_TRUE(matchAndVerifyResultTrue(5446    "class A { int a; int b; };",5447    recordDecl(hasName("::A"),5448               findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),5449                                  fieldDecl().bind("v"))))),5450    std::make_unique<VerifyIdIsBoundTo<Decl>>("v", 3)));5451 5452  EXPECT_TRUE(matchAndVerifyResultTrue(5453    "class A { class B {}; class C {}; };",5454    recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),5455    std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("v", 3)));5456}5457 5458TEST(HasAncenstor, MatchesDeclarationAncestors) {5459  EXPECT_TRUE(matches(5460    "class A { class B { class C {}; }; };",5461    recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));5462}5463 5464TEST(HasAncenstor, FailsIfNoAncestorMatches) {5465  EXPECT_TRUE(notMatches(5466    "class A { class B { class C {}; }; };",5467    recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));5468}5469 5470TEST(HasAncestor, MatchesDeclarationsThatGetVisitedLater) {5471  EXPECT_TRUE(matches(5472    "class A { class B { void f() { C c; } class C {}; }; };",5473    varDecl(hasName("c"), hasType(recordDecl(hasName("C"),5474                                             hasAncestor(recordDecl(hasName("A"))))))));5475}5476 5477TEST(HasAncenstor, MatchesStatementAncestors) {5478  EXPECT_TRUE(matches(5479    "void f() { if (true) { while (false) { 42; } } }",5480    integerLiteral(equals(42), hasAncestor(ifStmt()))));5481}5482 5483TEST(HasAncestor, DrillsThroughDifferentHierarchies) {5484  EXPECT_TRUE(matches(5485    "void f() { if (true) { int x = 42; } }",5486    integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));5487}5488 5489TEST(HasAncestor, BindsRecursiveCombinations) {5490  EXPECT_TRUE(matchAndVerifyResultTrue(5491    "class C { class D { class E { class F { int y; }; }; }; };",5492    fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),5493    std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("r", 1)));5494}5495 5496TEST(HasAncestor, BindsCombinationsWithHasDescendant) {5497  EXPECT_TRUE(matchAndVerifyResultTrue(5498    "class C { class D { class E { class F { int y; }; }; }; };",5499    fieldDecl(hasAncestor(5500      decl(5501        hasDescendant(recordDecl(isDefinition(),5502                                 hasAncestor(recordDecl())))5503      ).bind("d")5504    )),5505    std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("d", "E")));5506}5507 5508TEST(HasAncestor, MatchesClosestAncestor) {5509  EXPECT_TRUE(matchAndVerifyResultTrue(5510    "template <typename T> struct C {"5511      "  void f(int) {"5512      "    struct I { void g(T) { int x; } } i; i.g(42);"5513      "  }"5514      "};"5515      "template struct C<int>;",5516    varDecl(hasName("x"),5517            hasAncestor(functionDecl(hasParameter(5518              0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),5519    std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("f", "g", 2)));5520}5521 5522TEST(HasAncestor, MatchesInTemplateInstantiations) {5523  EXPECT_TRUE(matches(5524    "template <typename T> struct A { struct B { struct C { T t; }; }; }; "5525      "A<int>::B::C a;",5526    fieldDecl(hasType(asString("int")),5527              hasAncestor(recordDecl(hasName("A"))))));5528}5529 5530TEST(HasAncestor, MatchesInImplicitCode) {5531  EXPECT_TRUE(matches(5532    "struct X {}; struct A { A() {} X x; };",5533    cxxConstructorDecl(5534      hasAnyConstructorInitializer(withInitializer(expr(5535        hasAncestor(recordDecl(hasName("A")))))))));5536}5537 5538TEST(HasParent, MatchesOnlyParent) {5539  EXPECT_TRUE(matches(5540    "void f() { if (true) { int x = 42; } }",5541    compoundStmt(hasParent(ifStmt()))));5542  EXPECT_TRUE(notMatches(5543    "void f() { for (;;) { int x = 42; } }",5544    compoundStmt(hasParent(ifStmt()))));5545  EXPECT_TRUE(notMatches(5546    "void f() { if (true) for (;;) { int x = 42; } }",5547    compoundStmt(hasParent(ifStmt()))));5548}5549 5550TEST(MatcherMemoize, HasParentDiffersFromHas) {5551  // Test introduced after detecting a bug in memoization5552  constexpr auto code = "void f() { throw 1; }";5553  EXPECT_TRUE(notMatches(5554    code,5555    cxxThrowExpr(hasParent(expr()))));5556  EXPECT_TRUE(matches(5557    code,5558    cxxThrowExpr(has(expr()))));5559  EXPECT_TRUE(matches(5560    code,5561    cxxThrowExpr(anyOf(hasParent(expr()), has(expr())))));5562}5563 5564TEST(MatcherMemoize, HasDiffersFromHasDescendant) {5565  // Test introduced after detecting a bug in memoization5566  constexpr auto code = "void f() { throw 1+1; }";5567  EXPECT_TRUE(notMatches(5568    code,5569    cxxThrowExpr(has(integerLiteral()))));5570  EXPECT_TRUE(matches(5571    code,5572    cxxThrowExpr(hasDescendant(integerLiteral()))));5573  EXPECT_TRUE(5574      notMatches(code, cxxThrowExpr(allOf(hasDescendant(integerLiteral()),5575                                          has(integerLiteral())))));5576}5577TEST(HasAncestor, MatchesAllAncestors) {5578  EXPECT_TRUE(matches(5579    "template <typename T> struct C { static void f() { 42; } };"5580      "void t() { C<int>::f(); }",5581    integerLiteral(5582      equals(42),5583      allOf(5584        hasAncestor(cxxRecordDecl(isTemplateInstantiation())),5585        hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));5586}5587 5588TEST(HasAncestor, ImplicitArrayCopyCtorDeclRefExpr) {5589  EXPECT_TRUE(matches("struct MyClass {\n"5590                        "  int c[1];\n"5591                        "  static MyClass Create() { return MyClass(); }\n"5592                        "};",5593                      declRefExpr(to(decl(hasAncestor(decl()))))));5594}5595 5596TEST(HasAncestor, AnonymousUnionMemberExpr) {5597  EXPECT_TRUE(matches("int F() {\n"5598                        "  union { int i; };\n"5599                        "  return i;\n"5600                        "}\n",5601                      memberExpr(member(hasAncestor(decl())))));5602  EXPECT_TRUE(matches("void f() {\n"5603                        "  struct {\n"5604                        "    struct { int a; int b; };\n"5605                        "  } s;\n"5606                        "  s.a = 4;\n"5607                        "}\n",5608                      memberExpr(member(hasAncestor(decl())))));5609  EXPECT_TRUE(matches("void f() {\n"5610                        "  struct {\n"5611                        "    struct { int a; int b; };\n"5612                        "  } s;\n"5613                        "  s.a = 4;\n"5614                        "}\n",5615                      declRefExpr(to(decl(hasAncestor(decl()))))));5616}5617TEST(HasAncestor, NonParmDependentTemplateParmVarDeclRefExpr) {5618  EXPECT_TRUE(matches("struct PartitionAllocator {\n"5619                        "  template<typename T>\n"5620                        "  static int quantizedSize(int count) {\n"5621                        "    return count;\n"5622                        "  }\n"5623                        "  void f() { quantizedSize<int>(10); }\n"5624                        "};",5625                      declRefExpr(to(decl(hasAncestor(decl()))))));5626}5627 5628TEST(HasAncestor, AddressOfExplicitSpecializationFunction) {5629  EXPECT_TRUE(matches("template <class T> void f();\n"5630                        "template <> void f<int>();\n"5631                        "void (*get_f())() { return f<int>; }\n",5632                      declRefExpr(to(decl(hasAncestor(decl()))))));5633}5634 5635TEST(HasParent, MatchesAllParents) {5636  EXPECT_TRUE(matches(5637    "template <typename T> struct C { static void f() { 42; } };"5638      "void t() { C<int>::f(); }",5639    integerLiteral(5640      equals(42),5641      hasParent(compoundStmt(hasParent(functionDecl(5642        hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));5643  EXPECT_TRUE(5644    matches("template <typename T> struct C { static void f() { 42; } };"5645              "void t() { C<int>::f(); }",5646            integerLiteral(5647              equals(42),5648              hasParent(compoundStmt(hasParent(functionDecl(hasParent(5649                cxxRecordDecl(unless(isTemplateInstantiation()))))))))));5650  EXPECT_TRUE(matches(5651    "template <typename T> struct C { static void f() { 42; } };"5652      "void t() { C<int>::f(); }",5653    integerLiteral(equals(42),5654                   hasParent(compoundStmt(5655                     allOf(hasParent(functionDecl(hasParent(5656                       cxxRecordDecl(isTemplateInstantiation())))),5657                           hasParent(functionDecl(hasParent(cxxRecordDecl(5658                             unless(isTemplateInstantiation())))))))))));5659  EXPECT_TRUE(5660    notMatches("template <typename T> struct C { static void f() {} };"5661                 "void t() { C<int>::f(); }",5662               compoundStmt(hasParent(recordDecl()))));5663}5664 5665TEST(HasParent, NoDuplicateParents) {5666  class HasDuplicateParents : public BoundNodesCallback {5667  public:5668    bool run(const BoundNodes *Nodes, ASTContext *Context) override {5669      const Stmt *Node = Nodes->getNodeAs<Stmt>("node");5670      std::set<const void *> Parents;5671      for (const auto &Parent : Context->getParents(*Node)) {5672        if (!Parents.insert(Parent.getMemoizationData()).second) {5673          return true;5674        }5675      }5676      return false;5677    }5678  };5679  EXPECT_FALSE(matchAndVerifyResultTrue(5680    "template <typename T> int Foo() { return 1 + 2; }\n"5681      "int x = Foo<int>() + Foo<unsigned>();",5682    stmt().bind("node"), std::make_unique<HasDuplicateParents>()));5683}5684 5685TEST(HasAnyBase, BindsInnerBoundNodes) {5686  EXPECT_TRUE(matchAndVerifyResultTrue(5687      "struct Inner {}; struct Proxy : Inner {}; struct Main : public "5688      "Proxy {};",5689      cxxRecordDecl(hasName("Main"), unless(isImplicit()),5690                    hasAnyBase(cxxBaseSpecifier(hasType(5691                        cxxRecordDecl(hasName("Inner")).bind("base-class")))))5692          .bind("class"),5693      std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("base-class",5694                                                         "Inner")));5695}5696 5697TEST(TypeMatching, PointeeTypes) {5698  EXPECT_TRUE(matches("int b; int &a = b;",5699                      referenceType(pointee(builtinType()))));5700  EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));5701 5702  EXPECT_TRUE(matches("int *a;",5703                      loc(pointerType(pointee(builtinType())))));5704 5705  EXPECT_TRUE(matches(5706    "int const *A;",5707    pointerType(pointee(isConstQualified(), builtinType()))));5708  EXPECT_TRUE(notMatches(5709    "int *A;",5710    pointerType(pointee(isConstQualified(), builtinType()))));5711}5712 5713TEST(ElaboratedTypeNarrowing, hasQualifier) {5714  EXPECT_TRUE(matches(5715      "namespace N {"5716      "  namespace M {"5717      "    class D {};"5718      "  }"5719      "}"5720      "N::M::D d;",5721      recordType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));5722  EXPECT_TRUE(notMatches(5723      "namespace M {"5724      "  class D {};"5725      "}"5726      "M::D d;",5727      recordType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));5728  EXPECT_TRUE(notMatches("struct D {"5729                         "} d;",5730                         recordType(hasQualifier(nestedNameSpecifier()))));5731}5732 5733TEST(NNS, BindsNestedNameSpecifiers) {5734  EXPECT_TRUE(matchAndVerifyResultTrue(5735      "namespace ns { struct E { struct B {}; }; } ns::E::B b;",5736      nestedNameSpecifier(specifiesType(asString("ns::E"))).bind("nns"),5737      std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("nns",5738                                                               "ns::E::")));5739}5740 5741TEST(NNS, BindsNestedNameSpecifierLocs) {5742  EXPECT_TRUE(matchAndVerifyResultTrue(5743    "namespace ns { struct B {}; } ns::B b;",5744    loc(nestedNameSpecifier()).bind("loc"),5745    std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("loc", 1)));5746}5747 5748TEST(NNS, DescendantsOfNestedNameSpecifiers) {5749  StringRef Fragment =5750      "namespace a { struct A { struct B { struct C {}; }; }; };"5751      "void f() { a::A::B::C c; }";5752  EXPECT_TRUE(matches(5753      Fragment, nestedNameSpecifier(specifiesType(asString("a::A::B")),5754                                    hasDescendant(nestedNameSpecifier(5755                                        specifiesNamespace(hasName("a")))))));5756  EXPECT_TRUE(notMatches(5757      Fragment, nestedNameSpecifier(specifiesType(asString("a::A::B")),5758                                    has(nestedNameSpecifier(5759                                        specifiesNamespace(hasName("a")))))));5760  EXPECT_TRUE(matches(5761      Fragment, nestedNameSpecifier(specifiesType(asString("a::A")),5762                                    has(nestedNameSpecifier(5763                                        specifiesNamespace(hasName("a")))))));5764 5765  // Not really useful because a NestedNameSpecifier can af at most one child,5766  // but to complete the interface.5767  EXPECT_TRUE(matchAndVerifyResultTrue(5768      Fragment,5769      nestedNameSpecifier(specifiesType(asString("a::A::B")),5770                          forEach(nestedNameSpecifier().bind("x"))),5771      std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 1)));5772}5773 5774TEST(NNS, NestedNameSpecifiersAsDescendants) {5775  StringRef Fragment =5776      "namespace a { struct A { struct B { struct C {}; }; }; };"5777      "void f() { a::A::B::C c; }";5778  EXPECT_TRUE(matches(Fragment, decl(hasDescendant(nestedNameSpecifier(5779                                    specifiesType(asString("a::A")))))));5780  EXPECT_TRUE(matchAndVerifyResultTrue(5781    Fragment,5782    functionDecl(hasName("f"),5783                 forEachDescendant(nestedNameSpecifier().bind("x"))),5784    // Nested names: a, a::A and a::A::B.5785    std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 3)));5786}5787 5788TEST(NNSLoc, DescendantsOfNestedNameSpecifierLocs) {5789  StringRef Fragment =5790      "namespace a { struct A { struct B { struct C {}; }; }; };"5791      "void f() { a::A::B::C c; }";5792  EXPECT_TRUE(matches(Fragment, nestedNameSpecifierLoc(5793                                    loc(specifiesType(asString("a::A::B"))),5794                                    hasDescendant(loc(nestedNameSpecifier(5795                                        specifiesNamespace(hasName("a"))))))));5796  EXPECT_TRUE(notMatches(5797      Fragment,5798      nestedNameSpecifierLoc(5799          loc(specifiesType(asString("a::A::B"))),5800          has(loc(nestedNameSpecifier(specifiesNamespace(hasName("a"))))))));5801  EXPECT_TRUE(matches(5802      Fragment,5803      nestedNameSpecifierLoc(5804          loc(specifiesType(asString("a::A"))),5805          has(loc(nestedNameSpecifier(specifiesNamespace(hasName("a"))))))));5806 5807  EXPECT_TRUE(matchAndVerifyResultTrue(5808      Fragment,5809      nestedNameSpecifierLoc(loc(specifiesType(asString("a::A::B"))),5810                             forEach(nestedNameSpecifierLoc().bind("x"))),5811      std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 1)));5812}5813 5814TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) {5815  StringRef Fragment =5816      "namespace a { struct A { struct B { struct C {}; }; }; };"5817      "void f() { a::A::B::C c; }";5818  EXPECT_TRUE(matches(Fragment, decl(hasDescendant(loc(nestedNameSpecifier(5819                                    specifiesType(asString("a::A"))))))));5820  EXPECT_TRUE(matchAndVerifyResultTrue(5821    Fragment,5822    functionDecl(hasName("f"),5823                 forEachDescendant(nestedNameSpecifierLoc().bind("x"))),5824    // Nested names: a, a::A and a::A::B.5825    std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 3)));5826}5827 5828TEST(Attr, AttrsAsDescendants) {5829  StringRef Fragment = "namespace a { struct [[clang::warn_unused_result]] "5830                       "F{}; [[noreturn]] void foo(); }";5831  EXPECT_TRUE(matches(Fragment, namespaceDecl(hasDescendant(attr()))));5832  EXPECT_TRUE(matchAndVerifyResultTrue(5833      Fragment,5834      namespaceDecl(hasName("a"),5835                    forEachDescendant(decl(5836                        hasDescendant(attr(unless(isImplicit())).bind("x")),5837                        unless(isImplicit())))),5838      std::make_unique<VerifyIdIsBoundTo<Attr>>("x", 2)));5839}5840 5841TEST(Attr, ParentsOfAttrs) {5842  StringRef Fragment =5843      "namespace a { struct [[clang::warn_unused_result]] F{}; }";5844  EXPECT_TRUE(matches(Fragment, attr(hasAncestor(namespaceDecl()))));5845}5846 5847template <typename T> class VerifyMatchOnNode : public BoundNodesCallback {5848public:5849  VerifyMatchOnNode(StringRef Id, const internal::Matcher<T> &InnerMatcher,5850                    StringRef InnerId)5851      : Id(Id), InnerMatcher(InnerMatcher), InnerId(InnerId) {}5852 5853  bool run(const BoundNodes *Nodes, ASTContext *Context) override {5854    const T *Node = Nodes->getNodeAs<T>(Id);5855    return selectFirst<T>(InnerId, match(InnerMatcher, *Node, *Context)) !=5856           nullptr;5857  }5858 5859private:5860  std::string Id;5861  internal::Matcher<T> InnerMatcher;5862  std::string InnerId;5863};5864 5865TEST(MatchFinder, CanMatchDeclarationsRecursively) {5866  EXPECT_TRUE(matchAndVerifyResultTrue(5867    "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5868    std::make_unique<VerifyMatchOnNode<Decl>>(5869      "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),5870      "Y")));5871  EXPECT_TRUE(matchAndVerifyResultFalse(5872    "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5873    std::make_unique<VerifyMatchOnNode<Decl>>(5874      "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),5875      "Z")));5876}5877 5878TEST(MatchFinder, CanMatchStatementsRecursively) {5879  EXPECT_TRUE(matchAndVerifyResultTrue(5880    "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),5881    std::make_unique<VerifyMatchOnNode<Stmt>>(5882      "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));5883  EXPECT_TRUE(matchAndVerifyResultFalse(5884    "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),5885    std::make_unique<VerifyMatchOnNode<Stmt>>(5886      "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));5887}5888 5889TEST(MatchFinder, CanMatchSingleNodesRecursively) {5890  EXPECT_TRUE(matchAndVerifyResultTrue(5891    "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5892    std::make_unique<VerifyMatchOnNode<Decl>>(5893      "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));5894  EXPECT_TRUE(matchAndVerifyResultFalse(5895    "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5896    std::make_unique<VerifyMatchOnNode<Decl>>(5897      "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));5898}5899 5900TEST(StatementMatcher, HasReturnValue) {5901  StatementMatcher RetVal = returnStmt(hasReturnValue(binaryOperator()));5902  EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal));5903  EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal));5904  EXPECT_FALSE(matches("void F() { return; }", RetVal));5905}5906 5907TEST(StatementMatcher, ForFunction) {5908  StringRef CppString1 = "struct PosVec {"5909                         "  PosVec& operator=(const PosVec&) {"5910                         "    auto x = [] { return 1; };"5911                         "    return *this;"5912                         "  }"5913                         "};";5914  StringRef CppString2 = "void F() {"5915                         "  struct S {"5916                         "    void F2() {"5917                         "       return;"5918                         "    }"5919                         "  };"5920                         "}";5921  EXPECT_TRUE(5922    matches(5923      CppString1,5924      returnStmt(forFunction(hasName("operator=")),5925                 has(unaryOperator(hasOperatorName("*"))))));5926  EXPECT_TRUE(5927    notMatches(5928      CppString1,5929      returnStmt(forFunction(hasName("operator=")),5930                 has(integerLiteral()))));5931  EXPECT_TRUE(5932    matches(5933      CppString1,5934      returnStmt(forFunction(hasName("operator()")),5935                 has(integerLiteral()))));5936  EXPECT_TRUE(matches(CppString2, returnStmt(forFunction(hasName("F2")))));5937  EXPECT_TRUE(notMatches(CppString2, returnStmt(forFunction(hasName("F")))));5938}5939 5940TEST(StatementMatcher, ForCallable) {5941  // These tests are copied over from the forFunction() test above.5942  StringRef CppString1 = "struct PosVec {"5943                         "  PosVec& operator=(const PosVec&) {"5944                         "    auto x = [] { return 1; };"5945                         "    return *this;"5946                         "  }"5947                         "};";5948  StringRef CppString2 = "void F() {"5949                         "  struct S {"5950                         "    void F2() {"5951                         "       return;"5952                         "    }"5953                         "  };"5954                         "}";5955 5956  EXPECT_TRUE(5957    matches(5958      CppString1,5959      returnStmt(forCallable(functionDecl(hasName("operator="))),5960                 has(unaryOperator(hasOperatorName("*"))))));5961  EXPECT_TRUE(5962    notMatches(5963      CppString1,5964      returnStmt(forCallable(functionDecl(hasName("operator="))),5965                 has(integerLiteral()))));5966  EXPECT_TRUE(5967    matches(5968      CppString1,5969      returnStmt(forCallable(functionDecl(hasName("operator()"))),5970                 has(integerLiteral()))));5971  EXPECT_TRUE(matches(CppString2,5972                      returnStmt(forCallable(functionDecl(hasName("F2"))))));5973  EXPECT_TRUE(notMatches(CppString2,5974                         returnStmt(forCallable(functionDecl(hasName("F"))))));5975 5976  StringRef CodeWithDeepCallExpr = R"cpp(5977void Other();5978void Function() {5979  {5980    (5981      Other()5982    );5983  }5984}5985)cpp";5986  auto ForCallableFirst =5987      callExpr(forCallable(functionDecl(hasName("Function"))),5988               callee(functionDecl(hasName("Other")).bind("callee")))5989          .bind("call");5990  auto ForCallableSecond =5991      callExpr(callee(functionDecl(hasName("Other")).bind("callee")),5992               forCallable(functionDecl(hasName("Function"))))5993          .bind("call");5994  EXPECT_TRUE(matchAndVerifyResultTrue(5995      CodeWithDeepCallExpr, ForCallableFirst,5996      std::make_unique<VerifyIdIsBoundTo<CallExpr>>("call")));5997  EXPECT_TRUE(matchAndVerifyResultTrue(5998      CodeWithDeepCallExpr, ForCallableFirst,5999      std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("callee")));6000  EXPECT_TRUE(matchAndVerifyResultTrue(6001      CodeWithDeepCallExpr, ForCallableSecond,6002      std::make_unique<VerifyIdIsBoundTo<CallExpr>>("call")));6003  EXPECT_TRUE(matchAndVerifyResultTrue(6004      CodeWithDeepCallExpr, ForCallableSecond,6005      std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("callee")));6006 6007  // These tests are specific to forCallable().6008  StringRef ObjCString1 = "@interface I"6009                          "-(void) foo;"6010                          "@end"6011                          "@implementation I"6012                          "-(void) foo {"6013                          "  void (^block)() = ^{ 0x2b | ~0x2b; };"6014                          "}"6015                          "@end";6016 6017  EXPECT_TRUE(6018    matchesObjC(6019      ObjCString1,6020      binaryOperator(forCallable(blockDecl()))));6021 6022  EXPECT_TRUE(6023    notMatchesObjC(6024      ObjCString1,6025      binaryOperator(forCallable(objcMethodDecl()))));6026 6027  StringRef ObjCString2 = "@interface I"6028                          "-(void) foo;"6029                          "@end"6030                          "@implementation I"6031                          "-(void) foo {"6032                          "  0x2b | ~0x2b;"6033                          "  void (^block)() = ^{};"6034                          "}"6035                          "@end";6036 6037  EXPECT_TRUE(6038    matchesObjC(6039      ObjCString2,6040      binaryOperator(forCallable(objcMethodDecl()))));6041 6042  EXPECT_TRUE(6043    notMatchesObjC(6044      ObjCString2,6045      binaryOperator(forCallable(blockDecl()))));6046}6047 6048namespace {6049class ForCallablePreservesBindingWithMultipleParentsTestCallback6050    : public BoundNodesCallback {6051public:6052  bool run(const BoundNodes *BoundNodes, ASTContext *Context) override {6053    FunctionDecl const *FunDecl =6054        BoundNodes->getNodeAs<FunctionDecl>("funDecl");6055    // Validate test assumptions. This would be expressed as ASSERT_* in6056    // a TEST().6057    if (!FunDecl) {6058      EXPECT_TRUE(false && "Incorrect test setup");6059      return false;6060    }6061    auto const *FunDef = FunDecl->getDefinition();6062    if (!FunDef || !FunDef->getBody() ||6063        FunDef->getNameAsString() != "Function") {6064      EXPECT_TRUE(false && "Incorrect test setup");6065      return false;6066    }6067 6068    ExpectCorrectResult(6069        "Baseline",6070        callExpr(callee(cxxMethodDecl().bind("callee"))).bind("call"), //6071        FunDecl);6072 6073    ExpectCorrectResult("ForCallable first",6074                        callExpr(forCallable(equalsNode(FunDecl)),6075                                 callee(cxxMethodDecl().bind("callee")))6076                            .bind("call"),6077                        FunDecl);6078 6079    ExpectCorrectResult("ForCallable second",6080                        callExpr(callee(cxxMethodDecl().bind("callee")),6081                                 forCallable(equalsNode(FunDecl)))6082                            .bind("call"),6083                        FunDecl);6084 6085    // This value does not really matter: the EXPECT_* will set the exit code.6086    return true;6087  }6088 6089private:6090  void ExpectCorrectResult(StringRef LogInfo,6091                           ArrayRef<BoundNodes> Results) const {6092    EXPECT_EQ(Results.size(), 1u) << LogInfo;6093    if (Results.empty())6094      return;6095    auto const &R = Results.front();6096    EXPECT_TRUE(R.getNodeAs<CallExpr>("call")) << LogInfo;6097    EXPECT_TRUE(R.getNodeAs<CXXMethodDecl>("callee")) << LogInfo;6098  }6099 6100  template <typename MatcherT>6101  void ExpectCorrectResult(StringRef LogInfo, MatcherT Matcher,6102                           FunctionDecl const *FunDef) const {6103    auto &Context = FunDef->getASTContext();6104    auto const &Results = match(findAll(Matcher), *FunDef->getBody(), Context);6105    ExpectCorrectResult(LogInfo, Results);6106  }6107};6108} // namespace6109 6110TEST(StatementMatcher, ForCallablePreservesBindingWithMultipleParents) {6111  // Tests in this file are fairly simple and therefore can rely on matches,6112  // matchAndVerifyResultTrue, etc. This test, however, needs a FunctionDecl* in6113  // order to call equalsNode in order to reproduce the observed issue (bindings6114  // being removed despite forCallable matching the node).6115  //6116  // Because of this and because the machinery to compile the code into an6117  // ASTUnit is not exposed outside matchAndVerifyResultConditionally, it is6118  // cheaper to have a custom BoundNodesCallback for the purpose of this test.6119  StringRef codeWithTemplateFunction = R"cpp(6120struct Klass {6121  void Method();6122  template <typename T>6123  void Function(T t); // Declaration6124};6125 6126void Instantiate(Klass k) {6127  k.Function(0);6128}6129 6130template <typename T>6131void Klass::Function(T t) { // Definition6132  // Compound statement has two parents: the declaration and the definition.6133  Method();6134}6135)cpp";6136  EXPECT_TRUE(matchAndVerifyResultTrue(6137      codeWithTemplateFunction,6138      callExpr(callee(functionDecl(hasName("Function")).bind("funDecl"))),6139      std::make_unique<6140          ForCallablePreservesBindingWithMultipleParentsTestCallback>()));6141}6142 6143TEST(Matcher, ForEachOverriden) {6144  const auto ForEachOverriddenInClass = [](const char *ClassName) {6145    return cxxMethodDecl(ofClass(hasName(ClassName)), isVirtual(),6146                         forEachOverridden(cxxMethodDecl().bind("overridden")))6147        .bind("override");6148  };6149  static const char Code1[] = "class A { virtual void f(); };"6150                              "class B : public A { void f(); };"6151                              "class C : public B { void f(); };";6152  // C::f overrides A::f.6153  EXPECT_TRUE(matchAndVerifyResultTrue(6154      Code1, ForEachOverriddenInClass("C"),6155      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));6156  EXPECT_TRUE(matchAndVerifyResultTrue(6157      Code1, ForEachOverriddenInClass("C"),6158      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",6159                                                          1)));6160  // B::f overrides A::f.6161  EXPECT_TRUE(matchAndVerifyResultTrue(6162      Code1, ForEachOverriddenInClass("B"),6163      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));6164  EXPECT_TRUE(matchAndVerifyResultTrue(6165      Code1, ForEachOverriddenInClass("B"),6166      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",6167                                                          1)));6168  // A::f overrides nothing.6169  EXPECT_TRUE(notMatches(Code1, ForEachOverriddenInClass("A")));6170 6171  static const char Code2[] =6172      "class A1 { virtual void f(); };"6173      "class A2 { virtual void f(); };"6174      "class B : public A1, public A2 { void f(); };";6175  // B::f overrides A1::f and A2::f. This produces two matches.6176  EXPECT_TRUE(matchAndVerifyResultTrue(6177      Code2, ForEachOverriddenInClass("B"),6178      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 2)));6179  EXPECT_TRUE(matchAndVerifyResultTrue(6180      Code2, ForEachOverriddenInClass("B"),6181      std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",6182                                                          2)));6183  // A1::f overrides nothing.6184  EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1")));6185}6186 6187TEST(Matcher, HasAnyDeclaration) {6188  StringRef Fragment = "void foo(int p1);"6189                       "void foo(int *p2);"6190                       "void bar(int p3);"6191                       "template <typename T> void baz(T t) { foo(t); }";6192 6193  EXPECT_TRUE(6194      matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(6195                            hasParameter(0, parmVarDecl(hasName("p1"))))))));6196  EXPECT_TRUE(6197      matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(6198                            hasParameter(0, parmVarDecl(hasName("p2"))))))));6199  EXPECT_TRUE(6200      notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(6201                               hasParameter(0, parmVarDecl(hasName("p3"))))))));6202  EXPECT_TRUE(notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(6203                                       functionDecl(hasName("bar"))))));6204}6205 6206TEST(SubstTemplateTypeParmType, HasReplacementType) {6207  StringRef Fragment = "template<typename T>"6208                       "double F(T t);"6209                       "int i;"6210                       "double j = F(i);";6211  EXPECT_TRUE(matches(Fragment, substTemplateTypeParmType(hasReplacementType(6212                                    qualType(asString("int"))))));6213  EXPECT_TRUE(notMatches(Fragment, substTemplateTypeParmType(hasReplacementType(6214                                       qualType(asString("double"))))));6215  EXPECT_TRUE(6216      notMatches("template<int N>"6217                 "double F();"6218                 "double j = F<5>();",6219                 substTemplateTypeParmType(hasReplacementType(qualType()))));6220}6221 6222TEST(ClassTemplateSpecializationDecl, HasSpecializedTemplate) {6223  auto Matcher = classTemplateSpecializationDecl(6224      hasSpecializedTemplate(classTemplateDecl()));6225  EXPECT_TRUE(6226      matches("template<typename T> class A {}; typedef A<int> B;", Matcher));6227  EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher));6228}6229 6230TEST(CXXNewExpr, Array) {6231  StatementMatcher NewArray = cxxNewExpr(isArray());6232 6233  EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray));6234  EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray));6235 6236  StatementMatcher NewArraySize10 =6237      cxxNewExpr(hasArraySize(integerLiteral(equals(10))));6238  EXPECT_TRUE(6239      matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10));6240  EXPECT_TRUE(6241      notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10));6242}6243 6244TEST(CXXNewExpr, PlacementArgs) {6245  StatementMatcher IsPlacementNew = cxxNewExpr(hasAnyPlacementArg(anything()));6246 6247  EXPECT_TRUE(matches(R"(6248    void* operator new(decltype(sizeof(void*)), void*);6249    int *foo(void* Storage) {6250      return new (Storage) int;6251    })",6252                      IsPlacementNew));6253 6254  EXPECT_TRUE(matches(R"(6255    void* operator new(decltype(sizeof(void*)), void*, unsigned);6256    int *foo(void* Storage) {6257      return new (Storage, 16) int;6258    })",6259                      cxxNewExpr(hasPlacementArg(6260                          1, ignoringImpCasts(integerLiteral(equals(16)))))));6261 6262  EXPECT_TRUE(notMatches(R"(6263    void* operator new(decltype(sizeof(void*)), void*);6264    int *foo(void* Storage) {6265      return new int;6266    })",6267                         IsPlacementNew));6268}6269 6270TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {6271  EXPECT_TRUE(matches(6272      "const int x = 0;",6273      varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6274                                hasUnqualifiedLoc(loc(asString("int"))))))));6275}6276 6277TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {6278  EXPECT_TRUE(matches(6279      "volatile int x = 0;",6280      varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6281                                hasUnqualifiedLoc(loc(asString("int"))))))));6282}6283 6284TEST(HasUnqualifiedLoc, BindsToConstVolatileIntVarDecl) {6285  EXPECT_TRUE(matches(6286      "const volatile int x = 0;",6287      varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6288                                hasUnqualifiedLoc(loc(asString("int"))))))));6289}6290 6291TEST(HasUnqualifiedLoc, BindsToConstPointerVarDecl) {6292  auto matcher = varDecl(6293      hasName("x"),6294      hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))));6295  EXPECT_TRUE(matches("int* const x = 0;", matcher));6296  EXPECT_TRUE(notMatches("int const x = 0;", matcher));6297}6298 6299TEST(HasUnqualifiedLoc, BindsToPointerToConstVolatileIntVarDecl) {6300  EXPECT_TRUE(6301      matches("const volatile int* x = 0;",6302              varDecl(hasName("x"),6303                      hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(6304                          hasUnqualifiedLoc(loc(asString("int"))))))))));6305}6306 6307TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {6308  EXPECT_TRUE(6309      matches("const int f() { return 5; }",6310              functionDecl(hasName("f"),6311                           hasReturnTypeLoc(qualifiedTypeLoc(6312                               hasUnqualifiedLoc(loc(asString("int"))))))));6313}6314 6315TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {6316  EXPECT_TRUE(matches(6317      "const float x = 0;",6318      varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6319                                hasUnqualifiedLoc(loc(asString("float"))))))));6320}6321 6322TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {6323  EXPECT_TRUE(notMatches(6324      "int x = 0;",6325      varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6326                                hasUnqualifiedLoc(loc(asString("float"))))))));6327}6328 6329TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {6330  EXPECT_TRUE(notMatches(6331      "const int x = 0;",6332      varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6333                                hasUnqualifiedLoc(loc(asString("float"))))))));6334}6335 6336TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {6337  EXPECT_TRUE(matches(6338      "int f() { return 5; }",6339      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));6340}6341 6342TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {6343  EXPECT_TRUE(matches(6344      "float f() { return 5.0; }",6345      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));6346}6347 6348TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {6349  EXPECT_TRUE(matches(6350      "void f() {}",6351      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));6352}6353 6354TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {6355  EXPECT_TRUE(notMatches(6356      "int f() { return 5; }",6357      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));6358}6359 6360TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {6361  EXPECT_TRUE(notMatches(6362      "float f() { return 5.0; }",6363      functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));6364}6365 6366TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {6367  auto matcher = varDecl(hasName("x"),6368                         hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));6369  EXPECT_TRUE(matches("int* x;", matcher));6370  EXPECT_TRUE(matches("float* x;", matcher));6371  EXPECT_TRUE(matches("char* x;", matcher));6372  EXPECT_TRUE(matches("void* x;", matcher));6373}6374 6375TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {6376  auto matcher = varDecl(hasName("x"),6377                         hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));6378  EXPECT_TRUE(notMatches("int x;", matcher));6379  EXPECT_TRUE(notMatches("float x;", matcher));6380  EXPECT_TRUE(notMatches("char x;", matcher));6381}6382 6383TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {6384  EXPECT_TRUE(6385      matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));6386}6387 6388TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {6389  EXPECT_TRUE(matches("int** x;",6390                      pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));6391}6392 6393TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {6394  EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(6395                                      hasPointeeLoc(loc(asString("int"))))))));6396}6397 6398TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {6399  EXPECT_TRUE(matches("float* x;",6400                      pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));6401}6402 6403TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {6404  EXPECT_TRUE(notMatches("float* x;",6405                         pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));6406}6407 6408TEST(HasPointeeLoc, FloatPointeeDoesNotBindToTypeLocPointingToInt) {6409  EXPECT_TRUE(notMatches(6410      "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));6411}6412 6413TEST(HasReferentLoc, BindsToAnyReferentTypeLoc) {6414  auto matcher = varDecl(6415      hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));6416  EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher));6417  EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher));6418  EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher));6419  EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher));6420  EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher));6421}6422 6423TEST(HasReferentLoc, DoesNotBindToTypeLocWithoutReferent) {6424  auto matcher = varDecl(6425      hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));6426  EXPECT_TRUE(notMatches("int r;", matcher));6427  EXPECT_TRUE(notMatches("int r = 3;", matcher));6428  EXPECT_TRUE(notMatches("const int r = 3;", matcher));6429  EXPECT_TRUE(notMatches("int* r;", matcher));6430  EXPECT_TRUE(notMatches("float r;", matcher));6431  EXPECT_TRUE(notMatches("char r;", matcher));6432}6433 6434TEST(HasReferentLoc, BindsToAnyRvalueReference) {6435  auto matcher = varDecl(6436      hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));6437  EXPECT_TRUE(matches("int&& r = 3;", matcher));6438  EXPECT_TRUE(matches("auto&& r = 3;", matcher));6439  EXPECT_TRUE(matches("float&& r = 3.0;", matcher));6440}6441 6442TEST(HasReferentLoc, BindsToIntReferenceTypeLoc) {6443  EXPECT_TRUE(matches("int rr = 3; int& r = rr;",6444                      referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));6445}6446 6447TEST(HasReferentLoc, BindsToIntRvalueReferenceTypeLoc) {6448  EXPECT_TRUE(matches("int&& r = 3;",6449                      referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));6450}6451 6452TEST(HasReferentLoc, BindsToFloatReferenceTypeLoc) {6453  EXPECT_TRUE(6454      matches("float rr = 3.0; float& r = rr;",6455              referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));6456}6457 6458TEST(HasReferentLoc, BindsToParameterWithIntReferenceTypeLoc) {6459  EXPECT_TRUE(matches(6460      "int f(int& r) { return r; }",6461      parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(6462                                    hasReferentLoc(loc(asString("int"))))))));6463}6464 6465TEST(HasReferentLoc, IntReferenceDoesNotBindToFloatReferenceTypeLoc) {6466  EXPECT_TRUE(6467      notMatches("float rr = 3.0; float& r = rr;",6468                 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));6469}6470 6471TEST(HasReferentLoc, FloatReferenceDoesNotBindToIntReferenceTypeLoc) {6472  EXPECT_TRUE(6473      notMatches("int rr = 3; int& r = rr;",6474                 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));6475}6476 6477TEST(HasReferentLoc, DoesNotBindToParameterWithoutIntReferenceTypeLoc) {6478  EXPECT_TRUE(notMatches(6479      "int f(int r) { return r; }",6480      parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(6481                                    hasReferentLoc(loc(asString("int"))))))));6482}6483 6484TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {6485  EXPECT_TRUE(6486      matches("template<typename T> class A {}; A<int> a;",6487              varDecl(hasName("a"), hasTypeLoc(templateSpecializationTypeLoc(6488                                        hasAnyTemplateArgumentLoc(hasTypeLoc(6489                                            loc(asString("int")))))))));6490}6491 6492TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {6493  EXPECT_TRUE(6494      matches("template<typename T> class A {}; A<double> a;",6495              varDecl(hasName("a"), hasTypeLoc(templateSpecializationTypeLoc(6496                                        hasAnyTemplateArgumentLoc(hasTypeLoc(6497                                            loc(asString("double")))))))));6498}6499 6500TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {6501  EXPECT_TRUE(matches(6502      "template<typename T> class A {}; template<> class A<int> {};",6503      classTemplateSpecializationDecl(6504          hasName("A"),6505          hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));6506}6507 6508TEST(HasAnyTemplateArgumentLoc,6509     BindsToExplicitSpecializationWithDoubleArgument) {6510  EXPECT_TRUE(matches(6511      "template<typename T> class A {}; template<> class A<double> {};",6512      classTemplateSpecializationDecl(6513          hasName("A"),6514          hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));6515}6516 6517TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {6518  auto code = R"(6519  template<typename T, typename U> class A {};6520  template<> class A<double, int> {};6521  )";6522  EXPECT_TRUE(6523      matches(code, classTemplateSpecializationDecl(6524                        hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(6525                                          loc(asString("double")))))));6526 6527  EXPECT_TRUE(matches(6528      code, classTemplateSpecializationDecl(6529                hasName("A"),6530                hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));6531}6532 6533TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {6534  EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",6535                         classTemplateSpecializationDecl(6536                             hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(6537                                               loc(asString("double")))))));6538}6539 6540TEST(HasAnyTemplateArgumentLoc,6541     DoesNotBindToExplicitSpecializationWithIntArgument) {6542  EXPECT_TRUE(notMatches(6543      "template<typename T> class A {}; template<> class A<int> {};",6544      classTemplateSpecializationDecl(6545          hasName("A"),6546          hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));6547}6548 6549TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {6550  EXPECT_TRUE(matches(6551      "template<typename T> class A {}; A<int> a;",6552      varDecl(hasName("a"),6553              hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(6554                  0, hasTypeLoc(loc(asString("int")))))))));6555}6556 6557TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {6558  EXPECT_TRUE(matches(6559      "template<typename T> class A {}; A<double> a;",6560      varDecl(hasName("a"),6561              hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(6562                  0, hasTypeLoc(loc(asString("double")))))))));6563}6564 6565TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {6566  EXPECT_TRUE(notMatches(6567      "template<typename T> class A {}; A<int> a;",6568      varDecl(hasName("a"),6569              hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(6570                  0, hasTypeLoc(loc(asString("double")))))))));6571}6572 6573TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {6574  EXPECT_TRUE(matches(6575      "template<typename T> class A {}; template<> class A<int> {};",6576      classTemplateSpecializationDecl(6577          hasName("A"),6578          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));6579}6580 6581TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {6582  EXPECT_TRUE(matches(6583      "template<typename T> class A {}; template<> class A<double> {};",6584      classTemplateSpecializationDecl(6585          hasName("A"),6586          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));6587}6588 6589TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {6590  auto code = R"(6591  template<typename T, typename U> class A {};6592  template<> class A<double, int> {};6593  )";6594  EXPECT_TRUE(matches(6595      code, classTemplateSpecializationDecl(6596                hasName("A"), hasTemplateArgumentLoc(6597                                  0, hasTypeLoc(loc(asString("double")))))));6598  EXPECT_TRUE(matches(6599      code, classTemplateSpecializationDecl(6600                hasName("A"),6601                hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));6602}6603 6604TEST(HasTemplateArgumentLoc,6605     DoesNotBindToExplicitSpecializationWithIntArgument) {6606  EXPECT_TRUE(notMatches(6607      "template<typename T> class A {}; template<> class A<int> {};",6608      classTemplateSpecializationDecl(6609          hasName("A"),6610          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));6611}6612 6613TEST(HasTemplateArgumentLoc,6614     DoesNotBindToSpecializationWithMisplacedArguments) {6615  auto code = R"(6616  template<typename T, typename U> class A {};6617  template<> class A<double, int> {};6618  )";6619  EXPECT_TRUE(notMatches(6620      code, classTemplateSpecializationDecl(6621                hasName("A"), hasTemplateArgumentLoc(6622                                  1, hasTypeLoc(loc(asString("double")))))));6623  EXPECT_TRUE(notMatches(6624      code, classTemplateSpecializationDecl(6625                hasName("A"),6626                hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));6627}6628 6629TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {6630  auto code = R"(6631  template<typename T, typename U> class A {};6632  template<> class A<double, int> {};6633  )";6634  EXPECT_TRUE(notMatches(6635      code, classTemplateSpecializationDecl(6636                hasName("A"), hasTemplateArgumentLoc(6637                                  -1, hasTypeLoc(loc(asString("double")))))));6638  EXPECT_TRUE(notMatches(6639      code, classTemplateSpecializationDecl(6640                hasName("A"), hasTemplateArgumentLoc(6641                                  100, hasTypeLoc(loc(asString("int")))))));6642}6643 6644TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {6645  EXPECT_TRUE(matches(R"(6646      template<typename T> T f(T t) { return t; }6647      int g() { int i = f<int>(3); return i; }6648      )",6649                      declRefExpr(to(functionDecl(hasName("f"))),6650                                  hasTemplateArgumentLoc(6651                                      0, hasTypeLoc(loc(asString("int")))))));6652}6653 6654TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithDoubleArgument) {6655  EXPECT_TRUE(matches(6656      R"(6657      template<typename T> T f(T t) { return t; }6658      double g() { double i = f<double>(3.0); return i; }6659      )",6660      declRefExpr(6661          to(functionDecl(hasName("f"))),6662          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));6663}6664 6665TEST(HasTemplateArgumentLoc, DoesNotBindToDeclRefExprWithDoubleArgument) {6666  EXPECT_TRUE(notMatches(6667      R"(6668      template<typename T> T f(T t) { return t; }6669      double g() { double i = f<double>(3.0); return i; }6670      )",6671      declRefExpr(6672          to(functionDecl(hasName("f"))),6673          hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));6674}6675 6676TEST(HasNamedTypeLoc, BindsToElaboratedObjectDeclaration) {6677  EXPECT_TRUE(matches(6678      R"(6679      template <typename T>6680      class C {};6681      class C<int> c;6682      )",6683      varDecl(hasName("c"),6684              hasTypeLoc(templateSpecializationTypeLoc(6685                  hasAnyTemplateArgumentLoc(templateArgumentLoc()))))));6686}6687 6688TEST(HasNamedTypeLoc, BindsToNonElaboratedObjectDeclaration) {6689  EXPECT_TRUE(matches(6690      R"(6691      template <typename T>6692      class C {};6693      C<int> c;6694      )",6695      varDecl(hasName("c"),6696              hasTypeLoc(templateSpecializationTypeLoc(6697                  hasAnyTemplateArgumentLoc(templateArgumentLoc()))))));6698}6699 6700} // namespace ast_matchers6701} // namespace clang6702