brintos

brintos / llvm-project-archived public Read only

0
0
Text · 45.7 KiB · bcbf01b Raw
2084 lines · cpp
1//===- unittests/AST/ASTTraverserTest.h------------------------------------===//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 "clang/AST/ASTContext.h"10#include "clang/AST/ASTNodeTraverser.h"11#include "clang/AST/TextNodeDumper.h"12#include "clang/ASTMatchers/ASTMatchFinder.h"13#include "clang/ASTMatchers/ASTMatchers.h"14#include "clang/Tooling/Tooling.h"15#include "gmock/gmock.h"16#include "gtest/gtest.h"17 18using namespace clang::tooling;19using namespace clang::ast_matchers;20 21namespace clang {22 23class NodeTreePrinter : public TextTreeStructure {24  llvm::raw_ostream &OS;25 26public:27  NodeTreePrinter(llvm::raw_ostream &OS)28      : TextTreeStructure(OS, /* showColors */ false), OS(OS) {}29 30  void Visit(const Decl *D) {31    if (!D) {32      OS << "<<<NULL>>>";33      return;34    }35    OS << D->getDeclKindName() << "Decl";36    if (auto *ND = dyn_cast<NamedDecl>(D)) {37      OS << " '" << ND->getDeclName() << "'";38    }39  }40 41  void Visit(const Stmt *S) {42    if (!S) {43      OS << "<<<NULL>>>";44      return;45    }46    OS << S->getStmtClassName();47    if (auto *E = dyn_cast<DeclRefExpr>(S)) {48      OS << " '" << E->getDecl()->getDeclName() << "'";49    }50  }51 52  void Visit(QualType QT) {53    OS << "QualType " << QT.split().Quals.getAsString();54  }55 56  void Visit(const Type *T) { OS << T->getTypeClassName() << "Type"; }57 58  void Visit(const comments::Comment *C, const comments::FullComment *FC) {59    OS << C->getCommentKindName();60  }61 62  void Visit(const CXXCtorInitializer *Init) {63    OS << "CXXCtorInitializer";64    if (const auto *F = Init->getAnyMember()) {65      OS << " '" << F->getNameAsString() << "'";66    } else if (auto const *TSI = Init->getTypeSourceInfo()) {67      OS << " '" << TSI->getType() << "'";68    }69  }70 71  void Visit(const Attr *A) {72    switch (A->getKind()) {73#define ATTR(X)                                                                \74  case attr::X:                                                                \75    OS << #X;                                                                  \76    break;77#include "clang/Basic/AttrList.inc"78    }79    OS << "Attr";80  }81 82  void Visit(const OMPClause *C) { OS << "OMPClause"; }83  void Visit(const TemplateArgument &A, SourceRange R = {},84             const Decl *From = nullptr, const char *Label = nullptr) {85    OS << "TemplateArgument";86    switch (A.getKind()) {87    case TemplateArgument::Type: {88      OS << " type " << A.getAsType();89      break;90    }91    default:92      break;93    }94  }95 96  template <typename... T> void Visit(T...) {}97};98 99class TestASTDumper : public ASTNodeTraverser<TestASTDumper, NodeTreePrinter> {100 101  NodeTreePrinter MyNodeRecorder;102 103public:104  TestASTDumper(llvm::raw_ostream &OS) : MyNodeRecorder(OS) {}105  NodeTreePrinter &doGetNodeDelegate() { return MyNodeRecorder; }106};107 108template <typename... NodeType> std::string dumpASTString(NodeType &&... N) {109  std::string Buffer;110  llvm::raw_string_ostream OS(Buffer);111 112  TestASTDumper Dumper(OS);113 114  OS << "\n";115 116  Dumper.Visit(std::forward<NodeType &&>(N)...);117 118  return Buffer;119}120 121template <typename... NodeType>122std::string dumpASTString(TraversalKind TK, NodeType &&... N) {123  std::string Buffer;124  llvm::raw_string_ostream OS(Buffer);125 126  TestASTDumper Dumper(OS);127  Dumper.SetTraversalKind(TK);128 129  OS << "\n";130 131  Dumper.Visit(std::forward<NodeType &&>(N)...);132 133  return Buffer;134}135 136const FunctionDecl *getFunctionNode(clang::ASTUnit *AST,137                                    const std::string &Name) {138  auto Result = ast_matchers::match(functionDecl(hasName(Name)).bind("fn"),139                                    AST->getASTContext());140  EXPECT_EQ(Result.size(), 1u);141  return Result[0].getNodeAs<FunctionDecl>("fn");142}143 144template <typename T> struct Verifier {145  static void withDynNode(T Node, const std::string &DumpString) {146    EXPECT_EQ(dumpASTString(DynTypedNode::create(Node)), DumpString);147  }148};149 150template <typename T> struct Verifier<T *> {151  static void withDynNode(T *Node, const std::string &DumpString) {152    EXPECT_EQ(dumpASTString(DynTypedNode::create(*Node)), DumpString);153  }154};155 156template <typename T>157void verifyWithDynNode(T Node, const std::string &DumpString) {158  EXPECT_EQ(dumpASTString(Node), DumpString);159 160  Verifier<T>::withDynNode(Node, DumpString);161}162 163TEST(Traverse, Dump) {164 165  auto AST = buildASTFromCode(R"cpp(166struct A {167  int m_number;168 169  /// CTor170  A() : m_number(42) {}171 172  [[nodiscard]] const int func() {173    return 42;174  }175 176};177 178template<typename T>179struct templ180{181};182 183template<>184struct templ<int>185{186};187 188void parmvardecl_attr(struct A __attribute__((address_space(19)))*);189 190)cpp");191 192  const FunctionDecl *Func = getFunctionNode(AST.get(), "func");193 194  verifyWithDynNode(Func,195                    R"cpp(196CXXMethodDecl 'func'197|-CompoundStmt198| `-ReturnStmt199|   `-IntegerLiteral200`-WarnUnusedResultAttr201)cpp");202 203  Stmt *Body = Func->getBody();204 205  verifyWithDynNode(Body,206                    R"cpp(207CompoundStmt208`-ReturnStmt209  `-IntegerLiteral210)cpp");211 212  QualType QT = Func->getType();213 214  verifyWithDynNode(QT,215                    R"cpp(216FunctionProtoType217`-QualType const218  `-BuiltinType219)cpp");220 221  const FunctionDecl *CTorFunc = getFunctionNode(AST.get(), "A");222 223  verifyWithDynNode(CTorFunc->getType(),224                    R"cpp(225FunctionProtoType226`-BuiltinType227)cpp");228 229  Attr *A = *Func->attr_begin();230 231  {232    std::string expectedString = R"cpp(233WarnUnusedResultAttr234)cpp";235 236    EXPECT_EQ(dumpASTString(A), expectedString);237  }238 239  auto *CTor = dyn_cast<CXXConstructorDecl>(CTorFunc);240  const CXXCtorInitializer *Init = *CTor->init_begin();241 242  verifyWithDynNode(Init,243                    R"cpp(244CXXCtorInitializer 'm_number'245`-IntegerLiteral246)cpp");247 248  const comments::FullComment *Comment =249      AST->getASTContext().getLocalCommentForDeclUncached(CTorFunc);250  {251    std::string expectedString = R"cpp(252FullComment253`-ParagraphComment254  `-TextComment255)cpp";256    EXPECT_EQ(dumpASTString(Comment, Comment), expectedString);257  }258 259  auto Result = ast_matchers::match(260      classTemplateSpecializationDecl(hasName("templ")).bind("fn"),261      AST->getASTContext());262  EXPECT_EQ(Result.size(), 1u);263  auto Templ = Result[0].getNodeAs<ClassTemplateSpecializationDecl>("fn");264 265  TemplateArgument TA = Templ->getTemplateArgs()[0];266 267  verifyWithDynNode(TA,268                    R"cpp(269TemplateArgument type int270`-BuiltinType271)cpp");272 273  Func = getFunctionNode(AST.get(), "parmvardecl_attr");274 275  const auto *Parm = Func->getParamDecl(0);276  const auto TL = Parm->getTypeSourceInfo()->getTypeLoc();277  ASSERT_TRUE(TL.getType()->isPointerType());278 279  const auto ATL = TL.getNextTypeLoc().getAs<AttributedTypeLoc>();280  const auto *AS = cast<AddressSpaceAttr>(ATL.getAttr());281  EXPECT_EQ(toTargetAddressSpace(static_cast<LangAS>(AS->getAddressSpace())),282            19u);283}284 285TEST(Traverse, IgnoreUnlessSpelledInSourceVars) {286 287  auto AST = buildASTFromCodeWithArgs(R"cpp(288 289struct String290{291    String(const char*, int = -1) {}292 293    int overloaded() const;294    int& overloaded();295};296 297void stringConstruct()298{299    String s = "foo";300    s = "bar";301}302 303void overloadCall()304{305   String s = "foo";306   (s).overloaded();307}308 309struct C1 {};310struct C2 { operator C1(); };311 312void conversionOperator()313{314    C2* c2;315    C1 c1 = (*c2);316}317 318template <unsigned alignment>319void template_test() {320  static_assert(alignment, "");321}322void actual_template_test() {323  template_test<4>();324}325 326struct OneParamCtor {327  explicit OneParamCtor(int);328};329struct TwoParamCtor {330  explicit TwoParamCtor(int, int);331};332 333void varDeclCtors() {334  {335  auto var1 = OneParamCtor(5);336  auto var2 = TwoParamCtor(6, 7);337  }338  {339  OneParamCtor var3(5);340  TwoParamCtor var4(6, 7);341  }342  int i = 0;343  {344  auto var5 = OneParamCtor(i);345  auto var6 = TwoParamCtor(i, 7);346  }347  {348  OneParamCtor var7(i);349  TwoParamCtor var8(i, 7);350  }351}352 353)cpp", {"-std=c++14"});354 355  {356    auto FN =357        ast_matchers::match(functionDecl(hasName("stringConstruct")).bind("fn"),358                            AST->getASTContext());359    EXPECT_EQ(FN.size(), 1u);360 361    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Decl>("fn")),362              R"cpp(363FunctionDecl 'stringConstruct'364`-CompoundStmt365  |-DeclStmt366  | `-VarDecl 's'367  |   `-ExprWithCleanups368  |     `-CXXConstructExpr369  |       `-MaterializeTemporaryExpr370  |         `-ImplicitCastExpr371  |           `-CXXConstructExpr372  |             |-ImplicitCastExpr373  |             | `-StringLiteral374  |             `-CXXDefaultArgExpr375  |               `-UnaryOperator376  |                 `-IntegerLiteral377  `-ExprWithCleanups378    `-CXXOperatorCallExpr379      |-ImplicitCastExpr380      | `-DeclRefExpr 'operator='381      |-DeclRefExpr 's'382      `-MaterializeTemporaryExpr383        `-CXXConstructExpr384          |-ImplicitCastExpr385          | `-StringLiteral386          `-CXXDefaultArgExpr387            `-UnaryOperator388              `-IntegerLiteral389)cpp");390 391    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,392                            FN[0].getNodeAs<Decl>("fn")),393              R"cpp(394FunctionDecl 'stringConstruct'395`-CompoundStmt396  |-DeclStmt397  | `-VarDecl 's'398  |   `-StringLiteral399  `-CXXOperatorCallExpr400    |-DeclRefExpr 'operator='401    |-DeclRefExpr 's'402    `-StringLiteral403)cpp");404  }405 406  {407    auto FN =408        ast_matchers::match(functionDecl(hasName("overloadCall")).bind("fn"),409                            AST->getASTContext());410    EXPECT_EQ(FN.size(), 1u);411 412    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Decl>("fn")),413              R"cpp(414FunctionDecl 'overloadCall'415`-CompoundStmt416  |-DeclStmt417  | `-VarDecl 's'418  |   `-ExprWithCleanups419  |     `-CXXConstructExpr420  |       `-MaterializeTemporaryExpr421  |         `-ImplicitCastExpr422  |           `-CXXConstructExpr423  |             |-ImplicitCastExpr424  |             | `-StringLiteral425  |             `-CXXDefaultArgExpr426  |               `-UnaryOperator427  |                 `-IntegerLiteral428  `-CXXMemberCallExpr429    `-MemberExpr430      `-ParenExpr431        `-DeclRefExpr 's'432)cpp");433 434    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,435                            FN[0].getNodeAs<Decl>("fn")),436              R"cpp(437FunctionDecl 'overloadCall'438`-CompoundStmt439  |-DeclStmt440  | `-VarDecl 's'441  |   `-StringLiteral442  `-CXXMemberCallExpr443    `-MemberExpr444      `-DeclRefExpr 's'445)cpp");446  }447 448  {449    auto FN = ast_matchers::match(450        functionDecl(hasName("conversionOperator"),451                     hasDescendant(varDecl(hasName("c1")).bind("var"))),452        AST->getASTContext());453    EXPECT_EQ(FN.size(), 1u);454 455    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Decl>("var")),456              R"cpp(457VarDecl 'c1'458`-ExprWithCleanups459  `-CXXConstructExpr460    `-MaterializeTemporaryExpr461      `-ImplicitCastExpr462        `-CXXMemberCallExpr463          `-MemberExpr464            `-ParenExpr465              `-UnaryOperator466                `-ImplicitCastExpr467                  `-DeclRefExpr 'c2'468)cpp");469 470    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,471                            FN[0].getNodeAs<Decl>("var")),472              R"cpp(473VarDecl 'c1'474`-UnaryOperator475  `-DeclRefExpr 'c2'476)cpp");477  }478 479  {480    auto FN = ast_matchers::match(481        functionDecl(hasName("template_test"),482                     hasDescendant(staticAssertDecl().bind("staticAssert"))),483        AST->getASTContext());484    EXPECT_EQ(FN.size(), 2u);485 486    EXPECT_EQ(dumpASTString(TK_AsIs, FN[1].getNodeAs<Decl>("staticAssert")),487              R"cpp(488StaticAssertDecl489|-ImplicitCastExpr490| `-SubstNonTypeTemplateParmExpr491|   |-NonTypeTemplateParmDecl 'alignment'492|   `-IntegerLiteral493`-StringLiteral494)cpp");495 496    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,497                            FN[1].getNodeAs<Decl>("staticAssert")),498              R"cpp(499StaticAssertDecl500|-IntegerLiteral501`-StringLiteral502)cpp");503  }504 505  auto varChecker = [&AST](StringRef varName, StringRef SemanticDump,506                           StringRef SyntacticDump) {507    auto FN = ast_matchers::match(508        functionDecl(509            hasName("varDeclCtors"),510            forEachDescendant(varDecl(hasName(varName)).bind("varDeclCtor"))),511        AST->getASTContext());512    EXPECT_EQ(FN.size(), 1u);513 514    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Decl>("varDeclCtor")),515              SemanticDump);516 517    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,518                            FN[0].getNodeAs<Decl>("varDeclCtor")),519              SyntacticDump);520  };521 522  varChecker("var1",523             R"cpp(524VarDecl 'var1'525`-ExprWithCleanups526  `-CXXConstructExpr527    `-MaterializeTemporaryExpr528      `-CXXFunctionalCastExpr529        `-CXXConstructExpr530          `-IntegerLiteral531)cpp",532             R"cpp(533VarDecl 'var1'534`-CXXConstructExpr535  `-IntegerLiteral536)cpp");537 538  varChecker("var2",539             R"cpp(540VarDecl 'var2'541`-ExprWithCleanups542  `-CXXConstructExpr543    `-MaterializeTemporaryExpr544      `-CXXTemporaryObjectExpr545        |-IntegerLiteral546        `-IntegerLiteral547)cpp",548             R"cpp(549VarDecl 'var2'550`-CXXTemporaryObjectExpr551  |-IntegerLiteral552  `-IntegerLiteral553)cpp");554 555  varChecker("var3",556             R"cpp(557VarDecl 'var3'558`-CXXConstructExpr559  `-IntegerLiteral560)cpp",561             R"cpp(562VarDecl 'var3'563`-CXXConstructExpr564  `-IntegerLiteral565)cpp");566 567  varChecker("var4",568             R"cpp(569VarDecl 'var4'570`-CXXConstructExpr571  |-IntegerLiteral572  `-IntegerLiteral573)cpp",574             R"cpp(575VarDecl 'var4'576`-CXXConstructExpr577  |-IntegerLiteral578  `-IntegerLiteral579)cpp");580 581  varChecker("var5",582             R"cpp(583VarDecl 'var5'584`-ExprWithCleanups585  `-CXXConstructExpr586    `-MaterializeTemporaryExpr587      `-CXXFunctionalCastExpr588        `-CXXConstructExpr589          `-ImplicitCastExpr590            `-DeclRefExpr 'i'591)cpp",592             R"cpp(593VarDecl 'var5'594`-CXXConstructExpr595  `-DeclRefExpr 'i'596)cpp");597 598  varChecker("var6",599             R"cpp(600VarDecl 'var6'601`-ExprWithCleanups602  `-CXXConstructExpr603    `-MaterializeTemporaryExpr604      `-CXXTemporaryObjectExpr605        |-ImplicitCastExpr606        | `-DeclRefExpr 'i'607        `-IntegerLiteral608)cpp",609             R"cpp(610VarDecl 'var6'611`-CXXTemporaryObjectExpr612  |-DeclRefExpr 'i'613  `-IntegerLiteral614)cpp");615 616  varChecker("var7",617             R"cpp(618VarDecl 'var7'619`-CXXConstructExpr620  `-ImplicitCastExpr621    `-DeclRefExpr 'i'622)cpp",623             R"cpp(624VarDecl 'var7'625`-CXXConstructExpr626  `-DeclRefExpr 'i'627)cpp");628 629  varChecker("var8",630             R"cpp(631VarDecl 'var8'632`-CXXConstructExpr633  |-ImplicitCastExpr634  | `-DeclRefExpr 'i'635  `-IntegerLiteral636)cpp",637             R"cpp(638VarDecl 'var8'639`-CXXConstructExpr640  |-DeclRefExpr 'i'641  `-IntegerLiteral642)cpp");643}644 645TEST(Traverse, IgnoreUnlessSpelledInSourceStructs) {646  auto AST = buildASTFromCode(R"cpp(647 648struct MyStruct {649  MyStruct();650  MyStruct(int i) {651    MyStruct();652  }653  ~MyStruct();654};655 656)cpp");657 658  auto BN = ast_matchers::match(659      cxxConstructorDecl(hasName("MyStruct"),660                         hasParameter(0, parmVarDecl(hasType(isInteger()))))661          .bind("ctor"),662      AST->getASTContext());663  EXPECT_EQ(BN.size(), 1u);664 665  EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,666                          BN[0].getNodeAs<Decl>("ctor")),667            R"cpp(668CXXConstructorDecl 'MyStruct'669|-ParmVarDecl 'i'670`-CompoundStmt671  `-CXXTemporaryObjectExpr672)cpp");673 674  EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("ctor")),675            R"cpp(676CXXConstructorDecl 'MyStruct'677|-ParmVarDecl 'i'678`-CompoundStmt679  `-ExprWithCleanups680    `-CXXBindTemporaryExpr681      `-CXXTemporaryObjectExpr682)cpp");683}684 685TEST(Traverse, IgnoreUnlessSpelledInSourceReturnStruct) {686 687  auto AST = buildASTFromCode(R"cpp(688struct Retval {689  Retval() {}690  ~Retval() {}691};692 693Retval someFun();694 695void foo()696{697    someFun();698}699)cpp");700 701  auto BN = ast_matchers::match(functionDecl(hasName("foo")).bind("fn"),702                                AST->getASTContext());703  EXPECT_EQ(BN.size(), 1u);704 705  EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,706                          BN[0].getNodeAs<Decl>("fn")),707            R"cpp(708FunctionDecl 'foo'709`-CompoundStmt710  `-CallExpr711    `-DeclRefExpr 'someFun'712)cpp");713 714  EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("fn")),715            R"cpp(716FunctionDecl 'foo'717`-CompoundStmt718  `-ExprWithCleanups719    `-CXXBindTemporaryExpr720      `-CallExpr721        `-ImplicitCastExpr722          `-DeclRefExpr 'someFun'723)cpp");724}725 726TEST(Traverse, IgnoreUnlessSpelledInSourceReturns) {727 728  auto AST = buildASTFromCodeWithArgs(R"cpp(729 730struct A731{732};733 734struct B735{736  B(int);737  B(A const& a);738  B();739};740 741struct C742{743  operator B();744};745 746B func1() {747  return 42;748}749 750B func2() {751  return B{42};752}753 754B func3() {755  return B(42);756}757 758B func4() {759  return B();760}761 762B func5() {763  return B{};764}765 766B func6() {767  return C();768}769 770B func7() {771  return A();772}773 774B func8() {775  return C{};776}777 778B func9() {779  return A{};780}781 782B func10() {783  A a;784  return a;785}786 787B func11() {788  B b;789  return b;790}791 792B func12() {793  C c;794  return c;795}796 797)cpp", {"-std=c++14"});798 799  auto getFunctionNode = [&AST](const std::string &name) {800    auto BN = ast_matchers::match(functionDecl(hasName(name)).bind("fn"),801                                  AST->getASTContext());802    EXPECT_EQ(BN.size(), 1u);803    return BN[0].getNodeAs<Decl>("fn");804  };805 806  {807    auto FN = getFunctionNode("func1");808    llvm::StringRef Expected = R"cpp(809FunctionDecl 'func1'810`-CompoundStmt811  `-ReturnStmt812    `-ExprWithCleanups813      `-CXXConstructExpr814        `-MaterializeTemporaryExpr815          `-ImplicitCastExpr816            `-CXXConstructExpr817              `-IntegerLiteral818)cpp";819 820    EXPECT_EQ(dumpASTString(TK_AsIs, FN), Expected);821 822    Expected = R"cpp(823FunctionDecl 'func1'824`-CompoundStmt825  `-ReturnStmt826    `-IntegerLiteral827)cpp";828    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, FN), Expected);829  }830 831  llvm::StringRef Expected = R"cpp(832FunctionDecl 'func2'833`-CompoundStmt834  `-ReturnStmt835    `-CXXTemporaryObjectExpr836      `-IntegerLiteral837)cpp";838  EXPECT_EQ(839      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func2")),840      Expected);841 842  Expected = R"cpp(843FunctionDecl 'func3'844`-CompoundStmt845  `-ReturnStmt846    `-CXXConstructExpr847      `-IntegerLiteral848)cpp";849  EXPECT_EQ(850      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func3")),851      Expected);852 853  Expected = R"cpp(854FunctionDecl 'func4'855`-CompoundStmt856  `-ReturnStmt857    `-CXXTemporaryObjectExpr858)cpp";859  EXPECT_EQ(860      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func4")),861      Expected);862 863  Expected = R"cpp(864FunctionDecl 'func5'865`-CompoundStmt866  `-ReturnStmt867    `-CXXTemporaryObjectExpr868)cpp";869  EXPECT_EQ(870      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func5")),871      Expected);872 873  Expected = R"cpp(874FunctionDecl 'func6'875`-CompoundStmt876  `-ReturnStmt877    `-CXXTemporaryObjectExpr878)cpp";879  EXPECT_EQ(880      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func6")),881      Expected);882 883  Expected = R"cpp(884FunctionDecl 'func7'885`-CompoundStmt886  `-ReturnStmt887    `-CXXTemporaryObjectExpr888)cpp";889  EXPECT_EQ(890      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func7")),891      Expected);892 893  Expected = R"cpp(894FunctionDecl 'func8'895`-CompoundStmt896  `-ReturnStmt897    `-CXXFunctionalCastExpr898      `-InitListExpr899)cpp";900  EXPECT_EQ(901      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func8")),902      Expected);903 904  Expected = R"cpp(905FunctionDecl 'func9'906`-CompoundStmt907  `-ReturnStmt908    `-CXXFunctionalCastExpr909      `-InitListExpr910)cpp";911  EXPECT_EQ(912      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func9")),913      Expected);914 915  Expected = R"cpp(916FunctionDecl 'func10'917`-CompoundStmt918  |-DeclStmt919  | `-VarDecl 'a'920  |   `-CXXConstructExpr921  `-ReturnStmt922    `-DeclRefExpr 'a'923)cpp";924  EXPECT_EQ(925      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func10")),926      Expected);927 928  Expected = R"cpp(929FunctionDecl 'func11'930`-CompoundStmt931  |-DeclStmt932  | `-VarDecl 'b'933  |   `-CXXConstructExpr934  `-ReturnStmt935    `-DeclRefExpr 'b'936)cpp";937  EXPECT_EQ(938      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func11")),939      Expected);940 941  Expected = R"cpp(942FunctionDecl 'func12'943`-CompoundStmt944  |-DeclStmt945  | `-VarDecl 'c'946  |   `-CXXConstructExpr947  `-ReturnStmt948    `-DeclRefExpr 'c'949)cpp";950  EXPECT_EQ(951      dumpASTString(TK_IgnoreUnlessSpelledInSource, getFunctionNode("func12")),952      Expected);953}954 955TEST(Traverse, LambdaUnlessSpelledInSource) {956 957  auto AST =958      buildASTFromCodeWithArgs(R"cpp(959 960void captures() {961  int a = 0;962  int b = 0;963  int d = 0;964  int f = 0;965 966  [a, &b, c = d, &e = f](int g, int h = 42) {};967}968 969void templated() {970  int a = 0;971  [a]<typename T>(T t) {};972}973 974struct SomeStruct {975    int a = 0;976    void capture_this() {977        [this]() {};978    }979    void capture_this_copy() {980        [self = *this]() {};981    }982};983)cpp",984                               {"-Wno-unused-value", "-Wno-c++2a-extensions"});985 986  auto getLambdaNode = [&AST](const std::string &name) {987    auto BN = ast_matchers::match(988        lambdaExpr(hasAncestor(functionDecl(hasName(name)))).bind("lambda"),989        AST->getASTContext());990    EXPECT_EQ(BN.size(), 1u);991    return BN[0].getNodeAs<LambdaExpr>("lambda");992  };993 994  {995    auto L = getLambdaNode("captures");996 997    llvm::StringRef Expected = R"cpp(998LambdaExpr999|-DeclRefExpr 'a'1000|-DeclRefExpr 'b'1001|-VarDecl 'c'1002| `-DeclRefExpr 'd'1003|-VarDecl 'e'1004| `-DeclRefExpr 'f'1005|-ParmVarDecl 'g'1006|-ParmVarDecl 'h'1007| `-IntegerLiteral1008`-CompoundStmt1009)cpp";1010    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, L), Expected);1011 1012    Expected = R"cpp(1013LambdaExpr1014|-CXXRecordDecl ''1015| |-CXXMethodDecl 'operator()'1016| | |-ParmVarDecl 'g'1017| | |-ParmVarDecl 'h'1018| | | `-IntegerLiteral1019| | `-CompoundStmt1020| |-FieldDecl ''1021| |-FieldDecl ''1022| |-FieldDecl ''1023| |-FieldDecl ''1024| `-CXXDestructorDecl '~(lambda at input.cc:9:3)'1025|-ImplicitCastExpr1026| `-DeclRefExpr 'a'1027|-DeclRefExpr 'b'1028|-ImplicitCastExpr1029| `-DeclRefExpr 'd'1030|-DeclRefExpr 'f'1031`-CompoundStmt1032)cpp";1033    EXPECT_EQ(dumpASTString(TK_AsIs, L), Expected);1034  }1035 1036  {1037    auto L = getLambdaNode("templated");1038 1039    llvm::StringRef Expected = R"cpp(1040LambdaExpr1041|-DeclRefExpr 'a'1042|-TemplateTypeParmDecl 'T'1043|-ParmVarDecl 't'1044`-CompoundStmt1045)cpp";1046    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, L), Expected);1047  }1048 1049  {1050    auto L = getLambdaNode("capture_this");1051 1052    llvm::StringRef Expected = R"cpp(1053LambdaExpr1054|-CXXThisExpr1055`-CompoundStmt1056)cpp";1057    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, L), Expected);1058  }1059 1060  {1061    auto L = getLambdaNode("capture_this_copy");1062 1063    llvm::StringRef Expected = R"cpp(1064LambdaExpr1065|-VarDecl 'self'1066| `-UnaryOperator1067|   `-CXXThisExpr1068`-CompoundStmt1069)cpp";1070    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, L), Expected);1071  }1072}1073 1074TEST(Traverse, IgnoreUnlessSpelledInSourceImplicit) {1075  {1076    auto AST = buildASTFromCode(R"cpp(1077int i = 0;1078)cpp");1079    const auto *TUDecl = AST->getASTContext().getTranslationUnitDecl();1080 1081    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, TUDecl),1082              R"cpp(1083TranslationUnitDecl1084`-VarDecl 'i'1085  `-IntegerLiteral1086)cpp");1087  }1088 1089  auto AST2 = buildASTFromCodeWithArgs(R"cpp(1090struct Simple {1091};1092struct Other {1093};1094 1095struct Record : Simple, Other {1096  Record() : Simple(), m_i(42) {}1097private:1098  int m_i;1099  int m_i2 = 42;1100  Simple m_s;1101};1102 1103struct NonTrivial {1104    NonTrivial() {}1105    NonTrivial(NonTrivial&) {}1106    NonTrivial& operator=(NonTrivial&) { return *this; }1107 1108    ~NonTrivial() {}1109};1110 1111struct ContainsArray {1112    NonTrivial arr[2];1113    int irr[2];1114    ContainsArray& operator=(ContainsArray &) = default;1115};1116 1117void copyIt()1118{1119    ContainsArray ca;1120    ContainsArray ca2;1121    ca2 = ca;1122}1123 1124void forLoop()1125{1126    int arr[2];1127    for (auto i : arr)1128    {1129 1130    }1131    for (auto& a = arr; auto i : a)1132    {1133 1134    }1135}1136 1137struct DefaultedAndDeleted {1138  NonTrivial nt;1139  DefaultedAndDeleted() = default;1140  ~DefaultedAndDeleted() = default;1141  DefaultedAndDeleted(DefaultedAndDeleted &) = default;1142  DefaultedAndDeleted& operator=(DefaultedAndDeleted &) = default;1143  DefaultedAndDeleted(DefaultedAndDeleted &&) = delete;1144  DefaultedAndDeleted& operator=(DefaultedAndDeleted &&) = delete;1145};1146 1147void copyIt2()1148{1149    DefaultedAndDeleted ca;1150    DefaultedAndDeleted ca2;1151    ca2 = ca;1152}1153 1154void hasDefaultArg(int i, int j = 0)1155{1156}1157void callDefaultArg()1158{1159  hasDefaultArg(42);1160}1161 1162void decomposition()1163{1164    int arr[3];1165    auto &[f, s, t] = arr;1166 1167    f = 42;1168}1169 1170typedef __typeof(sizeof(int)) size_t;1171 1172struct Pair1173{1174    int x, y;1175};1176 1177// Tuple-like structure with a `get` method that has a default argument.1178struct Pair21179{1180    int x, y;1181};1182 1183// Note: these utilities are required to force binding to tuple like structure1184namespace std1185{1186    template <typename E>1187    struct tuple_size1188    {1189    };1190 1191    template <>1192    struct tuple_size<Pair>1193    {1194        static constexpr size_t value = 2;1195    };1196 1197    template <>1198    struct tuple_size<Pair2>1199    {1200        static constexpr size_t value = 2;1201    };1202 1203    template <size_t I, class T>1204    struct tuple_element1205    {1206        using type = int;1207    };1208 1209};1210 1211template <size_t I>1212int &&get(Pair &&p);1213 1214template <size_t I>1215int &&get(Pair2 &&p, int unused = 0);1216 1217void decompTuple()1218{1219    Pair p{1, 2};1220    auto [a, b] = p;1221 1222    a = 3;1223 1224    auto [c, d] = Pair2{3, 4};1225}1226 1227)cpp",1228                                       {"-std=c++20"});1229 1230  {1231    auto BN = ast_matchers::match(1232        cxxRecordDecl(hasName("Record"), unless(isImplicit())).bind("rec"),1233        AST2->getASTContext());1234    EXPECT_EQ(BN.size(), 1u);1235 1236    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),1237              R"cpp(1238CXXRecordDecl 'Record'1239|-CXXRecordDecl 'Record'1240|-CXXConstructorDecl 'Record'1241| |-CXXCtorInitializer 'Simple'1242| | `-CXXConstructExpr1243| |-CXXCtorInitializer 'Other'1244| | `-CXXConstructExpr1245| |-CXXCtorInitializer 'm_i'1246| | `-IntegerLiteral1247| |-CXXCtorInitializer 'm_i2'1248| | `-CXXDefaultInitExpr1249| |   `-IntegerLiteral1250| |-CXXCtorInitializer 'm_s'1251| | `-CXXConstructExpr1252| `-CompoundStmt1253|-AccessSpecDecl1254|-FieldDecl 'm_i'1255|-FieldDecl 'm_i2'1256| `-IntegerLiteral1257`-FieldDecl 'm_s'1258)cpp");1259 1260    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1261                            BN[0].getNodeAs<Decl>("rec")),1262              R"cpp(1263CXXRecordDecl 'Record'1264|-CXXConstructorDecl 'Record'1265| |-CXXCtorInitializer 'Simple'1266| | `-CXXConstructExpr1267| |-CXXCtorInitializer 'm_i'1268| | `-IntegerLiteral1269| `-CompoundStmt1270|-AccessSpecDecl1271|-FieldDecl 'm_i'1272|-FieldDecl 'm_i2'1273| `-IntegerLiteral1274`-FieldDecl 'm_s'1275)cpp");1276  }1277  {1278    auto BN = ast_matchers::match(1279        cxxRecordDecl(hasName("ContainsArray"), unless(isImplicit()))1280            .bind("rec"),1281        AST2->getASTContext());1282    EXPECT_EQ(BN.size(), 1u);1283 1284    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),1285              R"cpp(1286CXXRecordDecl 'ContainsArray'1287|-CXXRecordDecl 'ContainsArray'1288|-FieldDecl 'arr'1289|-FieldDecl 'irr'1290|-CXXMethodDecl 'operator='1291| |-ParmVarDecl ''1292| `-CompoundStmt1293|   |-ForStmt1294|   | |-DeclStmt1295|   | | `-VarDecl '__i0'1296|   | |   `-IntegerLiteral1297|   | |-<<<NULL>>>1298|   | |-BinaryOperator1299|   | | |-ImplicitCastExpr1300|   | | | `-DeclRefExpr '__i0'1301|   | | `-IntegerLiteral1302|   | |-UnaryOperator1303|   | | `-DeclRefExpr '__i0'1304|   | `-CXXMemberCallExpr1305|   |   |-MemberExpr1306|   |   | `-ArraySubscriptExpr1307|   |   |   |-ImplicitCastExpr1308|   |   |   | `-MemberExpr1309|   |   |   |   `-CXXThisExpr1310|   |   |   `-ImplicitCastExpr1311|   |   |     `-DeclRefExpr '__i0'1312|   |   `-ArraySubscriptExpr1313|   |     |-ImplicitCastExpr1314|   |     | `-MemberExpr1315|   |     |   `-DeclRefExpr ''1316|   |     `-ImplicitCastExpr1317|   |       `-DeclRefExpr '__i0'1318|   |-CallExpr1319|   | |-ImplicitCastExpr1320|   | | `-DeclRefExpr '__builtin_memcpy'1321|   | |-ImplicitCastExpr1322|   | | `-UnaryOperator1323|   | |   `-MemberExpr1324|   | |     `-CXXThisExpr1325|   | |-ImplicitCastExpr1326|   | | `-UnaryOperator1327|   | |   `-MemberExpr1328|   | |     `-DeclRefExpr ''1329|   | `-IntegerLiteral1330|   `-ReturnStmt1331|     `-UnaryOperator1332|       `-CXXThisExpr1333|-CXXConstructorDecl 'ContainsArray'1334| `-ParmVarDecl ''1335|-CXXDestructorDecl '~ContainsArray'1336| `-CompoundStmt1337`-CXXConstructorDecl 'ContainsArray'1338  |-CXXCtorInitializer 'arr'1339  | `-CXXConstructExpr1340  `-CompoundStmt1341)cpp");1342 1343    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1344                            BN[0].getNodeAs<Decl>("rec")),1345              R"cpp(1346CXXRecordDecl 'ContainsArray'1347|-FieldDecl 'arr'1348|-FieldDecl 'irr'1349`-CXXMethodDecl 'operator='1350  `-ParmVarDecl ''1351)cpp");1352  }1353  {1354    auto BN = ast_matchers::match(functionDecl(hasName("forLoop")).bind("func"),1355                                  AST2->getASTContext());1356    EXPECT_EQ(BN.size(), 1u);1357 1358    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("func")),1359              R"cpp(1360FunctionDecl 'forLoop'1361`-CompoundStmt1362  |-DeclStmt1363  | `-VarDecl 'arr'1364  |-CXXForRangeStmt1365  | |-<<<NULL>>>1366  | |-DeclStmt1367  | | `-VarDecl '__range1'1368  | |   `-DeclRefExpr 'arr'1369  | |-DeclStmt1370  | | `-VarDecl '__begin1'1371  | |   `-ImplicitCastExpr1372  | |     `-DeclRefExpr '__range1'1373  | |-DeclStmt1374  | | `-VarDecl '__end1'1375  | |   `-BinaryOperator1376  | |     |-ImplicitCastExpr1377  | |     | `-DeclRefExpr '__range1'1378  | |     `-IntegerLiteral1379  | |-BinaryOperator1380  | | |-ImplicitCastExpr1381  | | | `-DeclRefExpr '__begin1'1382  | | `-ImplicitCastExpr1383  | |   `-DeclRefExpr '__end1'1384  | |-UnaryOperator1385  | | `-DeclRefExpr '__begin1'1386  | |-DeclStmt1387  | | `-VarDecl 'i'1388  | |   `-ImplicitCastExpr1389  | |     `-UnaryOperator1390  | |       `-ImplicitCastExpr1391  | |         `-DeclRefExpr '__begin1'1392  | `-CompoundStmt1393  `-CXXForRangeStmt1394    |-DeclStmt1395    | `-VarDecl 'a'1396    |   `-DeclRefExpr 'arr'1397    |-DeclStmt1398    | `-VarDecl '__range1'1399    |   `-DeclRefExpr 'a'1400    |-DeclStmt1401    | `-VarDecl '__begin1'1402    |   `-ImplicitCastExpr1403    |     `-DeclRefExpr '__range1'1404    |-DeclStmt1405    | `-VarDecl '__end1'1406    |   `-BinaryOperator1407    |     |-ImplicitCastExpr1408    |     | `-DeclRefExpr '__range1'1409    |     `-IntegerLiteral1410    |-BinaryOperator1411    | |-ImplicitCastExpr1412    | | `-DeclRefExpr '__begin1'1413    | `-ImplicitCastExpr1414    |   `-DeclRefExpr '__end1'1415    |-UnaryOperator1416    | `-DeclRefExpr '__begin1'1417    |-DeclStmt1418    | `-VarDecl 'i'1419    |   `-ImplicitCastExpr1420    |     `-UnaryOperator1421    |       `-ImplicitCastExpr1422    |         `-DeclRefExpr '__begin1'1423    `-CompoundStmt1424)cpp");1425 1426    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1427                            BN[0].getNodeAs<Decl>("func")),1428              R"cpp(1429FunctionDecl 'forLoop'1430`-CompoundStmt1431  |-DeclStmt1432  | `-VarDecl 'arr'1433  |-CXXForRangeStmt1434  | |-<<<NULL>>>1435  | |-VarDecl 'i'1436  | |-DeclRefExpr 'arr'1437  | `-CompoundStmt1438  `-CXXForRangeStmt1439    |-DeclStmt1440    | `-VarDecl 'a'1441    |   `-DeclRefExpr 'arr'1442    |-VarDecl 'i'1443    |-DeclRefExpr 'a'1444    `-CompoundStmt1445)cpp");1446  }1447  {1448    auto BN = ast_matchers::match(1449        cxxRecordDecl(hasName("DefaultedAndDeleted"), unless(isImplicit()))1450            .bind("rec"),1451        AST2->getASTContext());1452    EXPECT_EQ(BN.size(), 1u);1453 1454    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),1455              R"cpp(1456CXXRecordDecl 'DefaultedAndDeleted'1457|-CXXRecordDecl 'DefaultedAndDeleted'1458|-FieldDecl 'nt'1459|-CXXConstructorDecl 'DefaultedAndDeleted'1460| |-CXXCtorInitializer 'nt'1461| | `-CXXConstructExpr1462| `-CompoundStmt1463|-CXXDestructorDecl '~DefaultedAndDeleted'1464| `-CompoundStmt1465|-CXXConstructorDecl 'DefaultedAndDeleted'1466| `-ParmVarDecl ''1467|-CXXMethodDecl 'operator='1468| |-ParmVarDecl ''1469| `-CompoundStmt1470|   |-CXXMemberCallExpr1471|   | |-MemberExpr1472|   | | `-MemberExpr1473|   | |   `-CXXThisExpr1474|   | `-MemberExpr1475|   |   `-DeclRefExpr ''1476|   `-ReturnStmt1477|     `-UnaryOperator1478|       `-CXXThisExpr1479|-CXXConstructorDecl 'DefaultedAndDeleted'1480| `-ParmVarDecl ''1481`-CXXMethodDecl 'operator='1482  `-ParmVarDecl ''1483)cpp");1484 1485    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1486                            BN[0].getNodeAs<Decl>("rec")),1487              R"cpp(1488CXXRecordDecl 'DefaultedAndDeleted'1489|-FieldDecl 'nt'1490|-CXXConstructorDecl 'DefaultedAndDeleted'1491|-CXXDestructorDecl '~DefaultedAndDeleted'1492|-CXXConstructorDecl 'DefaultedAndDeleted'1493| `-ParmVarDecl ''1494|-CXXMethodDecl 'operator='1495| `-ParmVarDecl ''1496|-CXXConstructorDecl 'DefaultedAndDeleted'1497| `-ParmVarDecl ''1498`-CXXMethodDecl 'operator='1499  `-ParmVarDecl ''1500)cpp");1501  }1502  {1503    auto BN = ast_matchers::match(1504        callExpr(callee(functionDecl(hasName("hasDefaultArg"))))1505            .bind("funcCall"),1506        AST2->getASTContext());1507    EXPECT_EQ(BN.size(), 1u);1508 1509    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<CallExpr>("funcCall")),1510              R"cpp(1511CallExpr1512|-ImplicitCastExpr1513| `-DeclRefExpr 'hasDefaultArg'1514|-IntegerLiteral1515`-CXXDefaultArgExpr1516  `-IntegerLiteral1517)cpp");1518    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1519                            BN[0].getNodeAs<CallExpr>("funcCall")),1520              R"cpp(1521CallExpr1522|-DeclRefExpr 'hasDefaultArg'1523`-IntegerLiteral1524)cpp");1525  }1526 1527  {1528    auto FN = ast_matchers::match(1529        functionDecl(hasName("decomposition"),1530                     hasDescendant(decompositionDecl().bind("decomp"))),1531        AST2->getASTContext());1532    EXPECT_EQ(FN.size(), 1u);1533 1534    EXPECT_EQ(1535        dumpASTString(TK_AsIs, FN[0].getNodeAs<DecompositionDecl>("decomp")),1536        R"cpp(1537DecompositionDecl ''1538|-DeclRefExpr 'arr'1539|-BindingDecl 'f'1540| `-ArraySubscriptExpr1541|   |-ImplicitCastExpr1542|   | `-DeclRefExpr ''1543|   `-IntegerLiteral1544|-BindingDecl 's'1545| `-ArraySubscriptExpr1546|   |-ImplicitCastExpr1547|   | `-DeclRefExpr ''1548|   `-IntegerLiteral1549`-BindingDecl 't'1550  `-ArraySubscriptExpr1551    |-ImplicitCastExpr1552    | `-DeclRefExpr ''1553    `-IntegerLiteral1554)cpp");1555 1556    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1557                            FN[0].getNodeAs<DecompositionDecl>("decomp")),1558              R"cpp(1559DecompositionDecl ''1560|-DeclRefExpr 'arr'1561|-BindingDecl 'f'1562|-BindingDecl 's'1563`-BindingDecl 't'1564)cpp");1565  }1566 1567  {1568    auto FN = ast_matchers::match(1569        functionDecl(hasName("decompTuple"),1570                     hasDescendant(decompositionDecl().bind("decomp"))),1571        AST2->getASTContext());1572    EXPECT_EQ(FN.size(), 1u);1573 1574    EXPECT_EQ(1575        dumpASTString(TK_AsIs, FN[0].getNodeAs<DecompositionDecl>("decomp")),1576        R"cpp(1577DecompositionDecl ''1578|-CXXConstructExpr1579| `-ImplicitCastExpr1580|   `-DeclRefExpr 'p'1581|-BindingDecl 'a'1582| |-VarDecl 'a'1583| | `-CallExpr1584| |   |-ImplicitCastExpr1585| |   | `-DeclRefExpr 'get'1586| |   `-ImplicitCastExpr1587| |     `-DeclRefExpr ''1588| `-DeclRefExpr 'a'1589`-BindingDecl 'b'1590  |-VarDecl 'b'1591  | `-CallExpr1592  |   |-ImplicitCastExpr1593  |   | `-DeclRefExpr 'get'1594  |   `-ImplicitCastExpr1595  |     `-DeclRefExpr ''1596  `-DeclRefExpr 'b'1597)cpp");1598 1599    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1600                            FN[0].getNodeAs<DecompositionDecl>("decomp")),1601              R"cpp(1602DecompositionDecl ''1603|-DeclRefExpr 'p'1604|-BindingDecl 'a'1605`-BindingDecl 'b'1606)cpp");1607  }1608 1609  {1610    auto FN = ast_matchers::match(1611        functionDecl(hasName("decompTuple"),1612                     hasDescendant(callExpr(hasAncestor(varDecl(1613                                                hasName("a"),1614                                                hasAncestor(bindingDecl()))))1615                                       .bind("decomp_call"))),1616        AST2->getASTContext());1617    EXPECT_EQ(FN.size(), 1u);1618 1619    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<CallExpr>("decomp_call")),1620              R"cpp(1621CallExpr1622|-ImplicitCastExpr1623| `-DeclRefExpr 'get'1624`-ImplicitCastExpr1625  `-DeclRefExpr ''1626)cpp");1627 1628    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1629                            FN[0].getNodeAs<CallExpr>("decomp_call")),1630              R"cpp(1631DeclRefExpr ''1632)cpp");1633  }1634 1635  {1636    auto FN = ast_matchers::match(1637        functionDecl(hasName("decompTuple"),1638                     hasDescendant(callExpr(hasAncestor(varDecl(1639                                                hasName("c"),1640                                                hasAncestor(bindingDecl()))))1641                                       .bind("decomp_call_with_default"))),1642        AST2->getASTContext());1643    EXPECT_EQ(FN.size(), 1u);1644 1645    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<CallExpr>(1646                                         "decomp_call_with_default")),1647              R"cpp(1648CallExpr1649|-ImplicitCastExpr1650| `-DeclRefExpr 'get'1651|-ImplicitCastExpr1652| `-DeclRefExpr ''1653`-CXXDefaultArgExpr1654  `-IntegerLiteral1655)cpp");1656 1657    EXPECT_EQ(1658        dumpASTString(TK_IgnoreUnlessSpelledInSource,1659                      FN[0].getNodeAs<CallExpr>("decomp_call_with_default")),1660        R"cpp(1661DeclRefExpr ''1662)cpp");1663  }1664}1665 1666TEST(Traverse, IgnoreUnlessSpelledInSourceTemplateInstantiations) {1667 1668  auto AST = buildASTFromCode(R"cpp(1669template<typename T>1670struct TemplStruct {1671  TemplStruct() {}1672  ~TemplStruct() {}1673 1674private:1675  T m_t;1676};1677 1678template<typename T>1679T timesTwo(T input)1680{1681  return input * 2;1682}1683 1684void instantiate()1685{1686  TemplStruct<int> ti;1687  TemplStruct<double> td;1688  (void)timesTwo<int>(2);1689  (void)timesTwo<double>(2);1690}1691 1692template class TemplStruct<float>;1693 1694extern template class TemplStruct<long>;1695 1696template<> class TemplStruct<bool> {1697  TemplStruct() {}1698  ~TemplStruct() {}1699 1700  void foo() {}1701private:1702  bool m_t;1703};1704 1705// Explicit instantiation of template functions do not appear in the AST1706template float timesTwo(float);1707 1708template<> bool timesTwo<bool>(bool) {1709  return true;1710}1711)cpp");1712  {1713    auto BN = ast_matchers::match(1714        classTemplateDecl(hasName("TemplStruct")).bind("rec"),1715        AST->getASTContext());1716    EXPECT_EQ(BN.size(), 1u);1717 1718    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1719                            BN[0].getNodeAs<Decl>("rec")),1720              R"cpp(1721ClassTemplateDecl 'TemplStruct'1722|-TemplateTypeParmDecl 'T'1723`-CXXRecordDecl 'TemplStruct'1724  |-CXXConstructorDecl 'TemplStruct<T>'1725  | `-CompoundStmt1726  |-CXXDestructorDecl '~TemplStruct<T>'1727  | `-CompoundStmt1728  |-AccessSpecDecl1729  `-FieldDecl 'm_t'1730)cpp");1731 1732    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),1733              R"cpp(1734ClassTemplateDecl 'TemplStruct'1735|-TemplateTypeParmDecl 'T'1736|-CXXRecordDecl 'TemplStruct'1737| |-CXXRecordDecl 'TemplStruct'1738| |-CXXConstructorDecl 'TemplStruct<T>'1739| | `-CompoundStmt1740| |-CXXDestructorDecl '~TemplStruct<T>'1741| | `-CompoundStmt1742| |-AccessSpecDecl1743| `-FieldDecl 'm_t'1744|-ClassTemplateSpecializationDecl 'TemplStruct'1745| |-TemplateArgument type int1746| | `-BuiltinType1747| |-CXXRecordDecl 'TemplStruct'1748| |-CXXConstructorDecl 'TemplStruct'1749| | `-CompoundStmt1750| |-CXXDestructorDecl '~TemplStruct'1751| | `-CompoundStmt1752| |-AccessSpecDecl1753| |-FieldDecl 'm_t'1754| `-CXXConstructorDecl 'TemplStruct'1755|   `-ParmVarDecl ''1756|-ClassTemplateSpecializationDecl 'TemplStruct'1757| |-TemplateArgument type double1758| | `-BuiltinType1759| |-CXXRecordDecl 'TemplStruct'1760| |-CXXConstructorDecl 'TemplStruct'1761| | `-CompoundStmt1762| |-CXXDestructorDecl '~TemplStruct'1763| | `-CompoundStmt1764| |-AccessSpecDecl1765| |-FieldDecl 'm_t'1766| `-CXXConstructorDecl 'TemplStruct'1767|   `-ParmVarDecl ''1768|-ClassTemplateSpecializationDecl 'TemplStruct'1769| |-TemplateArgument type float1770| | `-BuiltinType1771| |-CXXRecordDecl 'TemplStruct'1772| |-CXXConstructorDecl 'TemplStruct'1773| | `-CompoundStmt1774| |-CXXDestructorDecl '~TemplStruct'1775| | `-CompoundStmt1776| |-AccessSpecDecl1777| `-FieldDecl 'm_t'1778|-ClassTemplateSpecializationDecl 'TemplStruct'1779| |-TemplateArgument type long1780| | `-BuiltinType1781| |-CXXRecordDecl 'TemplStruct'1782| |-CXXConstructorDecl 'TemplStruct'1783| |-CXXDestructorDecl '~TemplStruct'1784| |-AccessSpecDecl1785| `-FieldDecl 'm_t'1786`-ClassTemplateSpecializationDecl 'TemplStruct'1787  |-TemplateArgument type _Bool1788  | `-BuiltinType1789  |-CXXRecordDecl 'TemplStruct'1790  |-CXXConstructorDecl 'TemplStruct'1791  | `-CompoundStmt1792  |-CXXDestructorDecl '~TemplStruct'1793  | `-CompoundStmt1794  |-CXXMethodDecl 'foo'1795  | `-CompoundStmt1796  |-AccessSpecDecl1797  `-FieldDecl 'm_t'1798)cpp");1799  }1800  {1801    auto BN = ast_matchers::match(1802        classTemplateSpecializationDecl(1803            hasTemplateArgument(1804                0, templateArgument(refersToType(asString("_Bool")))))1805            .bind("templSpec"),1806        AST->getASTContext());1807    EXPECT_EQ(BN.size(), 1u);1808 1809    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("templSpec")),1810              R"cpp(1811ClassTemplateSpecializationDecl 'TemplStruct'1812|-TemplateArgument type _Bool1813| `-BuiltinType1814|-CXXRecordDecl 'TemplStruct'1815|-CXXConstructorDecl 'TemplStruct'1816| `-CompoundStmt1817|-CXXDestructorDecl '~TemplStruct'1818| `-CompoundStmt1819|-CXXMethodDecl 'foo'1820| `-CompoundStmt1821|-AccessSpecDecl1822`-FieldDecl 'm_t'1823)cpp");1824 1825    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1826                            BN[0].getNodeAs<Decl>("templSpec")),1827              R"cpp(1828ClassTemplateSpecializationDecl 'TemplStruct'1829|-TemplateArgument type _Bool1830| `-BuiltinType1831|-CXXConstructorDecl 'TemplStruct'1832| `-CompoundStmt1833|-CXXDestructorDecl '~TemplStruct'1834| `-CompoundStmt1835|-CXXMethodDecl 'foo'1836| `-CompoundStmt1837|-AccessSpecDecl1838`-FieldDecl 'm_t'1839)cpp");1840  }1841  {1842    auto BN = ast_matchers::match(1843        functionTemplateDecl(hasName("timesTwo")).bind("fn"),1844        AST->getASTContext());1845    EXPECT_EQ(BN.size(), 1u);1846 1847    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1848                            BN[0].getNodeAs<Decl>("fn")),1849              R"cpp(1850FunctionTemplateDecl 'timesTwo'1851|-TemplateTypeParmDecl 'T'1852`-FunctionDecl 'timesTwo'1853  |-ParmVarDecl 'input'1854  `-CompoundStmt1855    `-ReturnStmt1856      `-BinaryOperator1857        |-DeclRefExpr 'input'1858        `-IntegerLiteral1859)cpp");1860 1861    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("fn")),1862              R"cpp(1863FunctionTemplateDecl 'timesTwo'1864|-TemplateTypeParmDecl 'T'1865|-FunctionDecl 'timesTwo'1866| |-ParmVarDecl 'input'1867| `-CompoundStmt1868|   `-ReturnStmt1869|     `-BinaryOperator1870|       |-DeclRefExpr 'input'1871|       `-IntegerLiteral1872|-FunctionDecl 'timesTwo'1873| |-TemplateArgument type int1874| | `-BuiltinType1875| |-ParmVarDecl 'input'1876| `-CompoundStmt1877|   `-ReturnStmt1878|     `-BinaryOperator1879|       |-ImplicitCastExpr1880|       | `-DeclRefExpr 'input'1881|       `-IntegerLiteral1882|-FunctionDecl 'timesTwo'1883| |-TemplateArgument type double1884| | `-BuiltinType1885| |-ParmVarDecl 'input'1886| `-CompoundStmt1887|   `-ReturnStmt1888|     `-BinaryOperator1889|       |-ImplicitCastExpr1890|       | `-DeclRefExpr 'input'1891|       `-ImplicitCastExpr1892|         `-IntegerLiteral1893|-FunctionDecl 'timesTwo'1894| |-TemplateArgument type float1895| | `-BuiltinType1896| |-ParmVarDecl 'input'1897| `-CompoundStmt1898|   `-ReturnStmt1899|     `-BinaryOperator1900|       |-ImplicitCastExpr1901|       | `-DeclRefExpr 'input'1902|       `-ImplicitCastExpr1903|         `-IntegerLiteral1904|-FunctionDecl 'timesTwo'1905| |-TemplateArgument type _Bool1906| | `-BuiltinType1907| |-ParmVarDecl ''1908| `-CompoundStmt1909|   `-ReturnStmt1910|     `-CXXBoolLiteralExpr1911`-FunctionDecl 'timesTwo'1912  |-TemplateArgument type _Bool1913  | `-BuiltinType1914  `-ParmVarDecl 'input'1915)cpp");1916  }1917  {1918    auto BN = ast_matchers::match(1919        classTemplateSpecializationDecl(1920            hasName("TemplStruct"),1921            hasTemplateArgument(1922                0, templateArgument(refersToType(asString("float")))),1923            hasParent(translationUnitDecl()))1924            .bind("rec"),1925        AST->getASTContext());1926    EXPECT_EQ(BN.size(), 1u);1927 1928    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,1929                            BN[0].getNodeAs<Decl>("rec")),1930              R"cpp(1931ClassTemplateSpecializationDecl 'TemplStruct'1932`-TemplateArgument type float1933  `-BuiltinType1934)cpp");1935 1936    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),1937              R"cpp(1938ClassTemplateSpecializationDecl 'TemplStruct'1939|-TemplateArgument type float1940| `-BuiltinType1941|-CXXRecordDecl 'TemplStruct'1942|-CXXConstructorDecl 'TemplStruct'1943| `-CompoundStmt1944|-CXXDestructorDecl '~TemplStruct'1945| `-CompoundStmt1946|-AccessSpecDecl1947`-FieldDecl 'm_t'1948)cpp");1949  }1950}1951 1952TEST(Traverse, CXXRewrittenBinaryOperator) {1953 1954  auto AST = buildASTFromCodeWithArgs(R"cpp(1955namespace std {1956struct strong_ordering {1957  int n;1958  constexpr operator int() const { return n; }1959  static const strong_ordering equal, greater, less;1960};1961constexpr strong_ordering strong_ordering::equal = {0};1962constexpr strong_ordering strong_ordering::greater = {1};1963constexpr strong_ordering strong_ordering::less = {-1};1964}1965 1966struct HasSpaceshipMem {1967  int a;1968  constexpr auto operator<=>(const HasSpaceshipMem&) const = default;1969};1970 1971void binop()1972{1973    HasSpaceshipMem hs1, hs2;1974    if (hs1 < hs2)1975        return;1976}1977)cpp",1978                                      {"-std=c++20"});1979  {1980    auto BN = ast_matchers::match(cxxRewrittenBinaryOperator().bind("binop"),1981                                  AST->getASTContext());1982    EXPECT_EQ(BN.size(), 1u);1983 1984    EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Stmt>("binop")),1985              R"cpp(1986CXXRewrittenBinaryOperator1987`-BinaryOperator1988  |-ImplicitCastExpr1989  | `-CXXMemberCallExpr1990  |   `-MemberExpr1991  |     `-ImplicitCastExpr1992  |       `-MaterializeTemporaryExpr1993  |         `-CXXOperatorCallExpr1994  |           |-ImplicitCastExpr1995  |           | `-DeclRefExpr 'operator<=>'1996  |           |-ImplicitCastExpr1997  |           | `-DeclRefExpr 'hs1'1998  |           `-ImplicitCastExpr1999  |             `-DeclRefExpr 'hs2'2000  `-IntegerLiteral2001)cpp");2002    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,2003                            BN[0].getNodeAs<Stmt>("binop")),2004              R"cpp(2005CXXRewrittenBinaryOperator2006|-DeclRefExpr 'hs1'2007`-DeclRefExpr 'hs2'2008)cpp");2009  }2010}2011 2012TEST(Traverse, CatchStatements) {2013 2014  auto AST = buildASTFromCode(R"cpp(2015void test()2016{2017  try2018  {2019    int a;2020  }2021  catch (...)2022  {2023    int b;2024  }2025 2026  try2027  {2028    int a;2029  }2030  catch (const int&)2031  {2032    int b;2033  }2034}2035)cpp");2036 2037  auto BN =2038      ast_matchers::match(cxxCatchStmt().bind("catch"), AST->getASTContext());2039  EXPECT_EQ(BN.size(), 2u);2040  const auto *catchWithoutDecl = BN[0].getNodeAs<Stmt>("catch");2041 2042  llvm::StringRef Expected = R"cpp(2043CXXCatchStmt2044|-<<<NULL>>>2045`-CompoundStmt2046  `-DeclStmt2047    `-VarDecl 'b'2048)cpp";2049  EXPECT_EQ(dumpASTString(TK_AsIs, catchWithoutDecl), Expected);2050 2051  Expected = R"cpp(2052CXXCatchStmt2053|-<<<NULL>>>2054`-CompoundStmt2055  `-DeclStmt2056    `-VarDecl 'b'2057)cpp";2058  EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, catchWithoutDecl),2059            Expected);2060 2061  const auto *catchWithDecl = BN[1].getNodeAs<Stmt>("catch");2062 2063  Expected = R"cpp(2064CXXCatchStmt2065|-VarDecl ''2066`-CompoundStmt2067  `-DeclStmt2068    `-VarDecl 'b'2069)cpp";2070  EXPECT_EQ(dumpASTString(TK_AsIs, catchWithDecl), Expected);2071 2072  Expected = R"cpp(2073CXXCatchStmt2074|-VarDecl ''2075`-CompoundStmt2076  `-DeclStmt2077    `-VarDecl 'b'2078)cpp";2079  EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, catchWithDecl),2080            Expected);2081}2082 2083} // namespace clang2084