clang: lib/Tooling/Syntax/BuildTree.cpp Source File (original) (raw)

1

2

3

4

5

6

7

33#include "llvm/ADT/ArrayRef.h"

34#include "llvm/ADT/DenseMap.h"

35#include "llvm/ADT/PointerUnion.h"

36#include "llvm/ADT/STLExtras.h"

37#include "llvm/ADT/ScopeExit.h"

38#include "llvm/ADT/SmallVector.h"

39#include "llvm/Support/Allocator.h"

40#include "llvm/Support/Casting.h"

41#include "llvm/Support/Compiler.h"

42#include "llvm/Support/FormatVariadic.h"

43#include "llvm/Support/MemoryBuffer.h"

44#include "llvm/Support/raw_ostream.h"

45#include

46#include

47

48using namespace clang;

49

50

51

52

54 if (auto *C = dyn_cast(E)) {

55 auto NumArgs = C->getNumArgs();

56 if (NumArgs == 1 || (NumArgs > 1 && isa(C->getArg(1)))) {

57 Expr *A = C->getArg(0);

58 if (C->getParenOrBraceRange().isInvalid())

59 return A;

60 }

61 }

62 return E;

63}

64

65

66

67

68

69

70

71

73 if (auto *F = dyn_cast(E)) {

74 if (F->getCastKind() == CK_ConstructorConversion)

75 return F->getSubExpr();

76 }

77 return E;

78}

79

84}

85

86LLVM_ATTRIBUTE_UNUSED

88

89namespace {

90

91

92

93

94

95

96

97

98

99

100

101

102struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> {

104 auto L = Visit(T.getInnerLoc());

105 if (L.isValid())

106 return L;

107 return T.getLParenLoc();

108 }

109

110

112 return HandlePointer(T);

113 }

114

116 return HandlePointer(T);

117 }

118

120 return HandlePointer(T);

121 }

122

124 return HandlePointer(T);

125 }

126

128 return HandlePointer(T);

129 }

130

131

132

133

134

136 auto N = T.getNextTypeLoc();

137 if (!N)

140 }

141

144 return SourceLocation();

146 }

147

148private:

149 template SourceLocation HandlePointer(PtrLoc T) {

150 auto L = Visit(T.getPointeeLoc());

151 if (L.isValid())

152 return L;

153 return T.getLocalSourceRange().getBegin();

154 }

155};

156}

157

159 auto FirstDefaultArg =

160 llvm::find_if(Args, [](auto It) { return isa(It); });

161 return llvm::make_range(Args.begin(), FirstDefaultArg);

162}

163

165 switch (E.getOperator()) {

166

167 case OO_EqualEqual:

168 case OO_ExclaimEqual:

169 case OO_Greater:

170 case OO_GreaterEqual:

171 case OO_Less:

172 case OO_LessEqual:

173 case OO_Spaceship:

174

175 case OO_Equal:

176 case OO_SlashEqual:

177 case OO_PercentEqual:

178 case OO_CaretEqual:

179 case OO_PipeEqual:

180 case OO_LessLessEqual:

181 case OO_GreaterGreaterEqual:

182 case OO_PlusEqual:

183 case OO_MinusEqual:

184 case OO_StarEqual:

185 case OO_AmpEqual:

186

187 case OO_Slash:

188 case OO_Percent:

189 case OO_Caret:

190 case OO_Pipe:

191 case OO_LessLess:

192 case OO_GreaterGreater:

193 case OO_AmpAmp:

194 case OO_PipePipe:

195 case OO_ArrowStar:

196 case OO_Comma:

197 return syntax::NodeKind::BinaryOperatorExpression;

198 case OO_Tilde:

199 case OO_Exclaim:

200 return syntax::NodeKind::PrefixUnaryOperatorExpression;

201

202 case OO_PlusPlus:

203 case OO_MinusMinus:

204 switch (E.getNumArgs()) {

205 case 1:

206 return syntax::NodeKind::PrefixUnaryOperatorExpression;

207 case 2:

208 return syntax::NodeKind::PostfixUnaryOperatorExpression;

209 default:

210 llvm_unreachable("Invalid number of arguments for operator");

211 }

212

213 case OO_Plus:

214 case OO_Minus:

215 case OO_Star:

216 case OO_Amp:

217 switch (E.getNumArgs()) {

218 case 1:

219 return syntax::NodeKind::PrefixUnaryOperatorExpression;

220 case 2:

221 return syntax::NodeKind::BinaryOperatorExpression;

222 default:

223 llvm_unreachable("Invalid number of arguments for operator");

224 }

225 return syntax::NodeKind::BinaryOperatorExpression;

226

227 case OO_New:

228 case OO_Delete:

229 case OO_Array_New:

230 case OO_Array_Delete:

231 case OO_Coawait:

232 case OO_Subscript:

233 case OO_Arrow:

234 return syntax::NodeKind::UnknownExpression;

235 case OO_Call:

236 return syntax::NodeKind::CallExpression;

237 case OO_Conditional:

240 llvm_unreachable("Not an overloadable operator");

241 }

242 llvm_unreachable("Unknown OverloadedOperatorKind enum");

243}

244

245

246

247

248

249

251 assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) &&

252 "only DeclaratorDecl and TypedefNameDecl are supported.");

253

254 auto DN = D->getDeclName();

255 bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo();

256 if (IsAnonymous)

258

259 if (const auto *DD = dyn_cast(D)) {

260 if (DD->getQualifierLoc()) {

261 return DD->getQualifierLoc().getBeginLoc();

262 }

263 }

264

266}

267

268

269

270

271

272

274 if (auto *V = dyn_cast(D)) {

275 auto *I = V->getInit();

276

277 if (I && V->isCXXForRangeDecl())

278 return I->getSourceRange();

279 }

280

282}

283

284

285

286

287

288

289

290

291

297 if (Name.isValid()) {

299 Start = Name;

300

301

302 if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name))

303 End = Name;

304 }

306 auto InitializerEnd = Initializer.getEnd();

307 assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) ||

308 End == InitializerEnd);

309 End = InitializerEnd;

310 }

312}

313

314namespace {

315

316using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;

317

318

319

320class ASTToSyntaxMapping {

321public:

323 assert(To != nullptr);

324 assert(!From.isNull());

325

326 bool Added = Nodes.insert({From, To}).second;

327 (void)Added;

328 assert(Added && "mapping added twice");

329 }

330

332 assert(To != nullptr);

334

335 bool Added = NNSNodes.insert({From, To}).second;

336 (void)Added;

337 assert(Added && "mapping added twice");

338 }

339

341

343 return NNSNodes.lookup(P);

344 }

345

346private:

347 llvm::DenseMap<ASTPtr, syntax::Tree *> Nodes;

348 llvm::DenseMap<NestedNameSpecifierLoc, syntax::Tree *> NNSNodes;

349};

350}

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

368public:

371 TBTM(TBTM),

372 Pending(Arena, TBTM.tokenBuffer()) {

374 LocationToToken.insert({T.location(), &T});

375 }

376

380 }

381

382

383

385 assert(New);

387 if (From)

388 Mapping.add(From, New);

389 }

390

392

394 }

395

398 assert(New);

400 if (From)

401 Mapping.add(From, New);

402 }

403

404

405

407 ASTPtr From) {

408 assert(New);

409 auto ListRange = Pending.shrinkToFitList(SuperRange);

410 Pending.foldChildren(TBTM.tokenBuffer(), ListRange, New);

411 if (From)

412 Mapping.add(From, New);

413 }

414

415

416

418

419

420

421

422

424

425

427

429

431

432

434

436

438

439

442 assert(!Tokens.empty());

443 assert(Tokens.back().kind() == tok::eof);

444

445

446 Pending.foldChildren(TBTM.tokenBuffer(), Tokens.drop_back(),

448

449 auto *TU = castsyntax::TranslationUnit(std::move(Pending).finalize());

450 TU->assertInvariantsRecursive();

451 return TU;

452 }

453

454

456

457

461 }

462

463

464

465

468 assert(First.isValid());

469 assert(Last.isValid());

473 }

474

478 return maybeAppendSemicolon(Tokens, D);

479 }

480

481

482

484 assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) &&

485 "only DeclaratorDecl and TypedefNameDecl are supported.");

486

488

489

490 if (Next == nullptr) {

491 return true;

492 }

493

494

495 if (D->getKind() != Next->getKind()) {

496 return true;

497 }

498

499

500 if (Next->getBeginLoc() != D->getBeginLoc()) {

501 return true;

502 }

503

504

505

506 return false;

507 }

508

511

512 if (const auto *S = dyn_cast(D))

513 Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());

514 else

516 return maybeAppendSemicolon(Tokens, D);

517 }

518

521 }

522

523

524

526 auto Tokens = getRange(S->getSourceRange());

527 if (isa(S))

528 return Tokens;

529

530

531

532 if (Tokens.back().kind() == tok::semi)

533 return Tokens;

534 return withTrailingSemicolon(Tokens);

535 }

536

537private:

539 const Decl *D) const {

540 if (isa(D))

541 return Tokens;

542 if (DeclsWithoutSemicolons.count(D))

543 return Tokens;

544

545

546 return withTrailingSemicolon(Tokens);

547 }

548

551 assert(!Tokens.empty());

552 assert(Tokens.back().kind() != tok::eof);

553

554 if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi)

555 return llvm::ArrayRef(Tokens.begin(), Tokens.end() + 1);

556 return Tokens;

557 }

558

561 N->setRole(R);

562 }

563

564

565

566

567

568

569

570 struct Forest {

573 assert(TB.expandedTokens().back().kind() == tok::eof);

574

575

579 L->Original = true;

581 Trees.insert(Trees.end(), {&T, L});

582 }

583 }

584

586 assert(Range.empty());

587 auto It = Trees.lower_bound(Range.begin());

588 assert(It != Trees.end() && "no node found");

589 assert(It->first == Range.begin() && "no child with the specified range");

590 assert((std::next(It) == Trees.end() ||

591 std::next(It)->first == Range.end()) &&

592 "no child with the specified range");

594 "re-assigning role for a child");

595 It->second->setRole(Role);

596 }

597

598

599

601 auto BeginChildren = Trees.lower_bound(Range.begin());

602 assert((BeginChildren == Trees.end() ||

603 BeginChildren->first == Range.begin()) &&

604 "Range crosses boundaries of existing subtrees");

605

606 auto EndChildren = Trees.lower_bound(Range.end());

607 assert(

608 (EndChildren == Trees.end() || EndChildren->first == Range.end()) &&

609 "Range crosses boundaries of existing subtrees");

610

611 auto BelongsToList = [](decltype(Trees)::value_type KV) {

612 auto Role = KV.second->getRole();

615 };

616

617 auto BeginListChildren =

618 std::find_if(BeginChildren, EndChildren, BelongsToList);

619

620 auto EndListChildren =

621 std::find_if_not(BeginListChildren, EndChildren, BelongsToList);

622

624 EndListChildren->first);

625 }

626

627

630

631 assert(Node->getFirstChild() == nullptr && "node already has children");

632

633 auto *FirstToken = Tokens.begin();

634 auto BeginChildren = Trees.lower_bound(FirstToken);

635

636 assert((BeginChildren == Trees.end() ||

637 BeginChildren->first == FirstToken) &&

638 "fold crosses boundaries of existing subtrees");

639 auto EndChildren = Trees.lower_bound(Tokens.end());

640 assert(

641 (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) &&

642 "fold crosses boundaries of existing subtrees");

643

644 for (auto It = BeginChildren; It != EndChildren; ++It) {

645 auto *C = It->second;

648 Node->appendChildLowLevel(C);

649 }

650

651

652 Node->Original = true;

653 Node->CanModify =

655

656 Trees.erase(BeginChildren, EndChildren);

657 Trees.insert({FirstToken, Node});

658 }

659

660

662 assert(Trees.size() == 1);

663 auto *Root = Trees.begin()->second;

664 Trees = {};

665 return Root;

666 }

667

669 std::string R;

670 for (auto It = Trees.begin(); It != Trees.end(); ++It) {

671 unsigned CoveredTokens =

672 It != Trees.end()

673 ? (std::next(It)->first - It->first)

675

676 R += std::string(

677 formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(),

678 It->first->text(STM.sourceManager()), CoveredTokens));

679 R += It->second->dump(STM);

680 }

681 return R;

682 }

683

684 private:

685

686

687

688 std::map<const syntax::Token *, syntax::Node *> Trees;

689 };

690

691

692 std::string str() { return Pending.str(TBTM); }

693

695 TokenBufferTokenManager& TBTM;

696

697 llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken;

698 Forest Pending;

699 llvm::DenseSet<Decl *> DeclsWithoutSemicolons;

700 ASTToSyntaxMapping Mapping;

701};

702

703namespace {

705public:

707 : Builder(Builder), Context(Context) {}

708

710

712 return processDeclaratorAndDeclaration(DD);

713 }

714

716 return processDeclaratorAndDeclaration(TD);

717 }

718

721 Builder.foldNode(Builder.getDeclarationRange(D),

723 return true;

724 }

725

726

727

728

729 bool

731 if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))

732 return false;

733 if (C->isExplicitSpecialization())

734 return true;

736 castsyntax::SimpleDeclaration(handleFreeStandingTagDecl(C));

737 foldExplicitTemplateInstantiation(

738 Builder.getTemplateRange(C),

739 Builder.findToken(C->getExternKeywordLoc()),

740 Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);

741 return true;

742 }

743

744 bool WalkUpFromTemplateDecl(TemplateDecl *S) {

745 foldTemplateDeclaration(

746 Builder.getDeclarationRange(S),

747 Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),

748 Builder.getDeclarationRange(S->getTemplatedDecl()), S);

749 return true;

750 }

751

752 bool WalkUpFromTagDecl(TagDecl *C) {

753

754 if (C->isFreeStanding()) {

755 assert(C->getNumTemplateParameterLists() == 0);

756 return true;

757 }

758 handleFreeStandingTagDecl(C);

759 return true;

760 }

761

763 assert(C->isFreeStanding());

764

765 auto DeclarationRange = Builder.getDeclarationRange(C);

767 Builder.foldNode(DeclarationRange, Result, nullptr);

768

769

771 const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());

772 auto R = llvm::ArrayRef(TemplateKW, DeclarationRange.end());

773 Result =

774 foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);

775 DeclarationRange = R;

776 };

777 if (auto *S = dyn_cast(C))

778 ConsumeTemplateParameters(*S->getTemplateParameters());

779 for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)

780 ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));

782 }

783

785

786

787 return true;

788 }

789

790 bool WalkUpFromCompoundStmt(CompoundStmt *S) {

792

793 Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen);

794 for (auto *Child : S->body())

795 Builder.markStmtChild(Child, NodeRole::Statement);

796 Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);

797

798 Builder.foldNode(Builder.getStmtRange(S),

800 return true;

801 }

802

803

805 Builder.foldNode(Builder.getStmtRange(S),

807 return true;

808 }

809

810 bool TraverseIfStmt(IfStmt *S) {

811 bool Result = [&, this]() {

812 if (S->getInit() && TraverseStmt(S->getInit())) {

813 return false;

814 }

815

816

817

818 if (S->hasVarStorage()) {

819 if (TraverseStmt(S->getConditionVariableDeclStmt()))

820 return false;

821 } else if (S->getCond() && TraverseStmt(S->getCond()))

822 return false;

823

824 if (S->getThen() && TraverseStmt(S->getThen()))

825 return false;

826 if (S->getElse() && TraverseStmt(S->getElse()))

827 return false;

828 return true;

829 }();

830 WalkUpFromIfStmt(S);

832 }

833

835

836

837

838

839 bool Result = [&, this]() {

840 if (S->getInit() && TraverseStmt(S->getInit()))

841 return false;

842 if (S->getLoopVariable() && TraverseDecl(S->getLoopVariable()))

843 return false;

844 if (S->getRangeInit() && TraverseStmt(S->getRangeInit()))

845 return false;

846 if (S->getBody() && TraverseStmt(S->getBody()))

847 return false;

848 return true;

849 }();

850 WalkUpFromCXXForRangeStmt(S);

852 }

853

855 if (auto *DS = dyn_cast_or_null(S)) {

856

857 for (auto *D : DS->decls())

858 Builder.noticeDeclWithoutSemicolon(D);

859 } else if (auto *E = dyn_cast_or_null(S)) {

861 }

863 }

864

866

867 return true;

868 }

869

870

871 bool WalkUpFromExpr(Expr *E) {

872 assert(isImplicitExpr(E) && "should be handled by TraverseStmt");

873 Builder.foldNode(Builder.getExprRange(E),

875 return true;

876 }

877

879

880

881

882

883

884 return WalkUpFromUserDefinedLiteral(S);

885 }

886

887 syntax::UserDefinedLiteralExpression *

889 switch (S->getLiteralOperatorKind()) {

891 return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;

893 return new (allocator()) syntax::FloatUserDefinedLiteralExpression;

895 return new (allocator()) syntax::CharUserDefinedLiteralExpression;

897 return new (allocator()) syntax::StringUserDefinedLiteralExpression;

900

901

902

903

904 auto TokLoc = S->getBeginLoc();

905 auto TokSpelling =

911 if (Literal.isIntegerLiteral())

912 return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;

913 else {

914 assert(Literal.isFloatingLiteral());

915 return new (allocator()) syntax::FloatUserDefinedLiteralExpression;

916 }

917 }

918 llvm_unreachable("Unknown literal operator kind.");

919 }

920

922 Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);

923 Builder.foldNode(Builder.getExprRange(S), buildUserDefinedLiteral(S), S);

924 return true;

925 }

926

927

928

929

930

931

932

935

936

937

938

939

940

942 if (auto DependentTL =

944

945

946

947 SR.setBegin(DependentTL.getTemplateKeywordLoc());

948 }

949 }

950

951 return SR;

952 }

953

957 return syntax::NodeKind::GlobalNameSpecifier;

961 return syntax::NodeKind::IdentifierNameSpecifier;

963 return syntax::NodeKind::SimpleTemplateNameSpecifier;

965 const auto *NNSType = NNS.getAsType();

966 assert(NNSType);

967 if (isa(NNSType))

968 return syntax::NodeKind::DecltypeNameSpecifier;

969 if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(

970 NNSType))

971 return syntax::NodeKind::SimpleTemplateNameSpecifier;

972 return syntax::NodeKind::IdentifierNameSpecifier;

973 }

974 default:

975

976 llvm::report_fatal_error("We don't yet support the __super specifier",

977 true);

978 }

979 }

980

981 syntax::NameSpecifier *

984 auto NameSpecifierTokens =

985 Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back();

987 case syntax::NodeKind::GlobalNameSpecifier:

988 return new (allocator()) syntax::GlobalNameSpecifier;

989 case syntax::NodeKind::IdentifierNameSpecifier: {

990 assert(NameSpecifierTokens.size() == 1);

991 Builder.markChildToken(NameSpecifierTokens.begin(),

992 syntax::NodeRole::Unknown);

993 auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;

994 Builder.foldNode(NameSpecifierTokens, NS, nullptr);

995 return NS;

996 }

997 case syntax::NodeKind::SimpleTemplateNameSpecifier: {

998

999

1000

1001

1002

1003 auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;

1004 Builder.foldNode(NameSpecifierTokens, NS, nullptr);

1005 return NS;

1006 }

1007 case syntax::NodeKind::DecltypeNameSpecifier: {

1009 if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL))

1010 return nullptr;

1011 auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;

1012

1013

1014

1015

1016 Builder.foldNode(NameSpecifierTokens, NS, nullptr);

1017 return NS;

1018 }

1019 default:

1020 llvm_unreachable("getChildKind() does not return this value");

1021 }

1022 }

1023

1024

1025

1026

1027

1029 if (!QualifierLoc)

1030 return true;

1031 for (auto It = QualifierLoc; It; It = It.getPrefix()) {

1032 auto *NS = buildNameSpecifier(It);

1033 if (!NS)

1034 return false;

1035 Builder.markChild(NS, syntax::NodeRole::ListElement);

1036 Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter);

1037 }

1038 Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()),

1040 QualifierLoc);

1041 return true;

1042 }

1043

1047 ASTPtr From) {

1048 if (QualifierLoc) {

1049 Builder.markChild(QualifierLoc, syntax::NodeRole::Qualifier);

1050 if (TemplateKeywordLoc.isValid())

1051 Builder.markChildToken(TemplateKeywordLoc,

1052 syntax::NodeRole::TemplateKeyword);

1053 }

1054

1056 Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId,

1057 nullptr);

1058 Builder.markChild(TheUnqualifiedId, syntax::NodeRole::UnqualifiedId);

1059

1060 auto IdExpressionBeginLoc =

1061 QualifierLoc ? QualifierLoc.getBeginLoc() : UnqualifiedIdLoc.getBegin();

1062

1063 auto *TheIdExpression = new (allocator()) syntax::IdExpression;

1064 Builder.foldNode(

1065 Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.getEnd()),

1066 TheIdExpression, From);

1067

1068 return TheIdExpression;

1069 }

1070

1071 bool WalkUpFromMemberExpr(MemberExpr *S) {

1072

1073

1074

1075 if (S->isImplicitAccess()) {

1076 buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),

1077 SourceRange(S->getMemberLoc(), S->getEndLoc()), S);

1078 return true;

1079 }

1080

1081 auto *TheIdExpression = buildIdExpression(

1082 S->getQualifierLoc(), S->getTemplateKeywordLoc(),

1083 SourceRange(S->getMemberLoc(), S->getEndLoc()), nullptr);

1084

1085 Builder.markChild(TheIdExpression, syntax::NodeRole::Member);

1086

1087 Builder.markExprChild(S->getBase(), syntax::NodeRole::Object);

1088 Builder.markChildToken(S->getOperatorLoc(), syntax::NodeRole::AccessToken);

1089

1090 Builder.foldNode(Builder.getExprRange(S),

1091 new (allocator()) syntax::MemberExpression, S);

1092 return true;

1093 }

1094

1095 bool WalkUpFromDeclRefExpr(DeclRefExpr *S) {

1096 buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),

1097 SourceRange(S->getLocation(), S->getEndLoc()), S);

1098

1099 return true;

1100 }

1101

1102

1104 buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),

1105 SourceRange(S->getLocation(), S->getEndLoc()), S);

1106

1107 return true;

1108 }

1109

1110 bool WalkUpFromCXXThisExpr(CXXThisExpr *S) {

1111 if (!S->isImplicit()) {

1112 Builder.markChildToken(S->getLocation(),

1113 syntax::NodeRole::IntroducerKeyword);

1114 Builder.foldNode(Builder.getExprRange(S),

1115 new (allocator()) syntax::ThisExpression, S);

1116 }

1117 return true;

1118 }

1119

1120 bool WalkUpFromParenExpr(ParenExpr *S) {

1121 Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen);

1122 Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::SubExpression);

1123 Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen);

1124 Builder.foldNode(Builder.getExprRange(S),

1125 new (allocator()) syntax::ParenExpression, S);

1126 return true;

1127 }

1128

1130 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);

1131 Builder.foldNode(Builder.getExprRange(S),

1132 new (allocator()) syntax::IntegerLiteralExpression, S);

1133 return true;

1134 }

1135

1137 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);

1138 Builder.foldNode(Builder.getExprRange(S),

1139 new (allocator()) syntax::CharacterLiteralExpression, S);

1140 return true;

1141 }

1142

1144 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);

1145 Builder.foldNode(Builder.getExprRange(S),

1146 new (allocator()) syntax::FloatingLiteralExpression, S);

1147 return true;

1148 }

1149

1150 bool WalkUpFromStringLiteral(StringLiteral *S) {

1151 Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);

1152 Builder.foldNode(Builder.getExprRange(S),

1153 new (allocator()) syntax::StringLiteralExpression, S);

1154 return true;

1155 }

1156

1158 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);

1159 Builder.foldNode(Builder.getExprRange(S),

1160 new (allocator()) syntax::BoolLiteralExpression, S);

1161 return true;

1162 }

1163

1165 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);

1166 Builder.foldNode(Builder.getExprRange(S),

1167 new (allocator()) syntax::CxxNullPtrExpression, S);

1168 return true;

1169 }

1170

1171 bool WalkUpFromUnaryOperator(UnaryOperator *S) {

1172 Builder.markChildToken(S->getOperatorLoc(),

1173 syntax::NodeRole::OperatorToken);

1174 Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::Operand);

1175

1176 if (S->isPostfix())

1177 Builder.foldNode(Builder.getExprRange(S),

1179 S);

1180 else

1181 Builder.foldNode(Builder.getExprRange(S),

1183 S);

1184

1185 return true;

1186 }

1187

1189 Builder.markExprChild(S->getLHS(), syntax::NodeRole::LeftHandSide);

1190 Builder.markChildToken(S->getOperatorLoc(),

1191 syntax::NodeRole::OperatorToken);

1192 Builder.markExprChild(S->getRHS(), syntax::NodeRole::RightHandSide);

1193 Builder.foldNode(Builder.getExprRange(S),

1195 return true;

1196 }

1197

1198

1199

1203 for (auto *Arg : Args) {

1204 Builder.markExprChild(Arg, syntax::NodeRole::ListElement);

1205 const auto *DelimiterToken =

1206 std::next(Builder.findToken(Arg->getEndLoc()));

1207 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)

1208 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);

1209 }

1210

1212 if (!Args.empty())

1213 Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(),

1214 (*(Args.end() - 1))->getEndLoc()),

1216

1218 }

1219

1220 bool WalkUpFromCallExpr(CallExpr *S) {

1221 Builder.markExprChild(S->getCallee(), syntax::NodeRole::Callee);

1222

1223 const auto *LParenToken =

1224 std::next(Builder.findToken(S->getCallee()->getEndLoc()));

1225

1226

1227 if (LParenToken->kind() == clang::tok::l_paren)

1228 Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);

1229

1230 Builder.markChild(buildCallArguments(S->arguments()),

1231 syntax::NodeRole::Arguments);

1232

1233 Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);

1234

1235 Builder.foldNode(Builder.getRange(S->getSourceRange()),

1236 new (allocator()) syntax::CallExpression, S);

1237 return true;

1238 }

1239

1241

1242 if ((S->getNumArgs() == 0 || isa(S->getArg(0))) &&

1243 S->getParenOrBraceRange().isInvalid())

1244 return true;

1245 return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S);

1246 }

1247

1249

1250

1251

1252

1253 for (auto *child : S->arguments()) {

1254

1255

1256

1257

1258

1259

1260 if (child->getSourceRange().isInvalid()) {

1262 syntax::NodeKind::PostfixUnaryOperatorExpression);

1263 continue;

1264 }

1266 return false;

1267 }

1268 return WalkUpFromCXXOperatorCallExpr(S);

1269 }

1270

1273 case syntax::NodeKind::BinaryOperatorExpression:

1274 Builder.markExprChild(S->getArg(0), syntax::NodeRole::LeftHandSide);

1275 Builder.markChildToken(S->getOperatorLoc(),

1276 syntax::NodeRole::OperatorToken);

1277 Builder.markExprChild(S->getArg(1), syntax::NodeRole::RightHandSide);

1278 Builder.foldNode(Builder.getExprRange(S),

1280 return true;

1281 case syntax::NodeKind::PrefixUnaryOperatorExpression:

1282 Builder.markChildToken(S->getOperatorLoc(),

1283 syntax::NodeRole::OperatorToken);

1284 Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);

1285 Builder.foldNode(Builder.getExprRange(S),

1287 S);

1288 return true;

1289 case syntax::NodeKind::PostfixUnaryOperatorExpression:

1290 Builder.markChildToken(S->getOperatorLoc(),

1291 syntax::NodeRole::OperatorToken);

1292 Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);

1293 Builder.foldNode(Builder.getExprRange(S),

1295 S);

1296 return true;

1297 case syntax::NodeKind::CallExpression: {

1298 Builder.markExprChild(S->getArg(0), syntax::NodeRole::Callee);

1299

1300 const auto *LParenToken =

1301 std::next(Builder.findToken(S->getArg(0)->getEndLoc()));

1302

1303

1304 if (LParenToken->kind() == clang::tok::l_paren)

1305 Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);

1306

1308 S->arg_begin() + 1, S->arg_end())),

1309 syntax::NodeRole::Arguments);

1310

1311 Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);

1312

1313 Builder.foldNode(Builder.getRange(S->getSourceRange()),

1314 new (allocator()) syntax::CallExpression, S);

1315 return true;

1316 }

1317 case syntax::NodeKind::UnknownExpression:

1318 return WalkUpFromExpr(S);

1319 default:

1320 llvm_unreachable("getOperatorNodeKind() does not return this value");

1321 }

1322 }

1323

1324 bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; }

1325

1326 bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {

1327 auto Tokens = Builder.getDeclarationRange(S);

1328 if (Tokens.front().kind() == tok::coloncolon) {

1329

1330

1331

1332 return true;

1333 }

1335 return true;

1336 }

1337

1338

1339

1341

1342 if (!WalkUpFromParenTypeLoc(L))

1343 return false;

1345 }

1346

1347 bool WalkUpFromParenTypeLoc(ParenTypeLoc L) {

1348 Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);

1349 Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);

1352 return true;

1353 }

1354

1355

1356 bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L) {

1357 Builder.markChildToken(L.getLBracketLoc(), syntax::NodeRole::OpenParen);

1358 Builder.markExprChild(L.getSizeExpr(), syntax::NodeRole::Size);

1359 Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen);

1362 return true;

1363 }

1364

1367 for (auto *P : Params) {

1368 Builder.markChild(P, syntax::NodeRole::ListElement);

1369 const auto *DelimiterToken = std::next(Builder.findToken(P->getEndLoc()));

1370 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)

1371 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);

1372 }

1374 if (!Params.empty())

1375 Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(),

1376 Params.back()->getEndLoc()),

1379 }

1380

1382 Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);

1383

1384 Builder.markChild(buildParameterDeclarationList(L.getParams()),

1385 syntax::NodeRole::Parameters);

1386

1387 Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);

1390 return true;

1391 }

1392

1395 return WalkUpFromFunctionTypeLoc(L);

1396

1397 auto *TrailingReturnTokens = buildTrailingReturn(L);

1398

1399 Builder.markChild(TrailingReturnTokens, syntax::NodeRole::TrailingReturn);

1400 return WalkUpFromFunctionTypeLoc(L);

1401 }

1402

1404

1405

1406

1407

1408 if (!WalkUpFromMemberPointerTypeLoc(L))

1409 return false;

1411 }

1412

1415 Builder.foldNode(Builder.getRange(SR),

1417 return true;

1418 }

1419

1420

1421

1422

1423 bool WalkUpFromDeclStmt(DeclStmt *S) {

1424 Builder.foldNode(Builder.getStmtRange(S),

1426 return true;

1427 }

1428

1429 bool WalkUpFromNullStmt(NullStmt *S) {

1430 Builder.foldNode(Builder.getStmtRange(S),

1432 return true;

1433 }

1434

1435 bool WalkUpFromSwitchStmt(SwitchStmt *S) {

1436 Builder.markChildToken(S->getSwitchLoc(),

1437 syntax::NodeRole::IntroducerKeyword);

1438 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);

1439 Builder.foldNode(Builder.getStmtRange(S),

1441 return true;

1442 }

1443

1444 bool WalkUpFromCaseStmt(CaseStmt *S) {

1445 Builder.markChildToken(S->getKeywordLoc(),

1446 syntax::NodeRole::IntroducerKeyword);

1447 Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseValue);

1448 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);

1449 Builder.foldNode(Builder.getStmtRange(S),

1451 return true;

1452 }

1453

1454 bool WalkUpFromDefaultStmt(DefaultStmt *S) {

1455 Builder.markChildToken(S->getKeywordLoc(),

1456 syntax::NodeRole::IntroducerKeyword);

1457 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);

1458 Builder.foldNode(Builder.getStmtRange(S),

1460 return true;

1461 }

1462

1463 bool WalkUpFromIfStmt(IfStmt *S) {

1464 Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword);

1465 Stmt *ConditionStatement = S->getCond();

1466 if (S->hasVarStorage())

1467 ConditionStatement = S->getConditionVariableDeclStmt();

1468 Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition);

1469 Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement);

1470 Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword);

1471 Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement);

1472 Builder.foldNode(Builder.getStmtRange(S),

1474 return true;

1475 }

1476

1477 bool WalkUpFromForStmt(ForStmt *S) {

1478 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);

1479 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);

1480 Builder.foldNode(Builder.getStmtRange(S),

1482 return true;

1483 }

1484

1485 bool WalkUpFromWhileStmt(WhileStmt *S) {

1486 Builder.markChildToken(S->getWhileLoc(),

1487 syntax::NodeRole::IntroducerKeyword);

1488 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);

1489 Builder.foldNode(Builder.getStmtRange(S),

1491 return true;

1492 }

1493

1494 bool WalkUpFromContinueStmt(ContinueStmt *S) {

1495 Builder.markChildToken(S->getContinueLoc(),

1496 syntax::NodeRole::IntroducerKeyword);

1497 Builder.foldNode(Builder.getStmtRange(S),

1499 return true;

1500 }

1501

1502 bool WalkUpFromBreakStmt(BreakStmt *S) {

1503 Builder.markChildToken(S->getBreakLoc(),

1504 syntax::NodeRole::IntroducerKeyword);

1505 Builder.foldNode(Builder.getStmtRange(S),

1507 return true;

1508 }

1509

1510 bool WalkUpFromReturnStmt(ReturnStmt *S) {

1511 Builder.markChildToken(S->getReturnLoc(),

1512 syntax::NodeRole::IntroducerKeyword);

1513 Builder.markExprChild(S->getRetValue(), syntax::NodeRole::ReturnValue);

1514 Builder.foldNode(Builder.getStmtRange(S),

1516 return true;

1517 }

1518

1520 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);

1521 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);

1522 Builder.foldNode(Builder.getStmtRange(S),

1524 return true;

1525 }

1526

1527 bool WalkUpFromEmptyDecl(EmptyDecl *S) {

1528 Builder.foldNode(Builder.getDeclarationRange(S),

1530 return true;

1531 }

1532

1534 Builder.markExprChild(S->getAssertExpr(), syntax::NodeRole::Condition);

1535 Builder.markExprChild(S->getMessage(), syntax::NodeRole::Message);

1536 Builder.foldNode(Builder.getDeclarationRange(S),

1538 return true;

1539 }

1540

1542 Builder.foldNode(Builder.getDeclarationRange(S),

1544 S);

1545 return true;

1546 }

1547

1549 Builder.foldNode(Builder.getDeclarationRange(S),

1551 return true;

1552 }

1553

1555 Builder.foldNode(Builder.getDeclarationRange(S),

1557 return true;

1558 }

1559

1560 bool WalkUpFromUsingDecl(UsingDecl *S) {

1561 Builder.foldNode(Builder.getDeclarationRange(S),

1563 return true;

1564 }

1565

1567 Builder.foldNode(Builder.getDeclarationRange(S),

1569 return true;

1570 }

1571

1573 Builder.foldNode(Builder.getDeclarationRange(S),

1575 return true;

1576 }

1577

1578 bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) {

1579 Builder.foldNode(Builder.getDeclarationRange(S),

1581 return true;

1582 }

1583

1584private:

1585

1586

1587 template bool processDeclaratorAndDeclaration(T *D) {

1589 Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(),

1591

1592

1593

1596 syntax::NodeRole::Declarators);

1597 Builder.foldNode(Builder.getDeclarationRange(D),

1599 return true;

1600 }

1601

1603 Builder.foldNode(Builder.getRange(Range), N, nullptr);

1604 Builder.markChild(N, syntax::NodeRole::ListElement);

1605

1606 if (!Builder.isResponsibleForCreatingDeclaration(D)) {

1607

1608

1609 const auto *DelimiterToken = std::next(Builder.findToken(Range.getEnd()));

1610 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)

1611 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);

1612 } else {

1614 auto DeclarationRange = Builder.getDeclarationRange(D);

1615 Builder.foldList(DeclarationRange, DL, nullptr);

1616

1617 Builder.markChild(DL, syntax::NodeRole::Declarators);

1618 Builder.foldNode(DeclarationRange,

1620 }

1621 return true;

1622 }

1623

1624

1627

1629

1630 auto ReturnDeclaratorRange = SourceRange(GetStartLoc().Visit(ReturnedType),

1631 ReturnedType.getEndLoc());

1633 if (ReturnDeclaratorRange.isValid()) {

1635 Builder.foldNode(Builder.getRange(ReturnDeclaratorRange),

1636 ReturnDeclarator, nullptr);

1637 }

1638

1639

1640 auto Return = Builder.getRange(ReturnedType.getSourceRange());

1641 const auto *Arrow = Return.begin() - 1;

1642 assert(Arrow->kind() == tok::arrow);

1644 Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken);

1645 if (ReturnDeclarator)

1646 Builder.markChild(ReturnDeclarator, syntax::NodeRole::Declarator);

1648 Builder.foldNode(Tokens, R, L);

1649 return R;

1650 }

1651

1652 void foldExplicitTemplateInstantiation(

1656 assert(!ExternKW || ExternKW->kind() == tok::kw_extern);

1657 assert(TemplateKW && TemplateKW->kind() == tok::kw_template);

1658 Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword);

1659 Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);

1660 Builder.markChild(InnerDeclaration, syntax::NodeRole::Declaration);

1661 Builder.foldNode(

1663 }

1664

1668 assert(TemplateKW && TemplateKW->kind() == tok::kw_template);

1669 Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);

1670

1672 Builder.foldNode(Range, N, From);

1673 Builder.markChild(N, syntax::NodeRole::Declaration);

1674 return N;

1675 }

1676

1677

1678 llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); }

1679

1682};

1683}

1684

1686 DeclsWithoutSemicolons.insert(D);

1687}

1688

1691 return;

1692 Pending.assignRole(*findToken(Loc), Role);

1693}

1694

1696 if (T)

1697 return;

1698 Pending.assignRole(*T, R);

1699}

1700

1702 assert(N);

1703 setRole(N, R);

1704}

1705

1707 auto *SN = Mapping.find(N);

1708 assert(SN != nullptr);

1709 setRole(SN, R);

1710}

1712 auto *SN = Mapping.find(NNSLoc);

1713 assert(SN != nullptr);

1714 setRole(SN, R);

1715}

1716

1718 if (!Child)

1719 return;

1720

1722 if (Expr *ChildExpr = dyn_cast(Child)) {

1723

1724

1727

1728 Pending.foldChildren(TBTM.tokenBuffer(), getStmtRange(Child), ChildNode);

1729 } else {

1730 ChildNode = Mapping.find(Child);

1731 }

1732 assert(ChildNode != nullptr);

1733 setRole(ChildNode, Role);

1734}

1735

1737 if (!Child)

1738 return;

1740

1741 syntax::Tree *ChildNode = Mapping.find(Child);

1742 assert(ChildNode != nullptr);

1743 setRole(ChildNode, Role);

1744}

1745

1748 return nullptr;

1749 auto It = LocationToToken.find(L);

1750 assert(It != LocationToToken.end());

1751 return It->second;

1752}

1753

1758 BuildTreeVisitor(Context, Builder).TraverseAST(Context);

1759 return std::move(Builder).finalize();

1760}

Forward declaration of all AST node types.

BoundNodesTreeBuilder Nodes

static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, SourceLocation Name, SourceRange Initializer)

Gets the range of declarator as defined by the C++ grammar.

static Expr * IgnoreImplicit(Expr *E)

static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args)

static LLVM_ATTRIBUTE_UNUSED bool isImplicitExpr(Expr *E)

static Expr * IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E)

static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E)

static SourceLocation getQualifiedNameStart(NamedDecl *D)

Get the start of the qualified name.

static SourceRange getInitializerRange(Decl *D)

Gets the range of the initializer inside an init-declarator C++ [dcl.decl].

static Expr * IgnoreImplicitConstructorSingleStep(Expr *E)

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the clang::Expr interface and subclasses for C++ expressions.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::SourceLocation class and associated facilities.

Defines the SourceManager interface.

Defines various enumerations that describe declaration and type specifiers.

Defines the clang::TokenKind enum and support functions.

Defines the clang::TypeLoc interface and its subclasses.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

const LangOptions & getLangOpts() const

DiagnosticsEngine & getDiagnostics() const

const TargetInfo & getTargetInfo() const

Wrapper for source info for arrays.

SourceLocation getLBracketLoc() const

Expr * getSizeExpr() const

SourceLocation getRBracketLoc() const

A builtin binary operation expression such as "x + y" or "x <= y".

Wrapper for source info for block pointers.

BreakStmt - This represents a break.

A boolean literal, per ([C++ lex.bool] Boolean literals).

Represents a call to a C++ constructor.

A default argument (C++ [dcl.fct.default]).

CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...

The null pointer literal (C++11 [lex.nullptr])

A call to an overloaded operator written using operator syntax.

Represents the this expression in C++.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

llvm::iterator_range< arg_iterator > arg_range

CaseStmt - Represent a case statement.

Represents a class template specialization, which refers to a class template with a given set of temp...

CompoundStmt - This represents a group of statements like { stmt stmt }.

ContinueStmt - This represents a continue.

A reference to a declared variable, function, enum, etc.

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

Decl - This represents one declaration (or definition), e.g.

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

Decl * getNextDeclInContext()

SourceLocation getLocation() const

SourceLocation getBeginLoc() const LLVM_READONLY

virtual SourceRange getSourceRange() const LLVM_READONLY

Source range that this declaration covers.

Represents a ValueDecl that came out of a declarator.

A qualified reference to a name whose declaration cannot yet be resolved.

Represents an empty-declaration.

This represents one expression.

ForStmt - This represents a 'for (init;cond;inc)' stmt.

bool hasTrailingReturn() const

Whether this function prototype has a trailing return type.

Wrapper for source info for functions.

ArrayRef< ParmVarDecl * > getParams() const

TypeLoc getReturnLoc() const

SourceLocation getLParenLoc() const

SourceLocation getRParenLoc() const

IfStmt - This represents an if/then/else.

const TypeClass * getTypePtr() const

Represents a linkage specification.

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

Wrapper for source info for member pointers.

SourceRange getLocalSourceRange() const

This represents a decl that may have a name.

Represents a C++ namespace alias.

Represent a C++ namespace.

A C++ nested-name-specifier augmented with source location information.

SourceLocation getBeginLoc() const

Retrieve the location of the beginning of this nested-name-specifier.

TypeLoc getTypeLoc() const

For a nested-name-specifier that refers to a type, retrieve the type with source-location information...

SourceRange getLocalSourceRange() const

Retrieve the source range covering just the last part of this nested-name-specifier,...

bool hasQualifier() const

Evaluates true when this nested-name-specifier location is non-empty.

NestedNameSpecifier * getNestedNameSpecifier() const

Retrieve the nested-name-specifier to which this instance refers.

SourceRange getSourceRange() const LLVM_READONLY

Retrieve the source range covering the entirety of this nested-name-specifier.

Represents a C++ nested name specifier, such as "\::std::vector::".

SpecifierKind getKind() const

Determine what kind of nested name specifier is stored.

@ NamespaceAlias

A namespace alias, stored as a NamespaceAliasDecl*.

@ TypeSpec

A type, stored as a Type*.

@ TypeSpecWithTemplate

A type that was preceded by the 'template' keyword, stored as a Type*.

@ Identifier

An identifier, stored as an IdentifierInfo*.

@ Global

The global specifier '::'. There is no stored value.

@ Namespace

A namespace, stored as a NamespaceDecl*.

const Type * getAsType() const

Retrieve the type stored in this nested name specifier.

NullStmt - This is the null statement ";": C99 6.8.3p3.

NumericLiteralParser - This performs strict semantic analysis of the content of a ppnumber,...

Wraps an ObjCPointerType with source location information.

OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.

ParenExpr - This represents a parenthesized expression, e.g.

SourceLocation getRParenLoc() const

SourceLocation getLParenLoc() const

TypeLoc getInnerLoc() const

TypeLoc getPointeeLoc() const

Wrapper for source info for pointers.

A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...

bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)

Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...

bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)

Recursively visit a C++ nested-name-specifier with location information.

bool TraverseDecl(Decl *D)

Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...

bool WalkUpFromStmt(Stmt *S)

bool TraverseTypeLoc(TypeLoc TL)

Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...

bool shouldTraversePostOrder() const

Return whether this visitor should traverse post-order.

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

This class handles loading and caching of source files into memory.

bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const

Determines the order of 2 source locations in the translation unit.

A trivial tuple used to represent a source range.

void setBegin(SourceLocation b)

SourceLocation getEnd() const

SourceLocation getBegin() const

Represents a C++11 static_assert declaration.

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

StringLiteral - This represents a string literal expression, e.g.

SwitchStmt - This represents a 'switch' stmt.

Represents the declaration of a struct/union/class/enum.

The base class of all kinds of template declarations (e.g., class, function, etc.).

Stores a list of template parameters for a TemplateDecl and its derived classes.

The top declaration context.

Represents the declaration of a typedef-name via a C++11 alias-declaration.

RetTy Visit(TypeLoc TyLoc)

RetTy VisitTypeLoc(TypeLoc TyLoc)

Base wrapper for a particular "section" of type source info.

T castAs() const

Convert to the specified TypeLoc type, asserting that this TypeLoc is of the desired type.

SourceLocation getEndLoc() const

Get the end source location.

Base class for declarations which introduce a typedef-name.

UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...

Represents a dependent using declaration which was marked with typename.

Represents a dependent using declaration which was not marked with typename.

A call to a literal operator (C++11 [over.literal]) written as a user-defined literal (C++11 [lit....

@ LOK_String

operator "" X (const CharT *, size_t)

@ LOK_Raw

Raw form: operator "" X (const char *)

@ LOK_Floating

operator "" X (long double)

@ LOK_Integer

operator "" X (unsigned long long)

@ LOK_Template

Raw form: operator "" X<cs...> ()

@ LOK_Character

operator "" X (CharT)

Represents a C++ using-declaration.

Represents C++ using-directive.

WhileStmt - This represents a 'while' stmt.

A memory arena for syntax trees.

llvm::BumpPtrAllocator & getAllocator()

Array size specified inside a declarator.

Models arguments of a function call.

{ statement1; statement2; … }

A declaration that can appear at the top-level.

A semicolon in the top-level context. Does not declare anything.

The no-op statement, i.e. ';'.

template Examples: template struct X template void foo() template int var<dou...

Expression in a statement position, e.g.

for (; ; )

if (cond) else FIXME: add condition that models 'expression or vari...

A leaf node points to a single token.

extern declaration extern { }

A list of Elements separated or terminated by a fixed token.

Member pointer inside a declarator E.g.

namespace =

namespace { }

Models a nested-name-specifier.

Models a parameter-declaration-list which appears within parameters-and-qualifiers.

Parameter list for a function type and a trailing return type, if the function has one.

Declarator inside parentheses.

for ( : )

Groups multiple declarators (e.g.

A top-level declarator without parentheses.

static_assert(, ) static_assert()

template

A TokenBuffer-powered token manager.

const TokenBuffer & tokenBuffer() const

SourceManager & sourceManager()

A list of tokens obtained by preprocessing a text buffer and operations to map between the expanded a...

llvm::ArrayRef< syntax::Token > expandedTokens() const

All tokens produced by the preprocessor after all macro replacements, directives, etc.

std::optional< llvm::ArrayRef< syntax::Token > > spelledForExpanded(llvm::ArrayRef< syntax::Token > Expanded) const

Returns the subrange of spelled tokens corresponding to AST node spanning Expanded.

uintptr_t Key

A key to identify a specific token.

A token coming directly from a file or from a macro invocation.

tok::TokenKind kind() const

Trailing return type after the parameter list, including the arrow token.

A node that has children and represents a syntactic language construct.

Declaration of an unknown kind, e.g. not yet supported in syntax trees.

An expression of an unknown kind, i.e.

A statement of an unknown kind, i.e.

Models an unqualified-id.

using :: using typename ::

A helper class for constructing the syntax tree while traversing a clang AST.

ArrayRef< syntax::Token > getRange(SourceLocation First, SourceLocation Last) const

Finds the syntax tokens corresponding to the passed source locations.

ArrayRef< syntax::Token > getStmtRange(const Stmt *S) const

Find the adjusted range for the statement, consuming the trailing semicolon when needed.

void foldList(ArrayRef< syntax::Token > SuperRange, syntax::List *New, ASTPtr From)

Populate children for New list, assuming it covers tokens from a subrange of SuperRange.

void markExprChild(Expr *Child, NodeRole Role)

Should be called for expressions in non-statement position to avoid wrapping into expression statemen...

const SourceManager & sourceManager() const

void markChildToken(SourceLocation Loc, NodeRole R)

Set role for a token starting at Loc.

ArrayRef< syntax::Token > getDeclarationRange(Decl *D)

void markChild(syntax::Node *N, NodeRole R)

Set role for N.

void foldNode(ArrayRef< syntax::Token > Range, syntax::Tree *New, TypeLoc L)

const syntax::Token * findToken(SourceLocation L) const

Finds a token starting at L. The token must exist if L is valid.

void noticeDeclWithoutSemicolon(Decl *D)

Notifies that we should not consume trailing semicolon when computing token range of D.

ArrayRef< syntax::Token > getRange(SourceRange Range) const

Finds the syntax tokens corresponding to the SourceRange.

bool isResponsibleForCreatingDeclaration(const Decl *D) const

Returns true if D is the last declarator in a chain and is thus reponsible for creating SimpleDeclara...

syntax::TranslationUnit * finalize() &&

Finish building the tree and consume the root node.

void foldNode(ArrayRef< syntax::Token > Range, syntax::Tree *New, ASTPtr From)

Populate children for New node, assuming it covers tokens from Range.

TreeBuilder(syntax::Arena &Arena, TokenBufferTokenManager &TBTM)

ArrayRef< syntax::Token > getTemplateRange(const ClassTemplateSpecializationDecl *D) const

void foldNode(llvm::ArrayRef< syntax::Token > Range, syntax::Tree *New, NestedNameSpecifierLoc From)

ArrayRef< syntax::Token > getExprRange(const Expr *E) const

void markStmtChild(Stmt *Child, NodeRole Role)

Mark the Child node with a corresponding Role.

llvm::BumpPtrAllocator & allocator()

uint32_t Literal

Literals are represented as positive integers.

NodeRole

A relation between a parent and child node, e.g.

@ ListElement

List API roles.

@ Detached

A node without a parent.

@ Unknown

Children of an unknown semantic nature, e.g. skipped tokens, comments.

syntax::TranslationUnit * buildSyntaxTree(Arena &A, TokenBufferTokenManager &TBTM, ASTContext &Context)

Build a syntax tree for the main file.

NodeKind

A kind of a syntax node, used for implementing casts.

The JSON file list parser is used to communicate input to InstallAPI.

@ OO_None

Not an overloaded operator.

@ NUM_OVERLOADED_OPERATORS

Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)

Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...

@ Result

The result type of a method or function.

Expr * IgnoreImplicitSingleStep(Expr *E)

const FunctionProtoType * T

void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)