clang: lib/Tooling/Syntax/BuildTree.cpp Source File (original) (raw)
1
2
3
4
5
6
7
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/PointerUnion.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/SmallVector.h"
37#include "llvm/Support/Allocator.h"
38#include "llvm/Support/Compiler.h"
39#include "llvm/Support/FormatVariadic.h"
40#include
41
42using namespace clang;
43
44
45
46
48 if (auto *C = dyn_cast(E)) {
49 auto NumArgs = C->getNumArgs();
52 if (C->getParenOrBraceRange().isInvalid())
53 return A;
54 }
55 }
56 return E;
57}
58
59
60
61
62
63
64
65
67 if (auto *F = dyn_cast(E)) {
68 if (F->getCastKind() == CK_ConstructorConversion)
69 return F->getSubExpr();
70 }
71 return E;
72}
73
79
80[[maybe_unused]]
84
85namespace {
86
87
88
89
90
91
92
93
94
95
96
97
98struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> {
99 SourceLocation VisitParenTypeLoc(ParenTypeLoc T) {
100 auto L = Visit(T.getInnerLoc());
101 if (L.isValid())
102 return L;
103 return T.getLParenLoc();
104 }
105
106
107 SourceLocation VisitPointerTypeLoc(PointerTypeLoc T) {
108 return HandlePointer(T);
109 }
110
111 SourceLocation VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
112 return HandlePointer(T);
113 }
114
115 SourceLocation VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
116 return HandlePointer(T);
117 }
118
119 SourceLocation VisitReferenceTypeLoc(ReferenceTypeLoc T) {
120 return HandlePointer(T);
121 }
122
123 SourceLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc T) {
124 return HandlePointer(T);
125 }
126
127
128
129
130
131 SourceLocation VisitTypeLoc(TypeLoc T) {
132 auto N = T.getNextTypeLoc();
133 if (!N)
134 return SourceLocation();
135 return Visit(N);
136 }
137
138 SourceLocation VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc T) {
140 return SourceLocation();
141 return VisitTypeLoc(T);
142 }
143
144private:
145 template SourceLocation HandlePointer(PtrLoc T) {
146 auto L = Visit(T.getPointeeLoc());
147 if (L.isValid())
148 return L;
149 return T.getLocalSourceRange().getBegin();
150 }
151};
152}
153
155 auto FirstDefaultArg =
157 return llvm::make_range(Args.begin(), FirstDefaultArg);
158}
159
162
163 case OO_EqualEqual:
164 case OO_ExclaimEqual:
165 case OO_Greater:
166 case OO_GreaterEqual:
167 case OO_Less:
168 case OO_LessEqual:
169 case OO_Spaceship:
170
171 case OO_Equal:
172 case OO_SlashEqual:
173 case OO_PercentEqual:
174 case OO_CaretEqual:
175 case OO_PipeEqual:
176 case OO_LessLessEqual:
177 case OO_GreaterGreaterEqual:
178 case OO_PlusEqual:
179 case OO_MinusEqual:
180 case OO_StarEqual:
181 case OO_AmpEqual:
182
183 case OO_Slash:
184 case OO_Percent:
185 case OO_Caret:
186 case OO_Pipe:
187 case OO_LessLess:
188 case OO_GreaterGreater:
189 case OO_AmpAmp:
190 case OO_PipePipe:
191 case OO_ArrowStar:
192 case OO_Comma:
193 return syntax::NodeKind::BinaryOperatorExpression;
194 case OO_Tilde:
195 case OO_Exclaim:
196 return syntax::NodeKind::PrefixUnaryOperatorExpression;
197
198 case OO_PlusPlus:
199 case OO_MinusMinus:
201 case 1:
202 return syntax::NodeKind::PrefixUnaryOperatorExpression;
203 case 2:
204 return syntax::NodeKind::PostfixUnaryOperatorExpression;
205 default:
206 llvm_unreachable("Invalid number of arguments for operator");
207 }
208
209 case OO_Plus:
210 case OO_Minus:
211 case OO_Star:
212 case OO_Amp:
214 case 1:
215 return syntax::NodeKind::PrefixUnaryOperatorExpression;
216 case 2:
217 return syntax::NodeKind::BinaryOperatorExpression;
218 default:
219 llvm_unreachable("Invalid number of arguments for operator");
220 }
221 return syntax::NodeKind::BinaryOperatorExpression;
222
223 case OO_New:
224 case OO_Delete:
225 case OO_Array_New:
226 case OO_Array_Delete:
227 case OO_Coawait:
228 case OO_Subscript:
229 case OO_Arrow:
230 return syntax::NodeKind::UnknownExpression;
231 case OO_Call:
232 return syntax::NodeKind::CallExpression;
233 case OO_Conditional:
236 llvm_unreachable("Not an overloadable operator");
237 }
238 llvm_unreachable("Unknown OverloadedOperatorKind enum");
239}
240
241
242
243
244
245
248 "only DeclaratorDecl and TypedefNameDecl are supported.");
249
251 bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo();
252 if (IsAnonymous)
254
255 if (const auto *DD = dyn_cast(D)) {
256 if (DD->getQualifierLoc()) {
257 return DD->getQualifierLoc().getBeginLoc();
258 }
259 }
260
262}
263
264
265
266
267
268
270 if (auto *V = dyn_cast(D)) {
271 auto *I = V->getInit();
272
273 if (I && ->isCXXForRangeDecl())
274 return I->getSourceRange();
275 }
276
278}
279
280
281
282
283
284
285
286
287
295 Start = Name;
296
297
298 if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name))
299 End = Name;
300 }
302 auto InitializerEnd = Initializer.getEnd();
303 assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) ||
304 End == InitializerEnd);
305 End = InitializerEnd;
306 }
308}
309
310namespace {
311
312using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;
313
314
315
316class ASTToSyntaxMapping {
317public:
318 void add(ASTPtr From, syntax::Tree *To) {
319 assert(To != nullptr);
320 assert(!From.isNull());
321
322 bool Added = Nodes.insert({From, To}).second;
323 (void)Added;
324 assert(Added && "mapping added twice");
325 }
326
327 void add(NestedNameSpecifierLoc From, syntax::Tree *To) {
328 assert(To != nullptr);
330
331 bool Added = NNSNodes.insert({From, To}).second;
332 (void)Added;
333 assert(Added && "mapping added twice");
334 }
335
336 syntax::Tree *find(ASTPtr P) const { return Nodes.lookup(P); }
337
338 syntax::Tree *find(NestedNameSpecifierLoc P) const {
339 return NNSNodes.lookup(P);
340 }
341
342private:
343 llvm::DenseMap<ASTPtr, syntax::Tree *> Nodes;
344 llvm::DenseMap<NestedNameSpecifierLoc, syntax::Tree *> NNSNodes;
345};
346}
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363class syntax::TreeBuilder {
364public:
365 TreeBuilder(syntax::Arena &Arena, TokenBufferTokenManager& TBTM)
366 : Arena(Arena),
367 TBTM(TBTM),
368 Pending(Arena, TBTM.tokenBuffer()) {
369 for (const auto &T : TBTM.tokenBuffer().expandedTokens())
370 LocationToToken.insert({T.location(), &T});
371 }
372
373 llvm::BumpPtrAllocator &allocator() { return Arena.getAllocator(); }
374 const SourceManager &sourceManager() const {
375 return TBTM.sourceManager();
376 }
377
378
379
380 void foldNode(ArrayRefsyntax::Token Range, syntax::Tree *New, ASTPtr From) {
381 assert(New);
382 Pending.foldChildren(TBTM.tokenBuffer(), Range, New);
383 if (From)
384 Mapping.add(From, New);
385 }
386
387 void foldNode(ArrayRefsyntax::Token Range, syntax::Tree *New, TypeLoc L) {
388
389 foldNode(Range, New, nullptr);
390 }
391
392 void foldNode(llvm::ArrayRefsyntax::Token Range, syntax::Tree *New,
393 NestedNameSpecifierLoc From) {
394 assert(New);
395 Pending.foldChildren(TBTM.tokenBuffer(), Range, New);
396 if (From)
397 Mapping.add(From, New);
398 }
399
400
401
402 void foldList(ArrayRefsyntax::Token SuperRange, syntax::List *New,
403 ASTPtr From) {
404 assert(New);
405 auto ListRange = Pending.shrinkToFitList(SuperRange);
406 Pending.foldChildren(TBTM.tokenBuffer(), ListRange, New);
407 if (From)
408 Mapping.add(From, New);
409 }
410
411
412
413 void noticeDeclWithoutSemicolon(Decl *D);
414
415
416
417
418
419 void markStmtChild(Stmt *Child, NodeRole Role);
420
421
422 void markExprChild(Expr *Child, NodeRole Role);
423
424 void markChildToken(SourceLocation Loc, NodeRole R);
425
426 void markChildToken(const syntax::Token *T, NodeRole R);
427
428
429 void markChild(syntax::Node *N, NodeRole R);
430
431 void markChild(ASTPtr N, NodeRole R);
432
433 void markChild(NestedNameSpecifierLoc N, NodeRole R);
434
435
436 syntax::TranslationUnit *finalize() && {
437 auto Tokens = TBTM.tokenBuffer().expandedTokens();
438 assert(!Tokens.empty());
439 assert(Tokens.back().kind() == tok::eof);
440
441
442 Pending.foldChildren(TBTM.tokenBuffer(), Tokens.drop_back(),
443 new (Arena.getAllocator()) syntax::TranslationUnit);
444
446 TU->assertInvariantsRecursive();
447 return TU;
448 }
449
450
451 const syntax::Token *findToken(SourceLocation L) const;
452
453
454 ArrayRefsyntax::Token getRange(SourceRange Range) const {
455 assert(Range.isValid());
457 }
458
459
460
461
462 ArrayRefsyntax::Token getRange(SourceLocation First,
463 SourceLocation Last) const {
464 assert(First.isValid());
465 assert(Last.isValid());
467 TBTM.sourceManager().isBeforeInTranslationUnit(First, Last));
468 return llvm::ArrayRef(findToken(First), std::next(findToken(Last)));
469 }
470
471 ArrayRefsyntax::Token
472 getTemplateRange(const ClassTemplateSpecializationDecl *D) const {
474 return maybeAppendSemicolon(Tokens, D);
475 }
476
477
478
479 bool isResponsibleForCreatingDeclaration(const Decl *D) const {
481 "only DeclaratorDecl and TypedefNameDecl are supported.");
482
484
485
486 if (Next == nullptr) {
487 return true;
488 }
489
490
492 return true;
493 }
494
495
497 return true;
498 }
499
500
501
502 return false;
503 }
504
505 ArrayRefsyntax::Token getDeclarationRange(Decl *D) {
506 ArrayRefsyntax::Token Tokens;
507
508 if (const auto *S = dyn_cast(D))
509 Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());
510 else
512 return maybeAppendSemicolon(Tokens, D);
513 }
514
515 ArrayRefsyntax::Token getExprRange(const Expr *E) const {
517 }
518
519
520
521 ArrayRefsyntax::Token getStmtRange(const Stmt *S) const {
524 return Tokens;
525
526
527
528 if (Tokens.back().kind() == tok::semi)
529 return Tokens;
530 return withTrailingSemicolon(Tokens);
531 }
532
533private:
534 ArrayRefsyntax::Token maybeAppendSemicolon(ArrayRefsyntax::Token Tokens,
535 const Decl *D) const {
537 return Tokens;
538 if (DeclsWithoutSemicolons.count(D))
539 return Tokens;
540
541
542 return withTrailingSemicolon(Tokens);
543 }
544
545 ArrayRefsyntax::Token
546 withTrailingSemicolon(ArrayRefsyntax::Token Tokens) const {
547 assert(!Tokens.empty());
548 assert(Tokens.back().kind() != tok::eof);
549
550 if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi)
551 return llvm::ArrayRef(Tokens.begin(), Tokens.end() + 1);
552 return Tokens;
553 }
554
555 void setRole(syntax::Node *N, NodeRole R) {
556 assert(N->getRole() == NodeRole::Detached);
557 N->setRole(R);
558 }
559
560
561
562
563
564
565
566 struct Forest {
567 Forest(syntax::Arena &A, const syntax::TokenBuffer &TB) {
569 assert(TB.expandedTokens().back().kind() == tok::eof);
570
571
574 syntax::Leaf(reinterpret_castTokenManager::Key\(&T));
575 L->Original = true;
577 Trees.insert(Trees.end(), {&T, L});
578 }
579 }
580
582 assert(.empty());
583 auto It = Trees.lower_bound(Range.begin());
584 assert(It != Trees.end() && "no node found");
585 assert(It->first == Range.begin() && "no child with the specified range");
586 assert((std::next(It) == Trees.end() ||
587 std::next(It)->first == Range.end()) &&
588 "no child with the specified range");
589 assert(It->second->getRole() == NodeRole::Detached &&
590 "re-assigning role for a child");
591 It->second->setRole(Role);
592 }
593
594
595
596 ArrayRefsyntax::Token shrinkToFitList(ArrayRefsyntax::Token Range) {
597 auto BeginChildren = Trees.lower_bound(Range.begin());
598 assert((BeginChildren == Trees.end() ||
599 BeginChildren->first == Range.begin()) &&
600 "Range crosses boundaries of existing subtrees");
601
602 auto EndChildren = Trees.lower_bound(Range.end());
603 assert(
604 (EndChildren == Trees.end() || EndChildren->first == Range.end()) &&
605 "Range crosses boundaries of existing subtrees");
606
607 auto BelongsToList = [](decltype(Trees)::value_type KV) {
608 auto Role = KV.second->getRole();
609 return Role == syntax::NodeRole::ListElement ||
610 Role == syntax::NodeRole::ListDelimiter;
611 };
612
613 auto BeginListChildren =
614 std::find_if(BeginChildren, EndChildren, BelongsToList);
615
616 auto EndListChildren =
617 std::find_if_not(BeginListChildren, EndChildren, BelongsToList);
618
619 return ArrayRefsyntax::Token(BeginListChildren->first,
620 EndListChildren->first);
621 }
622
623
624 void foldChildren(const syntax::TokenBuffer &TB,
625 ArrayRefsyntax::Token Tokens, syntax::Tree *Node) {
626
627 assert(Node->getFirstChild() == nullptr && "node already has children");
628
629 auto *FirstToken = Tokens.begin();
630 auto BeginChildren = Trees.lower_bound(FirstToken);
631
632 assert((BeginChildren == Trees.end() ||
633 BeginChildren->first == FirstToken) &&
634 "fold crosses boundaries of existing subtrees");
635 auto EndChildren = Trees.lower_bound(Tokens.end());
636 assert(
637 (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) &&
638 "fold crosses boundaries of existing subtrees");
639
640 for (auto It = BeginChildren; It != EndChildren; ++It) {
641 auto *C = It->second;
642 if (C->getRole() == NodeRole::Detached)
643 C->setRole(NodeRole::Unknown);
644 Node->appendChildLowLevel(C);
645 }
646
647
648 Node->Original = true;
649 Node->CanModify =
651
652 Trees.erase(BeginChildren, EndChildren);
653 Trees.insert({FirstToken, Node});
654 }
655
656
657 syntax::Node *finalize() && {
658 assert(Trees.size() == 1);
659 auto *Root = Trees.begin()->second;
660 Trees = {};
661 return Root;
662 }
663
664 std::string str(const syntax::TokenBufferTokenManager &STM) const {
665 std::string R;
666 for (auto It = Trees.begin(); It != Trees.end(); ++It) {
667 unsigned CoveredTokens =
668 It != Trees.end()
669 ? (std::next(It)->first - It->first)
670 : STM.tokenBuffer().expandedTokens().end() - It->first;
671
672 R += std::string(
673 formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(),
674 It->first->text(STM.sourceManager()), CoveredTokens));
675 R += It->second->dump(STM);
676 }
677 return R;
678 }
679
680 private:
681
682
683
684 std::map<const syntax::Token *, syntax::Node *> Trees;
685 };
686
687
688 std::string str() { return Pending.str(TBTM); }
689
690 syntax::Arena &Arena;
691 TokenBufferTokenManager& TBTM;
692
693 llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken;
694 Forest Pending;
695 llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
696 ASTToSyntaxMapping Mapping;
697};
698
699namespace {
701public:
702 explicit BuildTreeVisitor(ASTContext &Context, syntax::TreeBuilder &Builder)
703 : Builder(Builder), Context(Context) {}
704
706
707 bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) {
708 return processDeclaratorAndDeclaration(DD);
709 }
710
711 bool WalkUpFromTypedefNameDecl(TypedefNameDecl *TD) {
712 return processDeclaratorAndDeclaration(TD);
713 }
714
717 Builder.foldNode(Builder.getDeclarationRange(D),
718 new (allocator()) syntax::UnknownDeclaration(), D);
719 return true;
720 }
721
722
723
724
725 bool
726 TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) {
727 if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))
728 return false;
729 if (C->isExplicitSpecialization())
730 return true;
733 foldExplicitTemplateInstantiation(
734 Builder.getTemplateRange(C),
735 Builder.findToken(C->getExternKeywordLoc()),
736 Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
737 return true;
738 }
739
740 bool WalkUpFromTemplateDecl(TemplateDecl *S) {
741 foldTemplateDeclaration(
742 Builder.getDeclarationRange(S),
745 return true;
746 }
747
748 bool WalkUpFromTagDecl(TagDecl *C) {
749
750 if (->isFreeStanding()) {
751 assert(C->getNumTemplateParameterLists() == 0);
752 return true;
753 }
754 handleFreeStandingTagDecl(C);
755 return true;
756 }
757
759 assert(C->isFreeStanding());
760
761 auto DeclarationRange = Builder.getDeclarationRange(C);
763 Builder.foldNode(DeclarationRange, Result, nullptr);
764
765
766 auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) {
767 const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
768 auto R = llvm::ArrayRef(TemplateKW, DeclarationRange.end());
770 foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);
771 DeclarationRange = R;
772 };
773 if (auto *S = dyn_cast(C))
774 ConsumeTemplateParameters(*S->getTemplateParameters());
775 for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
776 ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
778 }
779
780 bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) {
781
782
783 return true;
784 }
785
786 bool WalkUpFromCompoundStmt(CompoundStmt *S) {
788
789 Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen);
790 for (auto *Child : S->body())
791 Builder.markStmtChild(Child, NodeRole::Statement);
792 Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);
793
794 Builder.foldNode(Builder.getStmtRange(S),
795 new (allocator()) syntax::CompoundStatement, S);
796 return true;
797 }
798
799
801 Builder.foldNode(Builder.getStmtRange(S),
802 new (allocator()) syntax::UnknownStatement, S);
803 return true;
804 }
805
806 bool TraverseIfStmt(IfStmt *S) {
807 bool Result = [&, this]() {
809 return false;
810 }
811
812
813
816 return false;
817 } else if (S->getCond() && !TraverseStmt(S->getCond()))
818 return false;
819
821 return false;
823 return false;
824 return true;
825 }();
828 }
829
830 bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) {
831
832
833
834
835 bool Result = [&, this]() {
837 return false;
839 return false;
841 return false;
843 return false;
844 return true;
845 }();
848 }
849
851 if (auto *DS = dyn_cast_or_null(S)) {
852
853 for (auto *D : DS->decls())
854 Builder.noticeDeclWithoutSemicolon(D);
855 } else if (auto *E = dyn_cast_or_null(S)) {
857 }
859 }
860
861 bool TraverseOpaqueValueExpr(OpaqueValueExpr *VE) {
862
863 return true;
864 }
865
866
867 bool WalkUpFromExpr(Expr *E) {
868 assert((E) && "should be handled by TraverseStmt");
869 Builder.foldNode(Builder.getExprRange(E),
870 new (allocator()) syntax::UnknownExpression, E);
871 return true;
872 }
873
874 bool TraverseUserDefinedLiteral(UserDefinedLiteral *S) {
875
876
877
878
879
880 return WalkUpFromUserDefinedLiteral(S);
881 }
882
883 syntax::UserDefinedLiteralExpression *
884 buildUserDefinedLiteral(UserDefinedLiteral *S) {
887 return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
889 return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
891 return new (allocator()) syntax::CharUserDefinedLiteralExpression;
893 return new (allocator()) syntax::StringUserDefinedLiteralExpression;
896
897
898
899
901 auto TokSpelling =
904 NumericLiteralParser(TokSpelling, TokLoc, Context.getSourceManager(),
907 if (Literal.isIntegerLiteral())
908 return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
909 else {
910 assert(Literal.isFloatingLiteral());
911 return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
912 }
913 }
914 llvm_unreachable("Unknown literal operator kind.");
915 }
916
917 bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) {
918 Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
919 Builder.foldNode(Builder.getExprRange(S), buildUserDefinedLiteral(S), S);
920 return true;
921 }
922
923 syntax::NameSpecifier *buildIdentifier(SourceRange SR,
924 bool DropBack = false) {
925 auto NameSpecifierTokens = Builder.getRange(SR).drop_back(DropBack);
926 assert(NameSpecifierTokens.size() == 1);
927 Builder.markChildToken(NameSpecifierTokens.begin(),
928 syntax::NodeRole::Unknown);
929 auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
930 Builder.foldNode(NameSpecifierTokens, NS, nullptr);
931 return NS;
932 }
933
934 syntax::NameSpecifier *buildSimpleTemplateName(SourceRange SR) {
935 auto NameSpecifierTokens = Builder.getRange(SR);
936
937
938
939
940
941 auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
942 Builder.foldNode(NameSpecifierTokens, NS, nullptr);
943 return NS;
944 }
945
946 syntax::NameSpecifier *
947 buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) {
950 case NestedNameSpecifier::Kind::Global:
951 return new (allocator()) syntax::GlobalNameSpecifier;
952
953 case NestedNameSpecifier::Kind::Namespace:
955
959 case TypeLoc::Record:
960 case TypeLoc::InjectedClassName:
961 case TypeLoc::Enum:
963 case TypeLoc::Typedef:
965 case TypeLoc::UnresolvedUsing:
966 return buildIdentifier(
968 case TypeLoc::Using:
970 case TypeLoc::DependentName:
972 case TypeLoc::TemplateSpecialization: {
974 SourceLocation BeginLoc = TST.getTemplateKeywordLoc();
975 if (BeginLoc.isInvalid())
976 BeginLoc = TST.getTemplateNameLoc();
977 return buildSimpleTemplateName({BeginLoc, TST.getEndLoc()});
978 }
979 case TypeLoc::Decltype: {
981 if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(
982 DTL, true))
983 return nullptr;
984 auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
985
986
987
988
989 Builder.foldNode(Builder.getRange(DTL.getLocalSourceRange()), NS,
990 nullptr);
991 return NS;
992 }
993 default:
995 }
996 }
998
999 llvm::report_fatal_error("We don't yet support the __super specifier",
1000 true);
1001 }
1002 }
1003
1004
1005
1006
1007
1009 if (!QualifierLoc)
1010 return true;
1011 for (auto It = QualifierLoc; It; ) {
1012 auto *NS = buildNameSpecifier(It);
1013 if (!NS)
1014 return false;
1017 if (TypeLoc TL = It.getAsTypeLoc())
1018 It = TL.getPrefix();
1019 else
1020 It = It.getAsNamespaceAndPrefix().Prefix;
1021 }
1022 Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()),
1024 QualifierLoc);
1025 return true;
1026 }
1027
1031 ASTPtr From) {
1032 if (QualifierLoc) {
1034 if (TemplateKeywordLoc.isValid())
1035 Builder.markChildToken(TemplateKeywordLoc,
1037 }
1038
1040 Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId,
1041 nullptr);
1043
1044 auto IdExpressionBeginLoc =
1045 QualifierLoc ? QualifierLoc.getBeginLoc() : UnqualifiedIdLoc.getBegin();
1046
1047 auto *TheIdExpression = new (allocator()) syntax::IdExpression;
1048 Builder.foldNode(
1049 Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.getEnd()),
1050 TheIdExpression, From);
1051
1052 return TheIdExpression;
1053 }
1054
1056
1057
1058
1062 return true;
1063 }
1064
1068
1070
1073
1074 Builder.foldNode(Builder.getExprRange(S),
1075 new (allocator()) syntax::MemberExpression, S);
1076 return true;
1077 }
1078
1082
1083 return true;
1084 }
1085
1086
1090
1091 return true;
1092 }
1093
1096 Builder.markChildToken(S->getLocation(),
1098 Builder.foldNode(Builder.getExprRange(S),
1099 new (allocator()) syntax::ThisExpression, S);
1100 }
1101 return true;
1102 }
1103
1108 Builder.foldNode(Builder.getExprRange(S),
1109 new (allocator()) syntax::ParenExpression, S);
1110 return true;
1111 }
1112
1115 Builder.foldNode(Builder.getExprRange(S),
1116 new (allocator()) syntax::IntegerLiteralExpression, S);
1117 return true;
1118 }
1119
1122 Builder.foldNode(Builder.getExprRange(S),
1123 new (allocator()) syntax::CharacterLiteralExpression, S);
1124 return true;
1125 }
1126
1129 Builder.foldNode(Builder.getExprRange(S),
1130 new (allocator()) syntax::FloatingLiteralExpression, S);
1131 return true;
1132 }
1133
1136 Builder.foldNode(Builder.getExprRange(S),
1137 new (allocator()) syntax::StringLiteralExpression, S);
1138 return true;
1139 }
1140
1143 Builder.foldNode(Builder.getExprRange(S),
1144 new (allocator()) syntax::BoolLiteralExpression, S);
1145 return true;
1146 }
1147
1150 Builder.foldNode(Builder.getExprRange(S),
1151 new (allocator()) syntax::CxxNullPtrExpression, S);
1152 return true;
1153 }
1154
1159
1161 Builder.foldNode(Builder.getExprRange(S),
1163 S);
1164 else
1165 Builder.foldNode(Builder.getExprRange(S),
1167 S);
1168
1169 return true;
1170 }
1171
1177 Builder.foldNode(Builder.getExprRange(S),
1179 return true;
1180 }
1181
1182
1183
1184 syntax::CallArguments *
1187 for (auto *Arg : Args) {
1189 const auto *DelimiterToken =
1190 std::next(Builder.findToken(Arg->getEndLoc()));
1191 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1193 }
1194
1196 if (!Args.empty())
1197 Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(),
1198 (*(Args.end() - 1))->getEndLoc()),
1199 Arguments, nullptr);
1200
1201 return Arguments;
1202 }
1203
1206
1207 const auto *LParenToken =
1209
1210
1211 if (LParenToken->kind() == clang::tok::l_paren)
1213
1216
1218
1219 Builder.foldNode(Builder.getRange(S->getSourceRange()),
1220 new (allocator()) syntax::CallExpression, S);
1221 return true;
1222 }
1223
1225
1228 return true;
1229 return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S);
1230 }
1231
1233
1234
1235
1236
1237 for (auto *child : S->arguments()) {
1238
1239
1240
1241
1242
1243
1244 if (child->getSourceRange().isInvalid()) {
1246 syntax::NodeKind::PostfixUnaryOperatorExpression);
1247 continue;
1248 }
1250 return false;
1251 }
1253 }
1254
1257 case syntax::NodeKind::BinaryOperatorExpression:
1262 Builder.foldNode(Builder.getExprRange(S),
1264 return true;
1265 case syntax::NodeKind::PrefixUnaryOperatorExpression:
1269 Builder.foldNode(Builder.getExprRange(S),
1271 S);
1272 return true;
1273 case syntax::NodeKind::PostfixUnaryOperatorExpression:
1277 Builder.foldNode(Builder.getExprRange(S),
1279 S);
1280 return true;
1281 case syntax::NodeKind::CallExpression: {
1283
1284 const auto *LParenToken =
1285 std::next(Builder.findToken(S->getArg(0)->getEndLoc()));
1286
1287
1288 if (LParenToken->kind() == clang::tok::l_paren)
1290
1294
1296
1297 Builder.foldNode(Builder.getRange(S->getSourceRange()),
1298 new (allocator()) syntax::CallExpression, S);
1299 return true;
1300 }
1301 case syntax::NodeKind::UnknownExpression:
1302 return WalkUpFromExpr(S);
1303 default:
1304 llvm_unreachable("getOperatorNodeKind() does not return this value");
1305 }
1306 }
1307
1309
1311 auto Tokens = Builder.getDeclarationRange(S);
1312 if (Tokens.front().kind() == tok::coloncolon) {
1313
1314
1315
1316 return true;
1317 }
1319 return true;
1320 }
1321
1322
1323
1325
1327 return false;
1329 }
1330
1338
1339
1348
1349 syntax::ParameterDeclarationList *
1351 for (auto *P : Params) {
1353 const auto *DelimiterToken = std::next(Builder.findToken(P->getEndLoc()));
1354 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1356 }
1358 if (!Params.empty())
1359 Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(),
1360 Params.back()->getEndLoc()),
1361 Parameters, nullptr);
1362 return Parameters;
1363 }
1364
1367
1370
1374 return true;
1375 }
1376
1380
1381 auto *TrailingReturnTokens = buildTrailingReturn(L);
1382
1385 }
1386
1388 bool TraverseQualifier) {
1389
1390
1391
1392
1394 return false;
1396 }
1397
1400 Builder.foldNode(Builder.getRange(SR),
1402 return true;
1403 }
1404
1405
1406
1407
1409 Builder.foldNode(Builder.getStmtRange(S),
1411 return true;
1412 }
1413
1415 Builder.foldNode(Builder.getStmtRange(S),
1417 return true;
1418 }
1419
1424 Builder.foldNode(Builder.getStmtRange(S),
1426 return true;
1427 }
1428
1434 Builder.foldNode(Builder.getStmtRange(S),
1436 return true;
1437 }
1438
1443 Builder.foldNode(Builder.getStmtRange(S),
1445 return true;
1446 }
1447
1450 Stmt *ConditionStatement = S->getCond();
1457 Builder.foldNode(Builder.getStmtRange(S),
1459 return true;
1460 }
1461
1465 Builder.foldNode(Builder.getStmtRange(S),
1467 return true;
1468 }
1469
1471 Builder.markChildToken(S->getWhileLoc(),
1474 Builder.foldNode(Builder.getStmtRange(S),
1476 return true;
1477 }
1478
1481 Builder.foldNode(Builder.getStmtRange(S),
1483 return true;
1484 }
1485
1488 Builder.foldNode(Builder.getStmtRange(S),
1490 return true;
1491 }
1492
1497 Builder.foldNode(Builder.getStmtRange(S),
1499 return true;
1500 }
1501
1505 Builder.foldNode(Builder.getStmtRange(S),
1507 return true;
1508 }
1509
1511 Builder.foldNode(Builder.getDeclarationRange(S),
1513 return true;
1514 }
1515
1519 Builder.foldNode(Builder.getDeclarationRange(S),
1521 return true;
1522 }
1523
1525 Builder.foldNode(Builder.getDeclarationRange(S),
1527 S);
1528 return true;
1529 }
1530
1532 Builder.foldNode(Builder.getDeclarationRange(S),
1534 return true;
1535 }
1536
1538 Builder.foldNode(Builder.getDeclarationRange(S),
1540 return true;
1541 }
1542
1544 Builder.foldNode(Builder.getDeclarationRange(S),
1546 return true;
1547 }
1548
1550 Builder.foldNode(Builder.getDeclarationRange(S),
1552 return true;
1553 }
1554
1556 Builder.foldNode(Builder.getDeclarationRange(S),
1558 return true;
1559 }
1560
1562 Builder.foldNode(Builder.getDeclarationRange(S),
1564 return true;
1565 }
1566
1567private:
1568
1569
1570 template bool processDeclaratorAndDeclaration(T *D) {
1571 auto Range = getDeclaratorRange(
1572 Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(),
1574
1575
1576
1577 if (.getBegin().isValid()) {
1578 Builder.markChild(new (allocator()) syntax::DeclaratorList,
1579 syntax::NodeRole::Declarators);
1580 Builder.foldNode(Builder.getDeclarationRange(D),
1581 new (allocator()) syntax::SimpleDeclaration, D);
1582 return true;
1583 }
1584
1585 auto *N = new (allocator()) syntax::SimpleDeclarator;
1586 Builder.foldNode(Builder.getRange(Range), N, nullptr);
1587 Builder.markChild(N, syntax::NodeRole::ListElement);
1588
1589 if (!Builder.isResponsibleForCreatingDeclaration(D)) {
1590
1591
1592 const auto *DelimiterToken = std::next(Builder.findToken(Range.getEnd()));
1593 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1594 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1595 } else {
1596 auto *DL = new (allocator()) syntax::DeclaratorList;
1597 auto DeclarationRange = Builder.getDeclarationRange(D);
1598 Builder.foldList(DeclarationRange, DL, nullptr);
1599
1600 Builder.markChild(DL, syntax::NodeRole::Declarators);
1601 Builder.foldNode(DeclarationRange,
1602 new (allocator()) syntax::SimpleDeclaration, D);
1603 }
1604 return true;
1605 }
1606
1607
1608 syntax::TrailingReturnType *buildTrailingReturn(FunctionProtoTypeLoc L) {
1610
1612
1613 auto ReturnDeclaratorRange = SourceRange(GetStartLoc().Visit(ReturnedType),
1614 ReturnedType.getEndLoc());
1615 syntax::SimpleDeclarator *ReturnDeclarator = nullptr;
1616 if (ReturnDeclaratorRange.isValid()) {
1617 ReturnDeclarator = new (allocator()) syntax::SimpleDeclarator;
1618 Builder.foldNode(Builder.getRange(ReturnDeclaratorRange),
1619 ReturnDeclarator, nullptr);
1620 }
1621
1622
1623 auto Return = Builder.getRange(ReturnedType.getSourceRange());
1624 const auto *Arrow = Return.begin() - 1;
1625 assert(Arrow->kind() == tok::arrow);
1626 auto Tokens = llvm::ArrayRef(Arrow, Return.end());
1627 Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken);
1628 if (ReturnDeclarator)
1629 Builder.markChild(ReturnDeclarator, syntax::NodeRole::Declarator);
1630 auto *R = new (allocator()) syntax::TrailingReturnType;
1631 Builder.foldNode(Tokens, R, L);
1632 return R;
1633 }
1634
1635 void foldExplicitTemplateInstantiation(
1636 ArrayRefsyntax::Token Range, const syntax::Token *ExternKW,
1637 const syntax::Token *TemplateKW,
1638 syntax::SimpleDeclaration *InnerDeclaration, Decl *From) {
1639 assert(!ExternKW || ExternKW->kind() == tok::kw_extern);
1640 assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
1641 Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword);
1642 Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1643 Builder.markChild(InnerDeclaration, syntax::NodeRole::Declaration);
1644 Builder.foldNode(
1645 Range, new (allocator()) syntax::ExplicitTemplateInstantiation, From);
1646 }
1647
1648 syntax::TemplateDeclaration *foldTemplateDeclaration(
1649 ArrayRefsyntax::Token Range, const syntax::Token *TemplateKW,
1650 ArrayRefsyntax::Token TemplatedDeclaration, Decl *From) {
1651 assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
1652 Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1653
1654 auto *N = new (allocator()) syntax::TemplateDeclaration;
1655 Builder.foldNode(Range, N, From);
1656 Builder.markChild(N, syntax::NodeRole::Declaration);
1657 return N;
1658 }
1659
1660
1661 llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); }
1662
1663 syntax::TreeBuilder &Builder;
1664 const ASTContext &Context;
1665};
1666}
1667
1668void syntax::TreeBuilder::noticeDeclWithoutSemicolon(Decl *D) {
1669 DeclsWithoutSemicolons.insert(D);
1670}
1671
1672void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) {
1674 return;
1675 Pending.assignRole(*findToken(Loc), Role);
1676}
1677
1678void syntax::TreeBuilder::markChildToken(const syntax::Token *T, NodeRole R) {
1679 if ()
1680 return;
1681 Pending.assignRole(*T, R);
1682}
1683
1684void syntax::TreeBuilder::markChild(syntax::Node *N, NodeRole R) {
1685 assert(N);
1686 setRole(N, R);
1687}
1688
1689void syntax::TreeBuilder::markChild(ASTPtr N, NodeRole R) {
1690 auto *SN = Mapping.find(N);
1691 assert(SN != nullptr);
1692 setRole(SN, R);
1693}
1695 auto *SN = Mapping.find(NNSLoc);
1696 assert(SN != nullptr);
1697 setRole(SN, R);
1698}
1699
1700void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
1701 if (!Child)
1702 return;
1703
1705 if (Expr *ChildExpr = dyn_cast(Child)) {
1706
1707
1708 markExprChild(ChildExpr, NodeRole::Expression);
1710
1711 Pending.foldChildren(TBTM.tokenBuffer(), getStmtRange(Child), ChildNode);
1712 } else {
1713 ChildNode = Mapping.find(Child);
1714 }
1715 assert(ChildNode != nullptr);
1716 setRole(ChildNode, Role);
1717}
1718
1719void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
1720 if (!Child)
1721 return;
1723
1724 syntax::Tree *ChildNode = Mapping.find(Child);
1725 assert(ChildNode != nullptr);
1726 setRole(ChildNode, Role);
1727}
1728
1731 return nullptr;
1732 auto It = LocationToToken.find(L);
1733 assert(It != LocationToToken.end());
1734 return It->second;
1735}
1736
1740 TreeBuilder Builder(A, TBTM);
1741 BuildTreeVisitor(Context, Builder).TraverseAST(Context);
1742 return std::move(Builder).finalize();
1743}
Forward declaration of all AST node types.
bool WalkUpFromStringLiteral(StringLiteral *S)
Definition BuildTree.cpp:1134
bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S)
Definition BuildTree.cpp:1537
bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L)
Definition BuildTree.cpp:1365
bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S)
Definition BuildTree.cpp:1549
bool WalkUpFromParenExpr(ParenExpr *S)
Definition BuildTree.cpp:1104
bool WalkUpFromBreakStmt(BreakStmt *S)
Definition BuildTree.cpp:1486
bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S)
Definition BuildTree.cpp:1516
bool WalkUpFromFloatingLiteral(FloatingLiteral *S)
Definition BuildTree.cpp:1127
bool WalkUpFromCaseStmt(CaseStmt *S)
Definition BuildTree.cpp:1429
bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S)
Definition BuildTree.cpp:1524
syntax::ParameterDeclarationList * buildParameterDeclarationList(ArrayRef< ParmVarDecl * > Params)
Definition BuildTree.cpp:1350
bool WalkUpFromParenTypeLoc(ParenTypeLoc L)
Definition BuildTree.cpp:1331
bool WalkUpFromBinaryOperator(BinaryOperator *S)
Definition BuildTree.cpp:1172
bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S)
Definition BuildTree.cpp:1555
bool TraverseParenTypeLoc(ParenTypeLoc L, bool TraverseQualifier)
Definition BuildTree.cpp:1324
bool WalkUpFromCXXThisExpr(CXXThisExpr *S)
Definition BuildTree.cpp:1094
bool WalkUpFromDeclRefExpr(DeclRefExpr *S)
Definition BuildTree.cpp:1079
bool WalkUpFromSwitchStmt(SwitchStmt *S)
Definition BuildTree.cpp:1420
bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S)
Definition BuildTree.cpp:1561
bool WalkUpFromDeclStmt(DeclStmt *S)
Definition BuildTree.cpp:1408
bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S)
Definition BuildTree.cpp:1255
bool WalkUpFromWhileStmt(WhileStmt *S)
Definition BuildTree.cpp:1470
bool WalkUpFromNamespaceDecl(NamespaceDecl *S)
Definition BuildTree.cpp:1310
bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S)
Definition BuildTree.cpp:1308
bool WalkUpFromMemberExpr(MemberExpr *S)
Definition BuildTree.cpp:1055
bool WalkUpFromCharacterLiteral(CharacterLiteral *S)
Definition BuildTree.cpp:1120
static Expr * IgnoreImplicit(Expr *E)
Definition BuildTree.cpp:74
bool WalkUpFromDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S)
Definition BuildTree.cpp:1087
bool WalkUpFromNullStmt(NullStmt *S)
Definition BuildTree.cpp:1414
syntax::IdExpression * buildIdExpression(NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKeywordLoc, SourceRange UnqualifiedIdLoc, ASTPtr From)
Definition BuildTree.cpp:1028
bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S)
Definition BuildTree.cpp:1232
bool WalkUpFromEmptyDecl(EmptyDecl *S)
Definition BuildTree.cpp:1510
bool WalkUpFromIntegerLiteral(IntegerLiteral *S)
Definition BuildTree.cpp:1113
static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args)
Definition BuildTree.cpp:154
static bool isImplicitExpr(Expr *E)
Definition BuildTree.cpp:81
bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S)
Definition BuildTree.cpp:1148
bool WalkUpFromUnaryOperator(UnaryOperator *S)
Definition BuildTree.cpp:1155
static Expr * IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E)
Definition BuildTree.cpp:66
bool WalkUpFromCXXConstructExpr(CXXConstructExpr *S)
Definition BuildTree.cpp:1224
static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E)
Definition BuildTree.cpp:160
bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S)
Definition BuildTree.cpp:1502
bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L)
Definition BuildTree.cpp:1398
bool WalkUpFromUsingDecl(UsingDecl *S)
Definition BuildTree.cpp:1543
bool WalkUpFromReturnStmt(ReturnStmt *S)
Definition BuildTree.cpp:1493
bool WalkUpFromContinueStmt(ContinueStmt *S)
Definition BuildTree.cpp:1479
bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S)
Definition BuildTree.cpp:1531
bool WalkUpFromIfStmt(IfStmt *S)
Definition BuildTree.cpp:1448
bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L, bool TraverseQualifier)
Definition BuildTree.cpp:1387
static SourceLocation getQualifiedNameStart(NamedDecl *D)
Get the start of the qualified name.
Definition BuildTree.cpp:246
bool WalkUpFromCallExpr(CallExpr *S)
Definition BuildTree.cpp:1204
bool WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L)
Definition BuildTree.cpp:1377
bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L)
Definition BuildTree.cpp:1340
bool WalkUpFromDefaultStmt(DefaultStmt *S)
Definition BuildTree.cpp:1439
bool WalkUpFromForStmt(ForStmt *S)
Definition BuildTree.cpp:1462
static Expr * IgnoreImplicitConstructorSingleStep(Expr *E)
Definition BuildTree.cpp:47
bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S)
Definition BuildTree.cpp:1141
syntax::CallArguments * buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs)
Builds CallArguments syntax node from arguments that appear in source code, i.e. not default argument...
Definition BuildTree.cpp:1185
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
std::shared_ptr< TokenRole > Role
A token can have a special role that can carry extra information about the token's formatting.
FormatToken * Next
The next token in the unwrapped line.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
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".
SourceLocation getOperatorLoc() const
BreakStmt - This represents a break.
A boolean literal, per ([C++ lex.bool] Boolean literals).
SourceLocation getLocation() const
Represents a call to a C++ constructor.
SourceRange getParenOrBraceRange() const
Expr * getArg(unsigned Arg)
Return the specified argument.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
A default argument (C++ [dcl.fct.default]).
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
SourceLocation getForLoc() const
VarDecl * getLoopVariable()
The null pointer literal (C++11 [lex.nullptr])
SourceLocation getLocation() const
A call to an overloaded operator written using operator syntax.
SourceLocation getOperatorLoc() const
Returns the location of the operator symbol in the expression.
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
SourceRange getSourceRange() const
Represents the this expression in C++.
SourceLocation getLocation() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
llvm::iterator_range< arg_iterator > arg_range
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SourceLocation getRParenLoc() const
CaseStmt - Represent a case statement.
SourceLocation getLocation() const
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
SourceLocation getLBracLoc() const
SourceLocation getRBracLoc() const
ContinueStmt - This represents a continue.
A reference to a declared variable, function, enum, etc.
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getLocation() const
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.
bool isIdentifier() const
Predicate functions for querying what type of name this is.
SourceLocation getNameLoc() const
A qualified reference to a name whose declaration cannot yet be resolved.
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier that qualifies the name, with source location information.
SourceLocation getLocation() const
Retrieve the location of the name within the expression.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
SourceLocation getNameLoc() const
Represents an empty-declaration.
This represents one expression.
SourceLocation getLocation() const
ForStmt - This represents a 'for (init;cond;inc)' stmt.
SourceLocation getForLoc() const
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.
SourceLocation getIfLoc() const
bool hasVarStorage() const
True if this IfStmt has storage for a variable declaration.
SourceLocation getElseLoc() const
DeclStmt * getConditionVariableDeclStmt()
If this IfStmt has a condition variable, return the faux DeclStmt associated with the creation of tha...
const TypeClass * getTypePtr() const
SourceLocation getLocation() const
Retrieve the location of the literal.
Represents a linkage specification.
SourceLocation getKwLoc() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'.
SourceLocation getOperatorLoc() const
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding the member name, if any.
NestedNameSpecifierLoc getQualifierLoc() const
If the member name was qualified, retrieves the nested-name-specifier that precedes the member name,...
bool isImplicitAccess() const
Determine whether the base of this explicit is implicit.
SourceLocation getEndLoc() const LLVM_READONLY
Wrapper for source info for member pointers.
SourceRange getLocalSourceRange() const
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a C++ namespace alias.
Represent a C++ namespace.
A C++ nested-name-specifier augmented with source location information.
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.
SourceLocation getBeginLoc() const
Retrieve the location of the beginning of this nested-name-specifier.
TypeLoc castAsTypeLoc() const
For a nested-name-specifier that refers to a type, retrieve the type with source-location information...
bool hasQualifier() const
Evaluates true when this nested-name-specifier location is non-empty.
SourceRange getLocalSourceRange() const
Retrieve the source range covering just the last part of this nested-name-specifier,...
@ Type
A type, stored as a Type*.
NullStmt - This is the null statement ";": C99 6.8.3p3.
ParenExpr - This represents a parenthesized expression, e.g.
SourceLocation getLParen() const
Get the location of the left parentheses '('.
const Expr * getSubExpr() const
SourceLocation getRParen() const
Get the location of the right parentheses ')'.
SourceLocation getRParenLoc() const
SourceLocation getLParenLoc() const
TypeLoc getInnerLoc() const
TypeLoc getPointeeLoc() const
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 TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier=true)
Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...
bool WalkUpFromStmt(Stmt *S)
bool shouldTraversePostOrder() const
Return whether this visitor should traverse post-order.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
SourceLocation getReturnLoc() const
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.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Represents a C++11 static_assert declaration.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
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.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getKeywordLoc() const
SwitchStmt - This represents a 'switch' stmt.
SourceLocation getSwitchLoc() const
SourceLocation getNameLoc() const
NamedDecl * getTemplatedDecl() const
Get the underlying, templated declaration.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
SourceLocation getTemplateLoc() const
Represents the declaration of a typedef-name via a C++11 alias-declaration.
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.
SourceRange getLocalSourceRange() const
Get the local source range.
TypeLocClass getTypeLocClass() const
SourceLocation getEndLoc() const
Get the end source location.
Wrapper for source info for typedefs.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
static bool isPostfix(Opcode Op)
isPostfix - Return true if this is a postfix operation, like x++.
SourceLocation getOperatorLoc() const
getOperatorLoc - Return the location of the operator.
Expr * getSubExpr() const
Wrapper for source info for unresolved typename using decls.
Represents a dependent using declaration which was marked with typename.
Represents a dependent using declaration which was not marked with typename.
LiteralOperatorKind getLiteralOperatorKind() const
Returns the kind of literal operator invocation which this expression represents.
SourceLocation getBeginLoc() const
@ 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.
Wrapper for source info for types used via transparent aliases.
WhileStmt - This represents a 'while' stmt.
SourceLocation getWhileLoc() const
A memory arena for syntax trees.
llvm::BumpPtrAllocator & getAllocator()
Array size specified inside a declarator.
Models arguments of a function call.
A semicolon in the top-level context. Does not declare anything.
The no-op statement, i.e. ';'.
Expression in a statement position, e.g.
for (; ; )
if (cond) else FIXME: add condition that models 'expression or vari...
extern declaration extern { }
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 ( : )
static_assert(, ) static_assert()
A TokenBuffer-powered token manager.
SourceManager & sourceManager()
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.
A token coming directly from a file or from a macro invocation.
tok::TokenKind kind() const
A node that has children and represents a syntactic language construct.
Models an unqualified-id.
using :: using typename ::
uint32_t Literal
Literals are represented as positive integers.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
NodeRole
A relation between a parent and child node, e.g.
@ ListElement
List API roles.
@ LiteralToken
A token that represents a literal, e.g. 'nullptr', '1', 'true', etc.
@ CloseParen
A closing parenthesis in argument lists and blocks, e.g. '}', ')', etc.
@ IntroducerKeyword
A keywords that introduces some grammar construct, e.g. 'if', 'try', etc.
@ BodyStatement
An inner statement for those that have only a single child of kind statement, e.g.
@ OpenParen
An opening parenthesis in argument lists and blocks, e.g. '{', '(', etc.
syntax::TranslationUnit * buildSyntaxTree(Arena &A, TokenBufferTokenManager &TBTM, ASTContext &Context)
Build a syntax tree for the main file.
Definition BuildTree.cpp:1737
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
bool isa(CodeGen::Address addr)
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.
const FunctionProtoType * T
Expr * IgnoreImplicitSingleStep(Expr *E)
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
U cast(CodeGen::Address addr)