122989816SDimitry Andric //===- BuildTree.cpp ------------------------------------------*- C++ -*-=====//
222989816SDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
622989816SDimitry Andric //
722989816SDimitry Andric //===----------------------------------------------------------------------===//
822989816SDimitry Andric #include "clang/Tooling/Syntax/BuildTree.h"
9cfca06d7SDimitry Andric #include "clang/AST/ASTFwd.h"
10706b4fc4SDimitry Andric #include "clang/AST/Decl.h"
11706b4fc4SDimitry Andric #include "clang/AST/DeclBase.h"
12cfca06d7SDimitry Andric #include "clang/AST/DeclCXX.h"
13cfca06d7SDimitry Andric #include "clang/AST/DeclarationName.h"
14cfca06d7SDimitry Andric #include "clang/AST/Expr.h"
15cfca06d7SDimitry Andric #include "clang/AST/ExprCXX.h"
16b60736ecSDimitry Andric #include "clang/AST/IgnoreExpr.h"
17b60736ecSDimitry Andric #include "clang/AST/OperationKinds.h"
1822989816SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
1922989816SDimitry Andric #include "clang/AST/Stmt.h"
20cfca06d7SDimitry Andric #include "clang/AST/TypeLoc.h"
21cfca06d7SDimitry Andric #include "clang/AST/TypeLocVisitor.h"
2222989816SDimitry Andric #include "clang/Basic/LLVM.h"
2322989816SDimitry Andric #include "clang/Basic/SourceLocation.h"
2422989816SDimitry Andric #include "clang/Basic/SourceManager.h"
25cfca06d7SDimitry Andric #include "clang/Basic/Specifiers.h"
2622989816SDimitry Andric #include "clang/Basic/TokenKinds.h"
2722989816SDimitry Andric #include "clang/Lex/Lexer.h"
28cfca06d7SDimitry Andric #include "clang/Lex/LiteralSupport.h"
2922989816SDimitry Andric #include "clang/Tooling/Syntax/Nodes.h"
304b4fe385SDimitry Andric #include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
3122989816SDimitry Andric #include "clang/Tooling/Syntax/Tokens.h"
3222989816SDimitry Andric #include "clang/Tooling/Syntax/Tree.h"
3322989816SDimitry Andric #include "llvm/ADT/ArrayRef.h"
34cfca06d7SDimitry Andric #include "llvm/ADT/DenseMap.h"
35cfca06d7SDimitry Andric #include "llvm/ADT/PointerUnion.h"
3622989816SDimitry Andric #include "llvm/ADT/STLExtras.h"
37cfca06d7SDimitry Andric #include "llvm/ADT/ScopeExit.h"
3822989816SDimitry Andric #include "llvm/ADT/SmallVector.h"
3922989816SDimitry Andric #include "llvm/Support/Allocator.h"
4022989816SDimitry Andric #include "llvm/Support/Casting.h"
41706b4fc4SDimitry Andric #include "llvm/Support/Compiler.h"
4222989816SDimitry Andric #include "llvm/Support/FormatVariadic.h"
43706b4fc4SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
4422989816SDimitry Andric #include "llvm/Support/raw_ostream.h"
45cfca06d7SDimitry Andric #include <cstddef>
4622989816SDimitry Andric #include <map>
4722989816SDimitry Andric
4822989816SDimitry Andric using namespace clang;
4922989816SDimitry Andric
50b60736ecSDimitry Andric // Ignores the implicit `CXXConstructExpr` for copy/move constructor calls
51b60736ecSDimitry Andric // generated by the compiler, as well as in implicit conversions like the one
52b60736ecSDimitry Andric // wrapping `1` in `X x = 1;`.
IgnoreImplicitConstructorSingleStep(Expr * E)53b60736ecSDimitry Andric static Expr *IgnoreImplicitConstructorSingleStep(Expr *E) {
54b60736ecSDimitry Andric if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
55b60736ecSDimitry Andric auto NumArgs = C->getNumArgs();
56b60736ecSDimitry Andric if (NumArgs == 1 || (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
57b60736ecSDimitry Andric Expr *A = C->getArg(0);
58b60736ecSDimitry Andric if (C->getParenOrBraceRange().isInvalid())
59b60736ecSDimitry Andric return A;
60b60736ecSDimitry Andric }
61b60736ecSDimitry Andric }
62b60736ecSDimitry Andric return E;
63b60736ecSDimitry Andric }
64b60736ecSDimitry Andric
65b60736ecSDimitry Andric // In:
66b60736ecSDimitry Andric // struct X {
67b60736ecSDimitry Andric // X(int)
68b60736ecSDimitry Andric // };
69b60736ecSDimitry Andric // X x = X(1);
70b60736ecSDimitry Andric // Ignores the implicit `CXXFunctionalCastExpr` that wraps
71b60736ecSDimitry Andric // `CXXConstructExpr X(1)`.
IgnoreCXXFunctionalCastExprWrappingConstructor(Expr * E)72b60736ecSDimitry Andric static Expr *IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E) {
73b60736ecSDimitry Andric if (auto *F = dyn_cast<CXXFunctionalCastExpr>(E)) {
74b60736ecSDimitry Andric if (F->getCastKind() == CK_ConstructorConversion)
75b60736ecSDimitry Andric return F->getSubExpr();
76b60736ecSDimitry Andric }
77b60736ecSDimitry Andric return E;
78b60736ecSDimitry Andric }
79b60736ecSDimitry Andric
IgnoreImplicit(Expr * E)80b60736ecSDimitry Andric static Expr *IgnoreImplicit(Expr *E) {
81b60736ecSDimitry Andric return IgnoreExprNodes(E, IgnoreImplicitSingleStep,
82b60736ecSDimitry Andric IgnoreImplicitConstructorSingleStep,
83b60736ecSDimitry Andric IgnoreCXXFunctionalCastExprWrappingConstructor);
84b60736ecSDimitry Andric }
85b60736ecSDimitry Andric
86706b4fc4SDimitry Andric LLVM_ATTRIBUTE_UNUSED
isImplicitExpr(Expr * E)87b60736ecSDimitry Andric static bool isImplicitExpr(Expr *E) { return IgnoreImplicit(E) != E; }
88706b4fc4SDimitry Andric
89cfca06d7SDimitry Andric namespace {
90cfca06d7SDimitry Andric /// Get start location of the Declarator from the TypeLoc.
91cfca06d7SDimitry Andric /// E.g.:
92cfca06d7SDimitry Andric /// loc of `(` in `int (a)`
93cfca06d7SDimitry Andric /// loc of `*` in `int *(a)`
94cfca06d7SDimitry Andric /// loc of the first `(` in `int (*a)(int)`
95cfca06d7SDimitry Andric /// loc of the `*` in `int *(a)(int)`
96cfca06d7SDimitry Andric /// loc of the first `*` in `const int *const *volatile a;`
97cfca06d7SDimitry Andric ///
98cfca06d7SDimitry Andric /// It is non-trivial to get the start location because TypeLocs are stored
99cfca06d7SDimitry Andric /// inside out. In the example above `*volatile` is the TypeLoc returned
100cfca06d7SDimitry Andric /// by `Decl.getTypeSourceInfo()`, and `*const` is what `.getPointeeLoc()`
101cfca06d7SDimitry Andric /// returns.
102cfca06d7SDimitry Andric struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> {
VisitParenTypeLoc__anon99e135900111::GetStartLoc103cfca06d7SDimitry Andric SourceLocation VisitParenTypeLoc(ParenTypeLoc T) {
104cfca06d7SDimitry Andric auto L = Visit(T.getInnerLoc());
105cfca06d7SDimitry Andric if (L.isValid())
106cfca06d7SDimitry Andric return L;
107cfca06d7SDimitry Andric return T.getLParenLoc();
108cfca06d7SDimitry Andric }
109cfca06d7SDimitry Andric
110cfca06d7SDimitry Andric // Types spelled in the prefix part of the declarator.
VisitPointerTypeLoc__anon99e135900111::GetStartLoc111cfca06d7SDimitry Andric SourceLocation VisitPointerTypeLoc(PointerTypeLoc T) {
112cfca06d7SDimitry Andric return HandlePointer(T);
113cfca06d7SDimitry Andric }
114cfca06d7SDimitry Andric
VisitMemberPointerTypeLoc__anon99e135900111::GetStartLoc115cfca06d7SDimitry Andric SourceLocation VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
116cfca06d7SDimitry Andric return HandlePointer(T);
117cfca06d7SDimitry Andric }
118cfca06d7SDimitry Andric
VisitBlockPointerTypeLoc__anon99e135900111::GetStartLoc119cfca06d7SDimitry Andric SourceLocation VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
120cfca06d7SDimitry Andric return HandlePointer(T);
121cfca06d7SDimitry Andric }
122cfca06d7SDimitry Andric
VisitReferenceTypeLoc__anon99e135900111::GetStartLoc123cfca06d7SDimitry Andric SourceLocation VisitReferenceTypeLoc(ReferenceTypeLoc T) {
124cfca06d7SDimitry Andric return HandlePointer(T);
125cfca06d7SDimitry Andric }
126cfca06d7SDimitry Andric
VisitObjCObjectPointerTypeLoc__anon99e135900111::GetStartLoc127cfca06d7SDimitry Andric SourceLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc T) {
128cfca06d7SDimitry Andric return HandlePointer(T);
129cfca06d7SDimitry Andric }
130cfca06d7SDimitry Andric
131cfca06d7SDimitry Andric // All other cases are not important, as they are either part of declaration
132cfca06d7SDimitry Andric // specifiers (e.g. inheritors of TypeSpecTypeLoc) or introduce modifiers on
133cfca06d7SDimitry Andric // existing declarators (e.g. QualifiedTypeLoc). They cannot start the
134cfca06d7SDimitry Andric // declarator themselves, but their underlying type can.
VisitTypeLoc__anon99e135900111::GetStartLoc135cfca06d7SDimitry Andric SourceLocation VisitTypeLoc(TypeLoc T) {
136cfca06d7SDimitry Andric auto N = T.getNextTypeLoc();
137cfca06d7SDimitry Andric if (!N)
138cfca06d7SDimitry Andric return SourceLocation();
139cfca06d7SDimitry Andric return Visit(N);
140cfca06d7SDimitry Andric }
141cfca06d7SDimitry Andric
VisitFunctionProtoTypeLoc__anon99e135900111::GetStartLoc142cfca06d7SDimitry Andric SourceLocation VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc T) {
143cfca06d7SDimitry Andric if (T.getTypePtr()->hasTrailingReturn())
144cfca06d7SDimitry Andric return SourceLocation(); // avoid recursing into the suffix of declarator.
145cfca06d7SDimitry Andric return VisitTypeLoc(T);
146cfca06d7SDimitry Andric }
147cfca06d7SDimitry Andric
148cfca06d7SDimitry Andric private:
HandlePointer__anon99e135900111::GetStartLoc149cfca06d7SDimitry Andric template <class PtrLoc> SourceLocation HandlePointer(PtrLoc T) {
150cfca06d7SDimitry Andric auto L = Visit(T.getPointeeLoc());
151cfca06d7SDimitry Andric if (L.isValid())
152cfca06d7SDimitry Andric return L;
153cfca06d7SDimitry Andric return T.getLocalSourceRange().getBegin();
154cfca06d7SDimitry Andric }
155cfca06d7SDimitry Andric };
156cfca06d7SDimitry Andric } // namespace
157cfca06d7SDimitry Andric
dropDefaultArgs(CallExpr::arg_range Args)158b60736ecSDimitry Andric static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) {
159c0981da4SDimitry Andric auto FirstDefaultArg =
160c0981da4SDimitry Andric llvm::find_if(Args, [](auto It) { return isa<CXXDefaultArgExpr>(It); });
161b60736ecSDimitry Andric return llvm::make_range(Args.begin(), FirstDefaultArg);
162b60736ecSDimitry Andric }
163b60736ecSDimitry Andric
getOperatorNodeKind(const CXXOperatorCallExpr & E)164cfca06d7SDimitry Andric static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) {
165cfca06d7SDimitry Andric switch (E.getOperator()) {
166cfca06d7SDimitry Andric // Comparison
167cfca06d7SDimitry Andric case OO_EqualEqual:
168cfca06d7SDimitry Andric case OO_ExclaimEqual:
169cfca06d7SDimitry Andric case OO_Greater:
170cfca06d7SDimitry Andric case OO_GreaterEqual:
171cfca06d7SDimitry Andric case OO_Less:
172cfca06d7SDimitry Andric case OO_LessEqual:
173cfca06d7SDimitry Andric case OO_Spaceship:
174cfca06d7SDimitry Andric // Assignment
175cfca06d7SDimitry Andric case OO_Equal:
176cfca06d7SDimitry Andric case OO_SlashEqual:
177cfca06d7SDimitry Andric case OO_PercentEqual:
178cfca06d7SDimitry Andric case OO_CaretEqual:
179cfca06d7SDimitry Andric case OO_PipeEqual:
180cfca06d7SDimitry Andric case OO_LessLessEqual:
181cfca06d7SDimitry Andric case OO_GreaterGreaterEqual:
182cfca06d7SDimitry Andric case OO_PlusEqual:
183cfca06d7SDimitry Andric case OO_MinusEqual:
184cfca06d7SDimitry Andric case OO_StarEqual:
185cfca06d7SDimitry Andric case OO_AmpEqual:
186cfca06d7SDimitry Andric // Binary computation
187cfca06d7SDimitry Andric case OO_Slash:
188cfca06d7SDimitry Andric case OO_Percent:
189cfca06d7SDimitry Andric case OO_Caret:
190cfca06d7SDimitry Andric case OO_Pipe:
191cfca06d7SDimitry Andric case OO_LessLess:
192cfca06d7SDimitry Andric case OO_GreaterGreater:
193cfca06d7SDimitry Andric case OO_AmpAmp:
194cfca06d7SDimitry Andric case OO_PipePipe:
195cfca06d7SDimitry Andric case OO_ArrowStar:
196cfca06d7SDimitry Andric case OO_Comma:
197cfca06d7SDimitry Andric return syntax::NodeKind::BinaryOperatorExpression;
198cfca06d7SDimitry Andric case OO_Tilde:
199cfca06d7SDimitry Andric case OO_Exclaim:
200cfca06d7SDimitry Andric return syntax::NodeKind::PrefixUnaryOperatorExpression;
201cfca06d7SDimitry Andric // Prefix/Postfix increment/decrement
202cfca06d7SDimitry Andric case OO_PlusPlus:
203cfca06d7SDimitry Andric case OO_MinusMinus:
204cfca06d7SDimitry Andric switch (E.getNumArgs()) {
205cfca06d7SDimitry Andric case 1:
206cfca06d7SDimitry Andric return syntax::NodeKind::PrefixUnaryOperatorExpression;
207cfca06d7SDimitry Andric case 2:
208cfca06d7SDimitry Andric return syntax::NodeKind::PostfixUnaryOperatorExpression;
209cfca06d7SDimitry Andric default:
210cfca06d7SDimitry Andric llvm_unreachable("Invalid number of arguments for operator");
211cfca06d7SDimitry Andric }
212cfca06d7SDimitry Andric // Operators that can be unary or binary
213cfca06d7SDimitry Andric case OO_Plus:
214cfca06d7SDimitry Andric case OO_Minus:
215cfca06d7SDimitry Andric case OO_Star:
216cfca06d7SDimitry Andric case OO_Amp:
217cfca06d7SDimitry Andric switch (E.getNumArgs()) {
218cfca06d7SDimitry Andric case 1:
219cfca06d7SDimitry Andric return syntax::NodeKind::PrefixUnaryOperatorExpression;
220cfca06d7SDimitry Andric case 2:
221cfca06d7SDimitry Andric return syntax::NodeKind::BinaryOperatorExpression;
222cfca06d7SDimitry Andric default:
223cfca06d7SDimitry Andric llvm_unreachable("Invalid number of arguments for operator");
224cfca06d7SDimitry Andric }
225cfca06d7SDimitry Andric return syntax::NodeKind::BinaryOperatorExpression;
226cfca06d7SDimitry Andric // Not yet supported by SyntaxTree
227cfca06d7SDimitry Andric case OO_New:
228cfca06d7SDimitry Andric case OO_Delete:
229cfca06d7SDimitry Andric case OO_Array_New:
230cfca06d7SDimitry Andric case OO_Array_Delete:
231cfca06d7SDimitry Andric case OO_Coawait:
232cfca06d7SDimitry Andric case OO_Subscript:
233cfca06d7SDimitry Andric case OO_Arrow:
234cfca06d7SDimitry Andric return syntax::NodeKind::UnknownExpression;
235b60736ecSDimitry Andric case OO_Call:
236b60736ecSDimitry Andric return syntax::NodeKind::CallExpression;
237cfca06d7SDimitry Andric case OO_Conditional: // not overloadable
238cfca06d7SDimitry Andric case NUM_OVERLOADED_OPERATORS:
239cfca06d7SDimitry Andric case OO_None:
240cfca06d7SDimitry Andric llvm_unreachable("Not an overloadable operator");
241cfca06d7SDimitry Andric }
242cfca06d7SDimitry Andric llvm_unreachable("Unknown OverloadedOperatorKind enum");
243cfca06d7SDimitry Andric }
244cfca06d7SDimitry Andric
245b60736ecSDimitry Andric /// Get the start of the qualified name. In the examples below it gives the
246b60736ecSDimitry Andric /// location of the `^`:
247b60736ecSDimitry Andric /// `int ^a;`
248b60736ecSDimitry Andric /// `int *^a;`
249b60736ecSDimitry Andric /// `int ^a::S::f(){}`
getQualifiedNameStart(NamedDecl * D)250b60736ecSDimitry Andric static SourceLocation getQualifiedNameStart(NamedDecl *D) {
251b60736ecSDimitry Andric assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) &&
252b60736ecSDimitry Andric "only DeclaratorDecl and TypedefNameDecl are supported.");
253b60736ecSDimitry Andric
254b60736ecSDimitry Andric auto DN = D->getDeclName();
255b60736ecSDimitry Andric bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo();
256b60736ecSDimitry Andric if (IsAnonymous)
257b60736ecSDimitry Andric return SourceLocation();
258b60736ecSDimitry Andric
259b60736ecSDimitry Andric if (const auto *DD = dyn_cast<DeclaratorDecl>(D)) {
260b60736ecSDimitry Andric if (DD->getQualifierLoc()) {
261b60736ecSDimitry Andric return DD->getQualifierLoc().getBeginLoc();
262b60736ecSDimitry Andric }
263b60736ecSDimitry Andric }
264b60736ecSDimitry Andric
265b60736ecSDimitry Andric return D->getLocation();
266b60736ecSDimitry Andric }
267b60736ecSDimitry Andric
268b60736ecSDimitry Andric /// Gets the range of the initializer inside an init-declarator C++ [dcl.decl].
269b60736ecSDimitry Andric /// `int a;` -> range of ``,
270b60736ecSDimitry Andric /// `int *a = nullptr` -> range of `= nullptr`.
271b60736ecSDimitry Andric /// `int a{}` -> range of `{}`.
272b60736ecSDimitry Andric /// `int a()` -> range of `()`.
getInitializerRange(Decl * D)273b60736ecSDimitry Andric static SourceRange getInitializerRange(Decl *D) {
274b60736ecSDimitry Andric if (auto *V = dyn_cast<VarDecl>(D)) {
275b60736ecSDimitry Andric auto *I = V->getInit();
276b60736ecSDimitry Andric // Initializers in range-based-for are not part of the declarator
277b60736ecSDimitry Andric if (I && !V->isCXXForRangeDecl())
278b60736ecSDimitry Andric return I->getSourceRange();
279b60736ecSDimitry Andric }
280b60736ecSDimitry Andric
281b60736ecSDimitry Andric return SourceRange();
282b60736ecSDimitry Andric }
283b60736ecSDimitry Andric
284cfca06d7SDimitry Andric /// Gets the range of declarator as defined by the C++ grammar. E.g.
285cfca06d7SDimitry Andric /// `int a;` -> range of `a`,
286cfca06d7SDimitry Andric /// `int *a;` -> range of `*a`,
287cfca06d7SDimitry Andric /// `int a[10];` -> range of `a[10]`,
288cfca06d7SDimitry Andric /// `int a[1][2][3];` -> range of `a[1][2][3]`,
289cfca06d7SDimitry Andric /// `int *a = nullptr` -> range of `*a = nullptr`.
290b60736ecSDimitry Andric /// `int S::f(){}` -> range of `S::f()`.
291b60736ecSDimitry Andric /// FIXME: \p Name must be a source range.
getDeclaratorRange(const SourceManager & SM,TypeLoc T,SourceLocation Name,SourceRange Initializer)292cfca06d7SDimitry Andric static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T,
293cfca06d7SDimitry Andric SourceLocation Name,
294cfca06d7SDimitry Andric SourceRange Initializer) {
295cfca06d7SDimitry Andric SourceLocation Start = GetStartLoc().Visit(T);
296b60736ecSDimitry Andric SourceLocation End = T.getEndLoc();
297cfca06d7SDimitry Andric if (Name.isValid()) {
298cfca06d7SDimitry Andric if (Start.isInvalid())
299cfca06d7SDimitry Andric Start = Name;
300344a3780SDimitry Andric // End of TypeLoc could be invalid if the type is invalid, fallback to the
301344a3780SDimitry Andric // NameLoc.
302344a3780SDimitry Andric if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name))
303cfca06d7SDimitry Andric End = Name;
304cfca06d7SDimitry Andric }
305cfca06d7SDimitry Andric if (Initializer.isValid()) {
306cfca06d7SDimitry Andric auto InitializerEnd = Initializer.getEnd();
307cfca06d7SDimitry Andric assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) ||
308cfca06d7SDimitry Andric End == InitializerEnd);
309cfca06d7SDimitry Andric End = InitializerEnd;
310cfca06d7SDimitry Andric }
311cfca06d7SDimitry Andric return SourceRange(Start, End);
312cfca06d7SDimitry Andric }
313cfca06d7SDimitry Andric
314cfca06d7SDimitry Andric namespace {
315cfca06d7SDimitry Andric /// All AST hierarchy roots that can be represented as pointers.
316cfca06d7SDimitry Andric using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;
317cfca06d7SDimitry Andric /// Maintains a mapping from AST to syntax tree nodes. This class will get more
318cfca06d7SDimitry Andric /// complicated as we support more kinds of AST nodes, e.g. TypeLocs.
319cfca06d7SDimitry Andric /// FIXME: expose this as public API.
320cfca06d7SDimitry Andric class ASTToSyntaxMapping {
321cfca06d7SDimitry Andric public:
add(ASTPtr From,syntax::Tree * To)322cfca06d7SDimitry Andric void add(ASTPtr From, syntax::Tree *To) {
323cfca06d7SDimitry Andric assert(To != nullptr);
324cfca06d7SDimitry Andric assert(!From.isNull());
325cfca06d7SDimitry Andric
326cfca06d7SDimitry Andric bool Added = Nodes.insert({From, To}).second;
327cfca06d7SDimitry Andric (void)Added;
328cfca06d7SDimitry Andric assert(Added && "mapping added twice");
329cfca06d7SDimitry Andric }
330cfca06d7SDimitry Andric
add(NestedNameSpecifierLoc From,syntax::Tree * To)331b60736ecSDimitry Andric void add(NestedNameSpecifierLoc From, syntax::Tree *To) {
332b60736ecSDimitry Andric assert(To != nullptr);
333b60736ecSDimitry Andric assert(From.hasQualifier());
334b60736ecSDimitry Andric
335b60736ecSDimitry Andric bool Added = NNSNodes.insert({From, To}).second;
336b60736ecSDimitry Andric (void)Added;
337b60736ecSDimitry Andric assert(Added && "mapping added twice");
338b60736ecSDimitry Andric }
339b60736ecSDimitry Andric
find(ASTPtr P) const340cfca06d7SDimitry Andric syntax::Tree *find(ASTPtr P) const { return Nodes.lookup(P); }
341cfca06d7SDimitry Andric
find(NestedNameSpecifierLoc P) const342b60736ecSDimitry Andric syntax::Tree *find(NestedNameSpecifierLoc P) const {
343b60736ecSDimitry Andric return NNSNodes.lookup(P);
344b60736ecSDimitry Andric }
345b60736ecSDimitry Andric
346cfca06d7SDimitry Andric private:
347cfca06d7SDimitry Andric llvm::DenseMap<ASTPtr, syntax::Tree *> Nodes;
348b60736ecSDimitry Andric llvm::DenseMap<NestedNameSpecifierLoc, syntax::Tree *> NNSNodes;
349cfca06d7SDimitry Andric };
350cfca06d7SDimitry Andric } // namespace
351cfca06d7SDimitry Andric
35222989816SDimitry Andric /// A helper class for constructing the syntax tree while traversing a clang
35322989816SDimitry Andric /// AST.
35422989816SDimitry Andric ///
35522989816SDimitry Andric /// At each point of the traversal we maintain a list of pending nodes.
35622989816SDimitry Andric /// Initially all tokens are added as pending nodes. When processing a clang AST
35722989816SDimitry Andric /// node, the clients need to:
35822989816SDimitry Andric /// - create a corresponding syntax node,
35922989816SDimitry Andric /// - assign roles to all pending child nodes with 'markChild' and
36022989816SDimitry Andric /// 'markChildToken',
36122989816SDimitry Andric /// - replace the child nodes with the new syntax node in the pending list
36222989816SDimitry Andric /// with 'foldNode'.
36322989816SDimitry Andric ///
36422989816SDimitry Andric /// Note that all children are expected to be processed when building a node.
36522989816SDimitry Andric ///
36622989816SDimitry Andric /// Call finalize() to finish building the tree and consume the root node.
36722989816SDimitry Andric class syntax::TreeBuilder {
36822989816SDimitry Andric public:
TreeBuilder(syntax::Arena & Arena,TokenBufferTokenManager & TBTM)3694b4fe385SDimitry Andric TreeBuilder(syntax::Arena &Arena, TokenBufferTokenManager& TBTM)
3704b4fe385SDimitry Andric : Arena(Arena),
3714b4fe385SDimitry Andric TBTM(TBTM),
3724b4fe385SDimitry Andric Pending(Arena, TBTM.tokenBuffer()) {
3734b4fe385SDimitry Andric for (const auto &T : TBTM.tokenBuffer().expandedTokens())
374b60736ecSDimitry Andric LocationToToken.insert({T.location(), &T});
375706b4fc4SDimitry Andric }
37622989816SDimitry Andric
allocator()377b60736ecSDimitry Andric llvm::BumpPtrAllocator &allocator() { return Arena.getAllocator(); }
sourceManager() const378b60736ecSDimitry Andric const SourceManager &sourceManager() const {
3794b4fe385SDimitry Andric return TBTM.sourceManager();
380b60736ecSDimitry Andric }
38122989816SDimitry Andric
38222989816SDimitry Andric /// Populate children for \p New node, assuming it covers tokens from \p
38322989816SDimitry Andric /// Range.
foldNode(ArrayRef<syntax::Token> Range,syntax::Tree * New,ASTPtr From)384b60736ecSDimitry Andric void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, ASTPtr From) {
385cfca06d7SDimitry Andric assert(New);
3864b4fe385SDimitry Andric Pending.foldChildren(TBTM.tokenBuffer(), Range, New);
387cfca06d7SDimitry Andric if (From)
388cfca06d7SDimitry Andric Mapping.add(From, New);
389cfca06d7SDimitry Andric }
390b60736ecSDimitry Andric
foldNode(ArrayRef<syntax::Token> Range,syntax::Tree * New,TypeLoc L)391b60736ecSDimitry Andric void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, TypeLoc L) {
392cfca06d7SDimitry Andric // FIXME: add mapping for TypeLocs
393cfca06d7SDimitry Andric foldNode(Range, New, nullptr);
394cfca06d7SDimitry Andric }
395706b4fc4SDimitry Andric
foldNode(llvm::ArrayRef<syntax::Token> Range,syntax::Tree * New,NestedNameSpecifierLoc From)396b60736ecSDimitry Andric void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
397b60736ecSDimitry Andric NestedNameSpecifierLoc From) {
398b60736ecSDimitry Andric assert(New);
3994b4fe385SDimitry Andric Pending.foldChildren(TBTM.tokenBuffer(), Range, New);
400b60736ecSDimitry Andric if (From)
401b60736ecSDimitry Andric Mapping.add(From, New);
402b60736ecSDimitry Andric }
403b60736ecSDimitry Andric
404b60736ecSDimitry Andric /// Populate children for \p New list, assuming it covers tokens from a
405b60736ecSDimitry Andric /// subrange of \p SuperRange.
foldList(ArrayRef<syntax::Token> SuperRange,syntax::List * New,ASTPtr From)406b60736ecSDimitry Andric void foldList(ArrayRef<syntax::Token> SuperRange, syntax::List *New,
407b60736ecSDimitry Andric ASTPtr From) {
408b60736ecSDimitry Andric assert(New);
409b60736ecSDimitry Andric auto ListRange = Pending.shrinkToFitList(SuperRange);
4104b4fe385SDimitry Andric Pending.foldChildren(TBTM.tokenBuffer(), ListRange, New);
411b60736ecSDimitry Andric if (From)
412b60736ecSDimitry Andric Mapping.add(From, New);
413b60736ecSDimitry Andric }
414b60736ecSDimitry Andric
415706b4fc4SDimitry Andric /// Notifies that we should not consume trailing semicolon when computing
416706b4fc4SDimitry Andric /// token range of \p D.
417cfca06d7SDimitry Andric void noticeDeclWithoutSemicolon(Decl *D);
418706b4fc4SDimitry Andric
419706b4fc4SDimitry Andric /// Mark the \p Child node with a corresponding \p Role. All marked children
420706b4fc4SDimitry Andric /// should be consumed by foldNode.
421cfca06d7SDimitry Andric /// When called on expressions (clang::Expr is derived from clang::Stmt),
422706b4fc4SDimitry Andric /// wraps expressions into expression statement.
423706b4fc4SDimitry Andric void markStmtChild(Stmt *Child, NodeRole Role);
424706b4fc4SDimitry Andric /// Should be called for expressions in non-statement position to avoid
425706b4fc4SDimitry Andric /// wrapping into expression statement.
426706b4fc4SDimitry Andric void markExprChild(Expr *Child, NodeRole Role);
42722989816SDimitry Andric /// Set role for a token starting at \p Loc.
428706b4fc4SDimitry Andric void markChildToken(SourceLocation Loc, NodeRole R);
429cfca06d7SDimitry Andric /// Set role for \p T.
430cfca06d7SDimitry Andric void markChildToken(const syntax::Token *T, NodeRole R);
431cfca06d7SDimitry Andric
432cfca06d7SDimitry Andric /// Set role for \p N.
433cfca06d7SDimitry Andric void markChild(syntax::Node *N, NodeRole R);
434cfca06d7SDimitry Andric /// Set role for the syntax node matching \p N.
435cfca06d7SDimitry Andric void markChild(ASTPtr N, NodeRole R);
436b60736ecSDimitry Andric /// Set role for the syntax node matching \p N.
437b60736ecSDimitry Andric void markChild(NestedNameSpecifierLoc N, NodeRole R);
43822989816SDimitry Andric
43922989816SDimitry Andric /// Finish building the tree and consume the root node.
finalize()44022989816SDimitry Andric syntax::TranslationUnit *finalize() && {
4414b4fe385SDimitry Andric auto Tokens = TBTM.tokenBuffer().expandedTokens();
442519fc96cSDimitry Andric assert(!Tokens.empty());
443519fc96cSDimitry Andric assert(Tokens.back().kind() == tok::eof);
444519fc96cSDimitry Andric
44522989816SDimitry Andric // Build the root of the tree, consuming all the children.
4464b4fe385SDimitry Andric Pending.foldChildren(TBTM.tokenBuffer(), Tokens.drop_back(),
447b60736ecSDimitry Andric new (Arena.getAllocator()) syntax::TranslationUnit);
44822989816SDimitry Andric
449706b4fc4SDimitry Andric auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).finalize());
450706b4fc4SDimitry Andric TU->assertInvariantsRecursive();
451706b4fc4SDimitry Andric return TU;
45222989816SDimitry Andric }
45322989816SDimitry Andric
454cfca06d7SDimitry Andric /// Finds a token starting at \p L. The token must exist if \p L is valid.
455cfca06d7SDimitry Andric const syntax::Token *findToken(SourceLocation L) const;
456cfca06d7SDimitry Andric
457cfca06d7SDimitry Andric /// Finds the syntax tokens corresponding to the \p SourceRange.
getRange(SourceRange Range) const458b60736ecSDimitry Andric ArrayRef<syntax::Token> getRange(SourceRange Range) const {
459cfca06d7SDimitry Andric assert(Range.isValid());
460cfca06d7SDimitry Andric return getRange(Range.getBegin(), Range.getEnd());
461cfca06d7SDimitry Andric }
462cfca06d7SDimitry Andric
463cfca06d7SDimitry Andric /// Finds the syntax tokens corresponding to the passed source locations.
46422989816SDimitry Andric /// \p First is the start position of the first token and \p Last is the start
46522989816SDimitry Andric /// position of the last token.
getRange(SourceLocation First,SourceLocation Last) const466b60736ecSDimitry Andric ArrayRef<syntax::Token> getRange(SourceLocation First,
46722989816SDimitry Andric SourceLocation Last) const {
46822989816SDimitry Andric assert(First.isValid());
46922989816SDimitry Andric assert(Last.isValid());
47022989816SDimitry Andric assert(First == Last ||
4714b4fe385SDimitry Andric TBTM.sourceManager().isBeforeInTranslationUnit(First, Last));
472e3b55780SDimitry Andric return llvm::ArrayRef(findToken(First), std::next(findToken(Last)));
47322989816SDimitry Andric }
474cfca06d7SDimitry Andric
475b60736ecSDimitry Andric ArrayRef<syntax::Token>
getTemplateRange(const ClassTemplateSpecializationDecl * D) const476cfca06d7SDimitry Andric getTemplateRange(const ClassTemplateSpecializationDecl *D) const {
477cfca06d7SDimitry Andric auto Tokens = getRange(D->getSourceRange());
478cfca06d7SDimitry Andric return maybeAppendSemicolon(Tokens, D);
47922989816SDimitry Andric }
480cfca06d7SDimitry Andric
481cfca06d7SDimitry Andric /// Returns true if \p D is the last declarator in a chain and is thus
482cfca06d7SDimitry Andric /// reponsible for creating SimpleDeclaration for the whole chain.
isResponsibleForCreatingDeclaration(const Decl * D) const483b60736ecSDimitry Andric bool isResponsibleForCreatingDeclaration(const Decl *D) const {
484b60736ecSDimitry Andric assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) &&
485cfca06d7SDimitry Andric "only DeclaratorDecl and TypedefNameDecl are supported.");
486cfca06d7SDimitry Andric
487cfca06d7SDimitry Andric const Decl *Next = D->getNextDeclInContext();
488cfca06d7SDimitry Andric
489cfca06d7SDimitry Andric // There's no next sibling, this one is responsible.
490cfca06d7SDimitry Andric if (Next == nullptr) {
491cfca06d7SDimitry Andric return true;
492cfca06d7SDimitry Andric }
493cfca06d7SDimitry Andric
494cfca06d7SDimitry Andric // Next sibling is not the same type, this one is responsible.
495b60736ecSDimitry Andric if (D->getKind() != Next->getKind()) {
496cfca06d7SDimitry Andric return true;
497cfca06d7SDimitry Andric }
498cfca06d7SDimitry Andric // Next sibling doesn't begin at the same loc, it must be a different
499cfca06d7SDimitry Andric // declaration, so this declarator is responsible.
500b60736ecSDimitry Andric if (Next->getBeginLoc() != D->getBeginLoc()) {
501cfca06d7SDimitry Andric return true;
502cfca06d7SDimitry Andric }
503cfca06d7SDimitry Andric
504cfca06d7SDimitry Andric // NextT is a member of the same declaration, and we need the last member to
505cfca06d7SDimitry Andric // create declaration. This one is not responsible.
506cfca06d7SDimitry Andric return false;
507cfca06d7SDimitry Andric }
508cfca06d7SDimitry Andric
getDeclarationRange(Decl * D)509b60736ecSDimitry Andric ArrayRef<syntax::Token> getDeclarationRange(Decl *D) {
510b60736ecSDimitry Andric ArrayRef<syntax::Token> Tokens;
511cfca06d7SDimitry Andric // We want to drop the template parameters for specializations.
512b60736ecSDimitry Andric if (const auto *S = dyn_cast<TagDecl>(D))
513cfca06d7SDimitry Andric Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());
514cfca06d7SDimitry Andric else
515cfca06d7SDimitry Andric Tokens = getRange(D->getSourceRange());
516cfca06d7SDimitry Andric return maybeAppendSemicolon(Tokens, D);
517cfca06d7SDimitry Andric }
518cfca06d7SDimitry Andric
getExprRange(const Expr * E) const519b60736ecSDimitry Andric ArrayRef<syntax::Token> getExprRange(const Expr *E) const {
520cfca06d7SDimitry Andric return getRange(E->getSourceRange());
521706b4fc4SDimitry Andric }
522cfca06d7SDimitry Andric
523706b4fc4SDimitry Andric /// Find the adjusted range for the statement, consuming the trailing
524706b4fc4SDimitry Andric /// semicolon when needed.
getStmtRange(const Stmt * S) const525b60736ecSDimitry Andric ArrayRef<syntax::Token> getStmtRange(const Stmt *S) const {
526cfca06d7SDimitry Andric auto Tokens = getRange(S->getSourceRange());
527706b4fc4SDimitry Andric if (isa<CompoundStmt>(S))
528706b4fc4SDimitry Andric return Tokens;
529706b4fc4SDimitry Andric
530706b4fc4SDimitry Andric // Some statements miss a trailing semicolon, e.g. 'return', 'continue' and
531706b4fc4SDimitry Andric // all statements that end with those. Consume this semicolon here.
532706b4fc4SDimitry Andric if (Tokens.back().kind() == tok::semi)
533706b4fc4SDimitry Andric return Tokens;
534706b4fc4SDimitry Andric return withTrailingSemicolon(Tokens);
53522989816SDimitry Andric }
53622989816SDimitry Andric
53722989816SDimitry Andric private:
maybeAppendSemicolon(ArrayRef<syntax::Token> Tokens,const Decl * D) const538b60736ecSDimitry Andric ArrayRef<syntax::Token> maybeAppendSemicolon(ArrayRef<syntax::Token> Tokens,
539cfca06d7SDimitry Andric const Decl *D) const {
540b60736ecSDimitry Andric if (isa<NamespaceDecl>(D))
541cfca06d7SDimitry Andric return Tokens;
542cfca06d7SDimitry Andric if (DeclsWithoutSemicolons.count(D))
543cfca06d7SDimitry Andric return Tokens;
544cfca06d7SDimitry Andric // FIXME: do not consume trailing semicolon on function definitions.
545cfca06d7SDimitry Andric // Most declarations own a semicolon in syntax trees, but not in clang AST.
546cfca06d7SDimitry Andric return withTrailingSemicolon(Tokens);
547cfca06d7SDimitry Andric }
548cfca06d7SDimitry Andric
549b60736ecSDimitry Andric ArrayRef<syntax::Token>
withTrailingSemicolon(ArrayRef<syntax::Token> Tokens) const550b60736ecSDimitry Andric withTrailingSemicolon(ArrayRef<syntax::Token> Tokens) const {
551706b4fc4SDimitry Andric assert(!Tokens.empty());
552706b4fc4SDimitry Andric assert(Tokens.back().kind() != tok::eof);
553cfca06d7SDimitry Andric // We never consume 'eof', so looking at the next token is ok.
554706b4fc4SDimitry Andric if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi)
555e3b55780SDimitry Andric return llvm::ArrayRef(Tokens.begin(), Tokens.end() + 1);
556706b4fc4SDimitry Andric return Tokens;
557706b4fc4SDimitry Andric }
558706b4fc4SDimitry Andric
setRole(syntax::Node * N,NodeRole R)559cfca06d7SDimitry Andric void setRole(syntax::Node *N, NodeRole R) {
560b60736ecSDimitry Andric assert(N->getRole() == NodeRole::Detached);
561cfca06d7SDimitry Andric N->setRole(R);
562cfca06d7SDimitry Andric }
56322989816SDimitry Andric
56422989816SDimitry Andric /// A collection of trees covering the input tokens.
56522989816SDimitry Andric /// When created, each tree corresponds to a single token in the file.
56622989816SDimitry Andric /// Clients call 'foldChildren' to attach one or more subtrees to a parent
56722989816SDimitry Andric /// node and update the list of trees accordingly.
56822989816SDimitry Andric ///
56922989816SDimitry Andric /// Ensures that added nodes properly nest and cover the whole token stream.
57022989816SDimitry Andric struct Forest {
Forestsyntax::TreeBuilder::Forest5714b4fe385SDimitry Andric Forest(syntax::Arena &A, const syntax::TokenBuffer &TB) {
5724b4fe385SDimitry Andric assert(!TB.expandedTokens().empty());
5734b4fe385SDimitry Andric assert(TB.expandedTokens().back().kind() == tok::eof);
57422989816SDimitry Andric // Create all leaf nodes.
575519fc96cSDimitry Andric // Note that we do not have 'eof' in the tree.
5764b4fe385SDimitry Andric for (const auto &T : TB.expandedTokens().drop_back()) {
5774b4fe385SDimitry Andric auto *L = new (A.getAllocator())
5784b4fe385SDimitry Andric syntax::Leaf(reinterpret_cast<TokenManager::Key>(&T));
579706b4fc4SDimitry Andric L->Original = true;
5804b4fe385SDimitry Andric L->CanModify = TB.spelledForExpanded(T).has_value();
581cfca06d7SDimitry Andric Trees.insert(Trees.end(), {&T, L});
58222989816SDimitry Andric }
583706b4fc4SDimitry Andric }
584706b4fc4SDimitry Andric
assignRolesyntax::TreeBuilder::Forest585b60736ecSDimitry Andric void assignRole(ArrayRef<syntax::Token> Range, syntax::NodeRole Role) {
58622989816SDimitry Andric assert(!Range.empty());
58722989816SDimitry Andric auto It = Trees.lower_bound(Range.begin());
58822989816SDimitry Andric assert(It != Trees.end() && "no node found");
58922989816SDimitry Andric assert(It->first == Range.begin() && "no child with the specified range");
59022989816SDimitry Andric assert((std::next(It) == Trees.end() ||
59122989816SDimitry Andric std::next(It)->first == Range.end()) &&
59222989816SDimitry Andric "no child with the specified range");
593b60736ecSDimitry Andric assert(It->second->getRole() == NodeRole::Detached &&
594cfca06d7SDimitry Andric "re-assigning role for a child");
595cfca06d7SDimitry Andric It->second->setRole(Role);
59622989816SDimitry Andric }
59722989816SDimitry Andric
598b60736ecSDimitry Andric /// Shrink \p Range to a subrange that only contains tokens of a list.
599b60736ecSDimitry Andric /// List elements and delimiters should already have correct roles.
shrinkToFitListsyntax::TreeBuilder::Forest600b60736ecSDimitry Andric ArrayRef<syntax::Token> shrinkToFitList(ArrayRef<syntax::Token> Range) {
601b60736ecSDimitry Andric auto BeginChildren = Trees.lower_bound(Range.begin());
602b60736ecSDimitry Andric assert((BeginChildren == Trees.end() ||
603b60736ecSDimitry Andric BeginChildren->first == Range.begin()) &&
604b60736ecSDimitry Andric "Range crosses boundaries of existing subtrees");
605b60736ecSDimitry Andric
606b60736ecSDimitry Andric auto EndChildren = Trees.lower_bound(Range.end());
607b60736ecSDimitry Andric assert(
608b60736ecSDimitry Andric (EndChildren == Trees.end() || EndChildren->first == Range.end()) &&
609b60736ecSDimitry Andric "Range crosses boundaries of existing subtrees");
610b60736ecSDimitry Andric
611b60736ecSDimitry Andric auto BelongsToList = [](decltype(Trees)::value_type KV) {
612b60736ecSDimitry Andric auto Role = KV.second->getRole();
613b60736ecSDimitry Andric return Role == syntax::NodeRole::ListElement ||
614b60736ecSDimitry Andric Role == syntax::NodeRole::ListDelimiter;
615b60736ecSDimitry Andric };
616b60736ecSDimitry Andric
617b60736ecSDimitry Andric auto BeginListChildren =
618b60736ecSDimitry Andric std::find_if(BeginChildren, EndChildren, BelongsToList);
619b60736ecSDimitry Andric
620b60736ecSDimitry Andric auto EndListChildren =
621b60736ecSDimitry Andric std::find_if_not(BeginListChildren, EndChildren, BelongsToList);
622b60736ecSDimitry Andric
623b60736ecSDimitry Andric return ArrayRef<syntax::Token>(BeginListChildren->first,
624b60736ecSDimitry Andric EndListChildren->first);
625b60736ecSDimitry Andric }
626b60736ecSDimitry Andric
627706b4fc4SDimitry Andric /// Add \p Node to the forest and attach child nodes based on \p Tokens.
foldChildrensyntax::TreeBuilder::Forest6284b4fe385SDimitry Andric void foldChildren(const syntax::TokenBuffer &TB,
6294b4fe385SDimitry Andric ArrayRef<syntax::Token> Tokens, syntax::Tree *Node) {
630706b4fc4SDimitry Andric // Attach children to `Node`.
631b60736ecSDimitry Andric assert(Node->getFirstChild() == nullptr && "node already has children");
632cfca06d7SDimitry Andric
633cfca06d7SDimitry Andric auto *FirstToken = Tokens.begin();
634cfca06d7SDimitry Andric auto BeginChildren = Trees.lower_bound(FirstToken);
635cfca06d7SDimitry Andric
636cfca06d7SDimitry Andric assert((BeginChildren == Trees.end() ||
637cfca06d7SDimitry Andric BeginChildren->first == FirstToken) &&
638cfca06d7SDimitry Andric "fold crosses boundaries of existing subtrees");
639cfca06d7SDimitry Andric auto EndChildren = Trees.lower_bound(Tokens.end());
640cfca06d7SDimitry Andric assert(
641cfca06d7SDimitry Andric (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) &&
642cfca06d7SDimitry Andric "fold crosses boundaries of existing subtrees");
643cfca06d7SDimitry Andric
644b60736ecSDimitry Andric for (auto It = BeginChildren; It != EndChildren; ++It) {
645b60736ecSDimitry Andric auto *C = It->second;
646b60736ecSDimitry Andric if (C->getRole() == NodeRole::Detached)
647cfca06d7SDimitry Andric C->setRole(NodeRole::Unknown);
648b60736ecSDimitry Andric Node->appendChildLowLevel(C);
649706b4fc4SDimitry Andric }
65022989816SDimitry Andric
651cfca06d7SDimitry Andric // Mark that this node came from the AST and is backed by the source code.
652cfca06d7SDimitry Andric Node->Original = true;
653b60736ecSDimitry Andric Node->CanModify =
6544b4fe385SDimitry Andric TB.spelledForExpanded(Tokens).has_value();
65522989816SDimitry Andric
656cfca06d7SDimitry Andric Trees.erase(BeginChildren, EndChildren);
657cfca06d7SDimitry Andric Trees.insert({FirstToken, Node});
65822989816SDimitry Andric }
65922989816SDimitry Andric
66022989816SDimitry Andric // EXPECTS: all tokens were consumed and are owned by a single root node.
finalizesyntax::TreeBuilder::Forest66122989816SDimitry Andric syntax::Node *finalize() && {
66222989816SDimitry Andric assert(Trees.size() == 1);
663cfca06d7SDimitry Andric auto *Root = Trees.begin()->second;
66422989816SDimitry Andric Trees = {};
66522989816SDimitry Andric return Root;
66622989816SDimitry Andric }
66722989816SDimitry Andric
strsyntax::TreeBuilder::Forest6684b4fe385SDimitry Andric std::string str(const syntax::TokenBufferTokenManager &STM) const {
66922989816SDimitry Andric std::string R;
67022989816SDimitry Andric for (auto It = Trees.begin(); It != Trees.end(); ++It) {
67122989816SDimitry Andric unsigned CoveredTokens =
67222989816SDimitry Andric It != Trees.end()
67322989816SDimitry Andric ? (std::next(It)->first - It->first)
6744b4fe385SDimitry Andric : STM.tokenBuffer().expandedTokens().end() - It->first;
67522989816SDimitry Andric
676b60736ecSDimitry Andric R += std::string(
677b60736ecSDimitry Andric formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(),
6784b4fe385SDimitry Andric It->first->text(STM.sourceManager()), CoveredTokens));
6794b4fe385SDimitry Andric R += It->second->dump(STM);
68022989816SDimitry Andric }
68122989816SDimitry Andric return R;
68222989816SDimitry Andric }
68322989816SDimitry Andric
68422989816SDimitry Andric private:
68522989816SDimitry Andric /// Maps from the start token to a subtree starting at that token.
686706b4fc4SDimitry Andric /// Keys in the map are pointers into the array of expanded tokens, so
687706b4fc4SDimitry Andric /// pointer order corresponds to the order of preprocessor tokens.
688cfca06d7SDimitry Andric std::map<const syntax::Token *, syntax::Node *> Trees;
68922989816SDimitry Andric };
69022989816SDimitry Andric
69122989816SDimitry Andric /// For debugging purposes.
str()6924b4fe385SDimitry Andric std::string str() { return Pending.str(TBTM); }
69322989816SDimitry Andric
69422989816SDimitry Andric syntax::Arena &Arena;
6954b4fe385SDimitry Andric TokenBufferTokenManager& TBTM;
696706b4fc4SDimitry Andric /// To quickly find tokens by their start location.
697b60736ecSDimitry Andric llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken;
69822989816SDimitry Andric Forest Pending;
699706b4fc4SDimitry Andric llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
700cfca06d7SDimitry Andric ASTToSyntaxMapping Mapping;
70122989816SDimitry Andric };
70222989816SDimitry Andric
70322989816SDimitry Andric namespace {
70422989816SDimitry Andric class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
70522989816SDimitry Andric public:
BuildTreeVisitor(ASTContext & Context,syntax::TreeBuilder & Builder)706cfca06d7SDimitry Andric explicit BuildTreeVisitor(ASTContext &Context, syntax::TreeBuilder &Builder)
707cfca06d7SDimitry Andric : Builder(Builder), Context(Context) {}
70822989816SDimitry Andric
shouldTraversePostOrder() const70922989816SDimitry Andric bool shouldTraversePostOrder() const { return true; }
71022989816SDimitry Andric
WalkUpFromDeclaratorDecl(DeclaratorDecl * DD)711cfca06d7SDimitry Andric bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) {
712cfca06d7SDimitry Andric return processDeclaratorAndDeclaration(DD);
713706b4fc4SDimitry Andric }
714cfca06d7SDimitry Andric
WalkUpFromTypedefNameDecl(TypedefNameDecl * TD)715cfca06d7SDimitry Andric bool WalkUpFromTypedefNameDecl(TypedefNameDecl *TD) {
716cfca06d7SDimitry Andric return processDeclaratorAndDeclaration(TD);
71722989816SDimitry Andric }
71822989816SDimitry Andric
VisitDecl(Decl * D)71922989816SDimitry Andric bool VisitDecl(Decl *D) {
72022989816SDimitry Andric assert(!D->isImplicit());
721cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(D),
722cfca06d7SDimitry Andric new (allocator()) syntax::UnknownDeclaration(), D);
723cfca06d7SDimitry Andric return true;
724cfca06d7SDimitry Andric }
725cfca06d7SDimitry Andric
726cfca06d7SDimitry Andric // RAV does not call WalkUpFrom* on explicit instantiations, so we have to
727cfca06d7SDimitry Andric // override Traverse.
728cfca06d7SDimitry Andric // FIXME: make RAV call WalkUpFrom* instead.
729cfca06d7SDimitry Andric bool
TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl * C)730cfca06d7SDimitry Andric TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) {
731cfca06d7SDimitry Andric if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))
732cfca06d7SDimitry Andric return false;
733cfca06d7SDimitry Andric if (C->isExplicitSpecialization())
734cfca06d7SDimitry Andric return true; // we are only interested in explicit instantiations.
735cfca06d7SDimitry Andric auto *Declaration =
736cfca06d7SDimitry Andric cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C));
737cfca06d7SDimitry Andric foldExplicitTemplateInstantiation(
738ac9a064cSDimitry Andric Builder.getTemplateRange(C),
739ac9a064cSDimitry Andric Builder.findToken(C->getExternKeywordLoc()),
740cfca06d7SDimitry Andric Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
741cfca06d7SDimitry Andric return true;
742cfca06d7SDimitry Andric }
743cfca06d7SDimitry Andric
WalkUpFromTemplateDecl(TemplateDecl * S)744cfca06d7SDimitry Andric bool WalkUpFromTemplateDecl(TemplateDecl *S) {
745cfca06d7SDimitry Andric foldTemplateDeclaration(
746cfca06d7SDimitry Andric Builder.getDeclarationRange(S),
747cfca06d7SDimitry Andric Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),
748cfca06d7SDimitry Andric Builder.getDeclarationRange(S->getTemplatedDecl()), S);
749706b4fc4SDimitry Andric return true;
750706b4fc4SDimitry Andric }
751706b4fc4SDimitry Andric
WalkUpFromTagDecl(TagDecl * C)752706b4fc4SDimitry Andric bool WalkUpFromTagDecl(TagDecl *C) {
753706b4fc4SDimitry Andric // FIXME: build the ClassSpecifier node.
754cfca06d7SDimitry Andric if (!C->isFreeStanding()) {
755cfca06d7SDimitry Andric assert(C->getNumTemplateParameterLists() == 0);
756706b4fc4SDimitry Andric return true;
757706b4fc4SDimitry Andric }
758cfca06d7SDimitry Andric handleFreeStandingTagDecl(C);
75922989816SDimitry Andric return true;
76022989816SDimitry Andric }
76122989816SDimitry Andric
handleFreeStandingTagDecl(TagDecl * C)762cfca06d7SDimitry Andric syntax::Declaration *handleFreeStandingTagDecl(TagDecl *C) {
763cfca06d7SDimitry Andric assert(C->isFreeStanding());
764cfca06d7SDimitry Andric // Class is a declaration specifier and needs a spanning declaration node.
765cfca06d7SDimitry Andric auto DeclarationRange = Builder.getDeclarationRange(C);
766cfca06d7SDimitry Andric syntax::Declaration *Result = new (allocator()) syntax::SimpleDeclaration;
767cfca06d7SDimitry Andric Builder.foldNode(DeclarationRange, Result, nullptr);
768cfca06d7SDimitry Andric
769cfca06d7SDimitry Andric // Build TemplateDeclaration nodes if we had template parameters.
770cfca06d7SDimitry Andric auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) {
771cfca06d7SDimitry Andric const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
772e3b55780SDimitry Andric auto R = llvm::ArrayRef(TemplateKW, DeclarationRange.end());
773cfca06d7SDimitry Andric Result =
774cfca06d7SDimitry Andric foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);
775cfca06d7SDimitry Andric DeclarationRange = R;
776cfca06d7SDimitry Andric };
777b60736ecSDimitry Andric if (auto *S = dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
778cfca06d7SDimitry Andric ConsumeTemplateParameters(*S->getTemplateParameters());
779cfca06d7SDimitry Andric for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
780cfca06d7SDimitry Andric ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
781cfca06d7SDimitry Andric return Result;
782cfca06d7SDimitry Andric }
783cfca06d7SDimitry Andric
WalkUpFromTranslationUnitDecl(TranslationUnitDecl * TU)78422989816SDimitry Andric bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) {
785cfca06d7SDimitry Andric // We do not want to call VisitDecl(), the declaration for translation
78622989816SDimitry Andric // unit is built by finalize().
78722989816SDimitry Andric return true;
78822989816SDimitry Andric }
78922989816SDimitry Andric
WalkUpFromCompoundStmt(CompoundStmt * S)79022989816SDimitry Andric bool WalkUpFromCompoundStmt(CompoundStmt *S) {
79122989816SDimitry Andric using NodeRole = syntax::NodeRole;
79222989816SDimitry Andric
793706b4fc4SDimitry Andric Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen);
794706b4fc4SDimitry Andric for (auto *Child : S->body())
795b60736ecSDimitry Andric Builder.markStmtChild(Child, NodeRole::Statement);
796706b4fc4SDimitry Andric Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);
79722989816SDimitry Andric
798706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
799cfca06d7SDimitry Andric new (allocator()) syntax::CompoundStatement, S);
80022989816SDimitry Andric return true;
80122989816SDimitry Andric }
80222989816SDimitry Andric
803706b4fc4SDimitry Andric // Some statements are not yet handled by syntax trees.
WalkUpFromStmt(Stmt * S)804706b4fc4SDimitry Andric bool WalkUpFromStmt(Stmt *S) {
805706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
806cfca06d7SDimitry Andric new (allocator()) syntax::UnknownStatement, S);
807706b4fc4SDimitry Andric return true;
808706b4fc4SDimitry Andric }
809706b4fc4SDimitry Andric
TraverseIfStmt(IfStmt * S)810344a3780SDimitry Andric bool TraverseIfStmt(IfStmt *S) {
811344a3780SDimitry Andric bool Result = [&, this]() {
812344a3780SDimitry Andric if (S->getInit() && !TraverseStmt(S->getInit())) {
813344a3780SDimitry Andric return false;
814344a3780SDimitry Andric }
815344a3780SDimitry Andric // In cases where the condition is an initialized declaration in a
816344a3780SDimitry Andric // statement, we want to preserve the declaration and ignore the
817344a3780SDimitry Andric // implicit condition expression in the syntax tree.
818344a3780SDimitry Andric if (S->hasVarStorage()) {
819344a3780SDimitry Andric if (!TraverseStmt(S->getConditionVariableDeclStmt()))
820344a3780SDimitry Andric return false;
821344a3780SDimitry Andric } else if (S->getCond() && !TraverseStmt(S->getCond()))
822344a3780SDimitry Andric return false;
823344a3780SDimitry Andric
824344a3780SDimitry Andric if (S->getThen() && !TraverseStmt(S->getThen()))
825344a3780SDimitry Andric return false;
826344a3780SDimitry Andric if (S->getElse() && !TraverseStmt(S->getElse()))
827344a3780SDimitry Andric return false;
828344a3780SDimitry Andric return true;
829344a3780SDimitry Andric }();
830344a3780SDimitry Andric WalkUpFromIfStmt(S);
831344a3780SDimitry Andric return Result;
832344a3780SDimitry Andric }
833344a3780SDimitry Andric
TraverseCXXForRangeStmt(CXXForRangeStmt * S)834706b4fc4SDimitry Andric bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) {
835706b4fc4SDimitry Andric // We override to traverse range initializer as VarDecl.
836706b4fc4SDimitry Andric // RAV traverses it as a statement, we produce invalid node kinds in that
837706b4fc4SDimitry Andric // case.
838706b4fc4SDimitry Andric // FIXME: should do this in RAV instead?
839cfca06d7SDimitry Andric bool Result = [&, this]() {
840706b4fc4SDimitry Andric if (S->getInit() && !TraverseStmt(S->getInit()))
841706b4fc4SDimitry Andric return false;
842706b4fc4SDimitry Andric if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable()))
843706b4fc4SDimitry Andric return false;
844706b4fc4SDimitry Andric if (S->getRangeInit() && !TraverseStmt(S->getRangeInit()))
845706b4fc4SDimitry Andric return false;
846706b4fc4SDimitry Andric if (S->getBody() && !TraverseStmt(S->getBody()))
847706b4fc4SDimitry Andric return false;
848706b4fc4SDimitry Andric return true;
849cfca06d7SDimitry Andric }();
850cfca06d7SDimitry Andric WalkUpFromCXXForRangeStmt(S);
851cfca06d7SDimitry Andric return Result;
852706b4fc4SDimitry Andric }
853706b4fc4SDimitry Andric
TraverseStmt(Stmt * S)854706b4fc4SDimitry Andric bool TraverseStmt(Stmt *S) {
855b60736ecSDimitry Andric if (auto *DS = dyn_cast_or_null<DeclStmt>(S)) {
856706b4fc4SDimitry Andric // We want to consume the semicolon, make sure SimpleDeclaration does not.
857706b4fc4SDimitry Andric for (auto *D : DS->decls())
858cfca06d7SDimitry Andric Builder.noticeDeclWithoutSemicolon(D);
859b60736ecSDimitry Andric } else if (auto *E = dyn_cast_or_null<Expr>(S)) {
860b60736ecSDimitry Andric return RecursiveASTVisitor::TraverseStmt(IgnoreImplicit(E));
861706b4fc4SDimitry Andric }
862706b4fc4SDimitry Andric return RecursiveASTVisitor::TraverseStmt(S);
863706b4fc4SDimitry Andric }
864706b4fc4SDimitry Andric
TraverseOpaqueValueExpr(OpaqueValueExpr * VE)865344a3780SDimitry Andric bool TraverseOpaqueValueExpr(OpaqueValueExpr *VE) {
866344a3780SDimitry Andric // OpaqueValue doesn't correspond to concrete syntax, ignore it.
867344a3780SDimitry Andric return true;
868344a3780SDimitry Andric }
869344a3780SDimitry Andric
870706b4fc4SDimitry Andric // Some expressions are not yet handled by syntax trees.
WalkUpFromExpr(Expr * E)871706b4fc4SDimitry Andric bool WalkUpFromExpr(Expr *E) {
872706b4fc4SDimitry Andric assert(!isImplicitExpr(E) && "should be handled by TraverseStmt");
873706b4fc4SDimitry Andric Builder.foldNode(Builder.getExprRange(E),
874cfca06d7SDimitry Andric new (allocator()) syntax::UnknownExpression, E);
875706b4fc4SDimitry Andric return true;
876706b4fc4SDimitry Andric }
877706b4fc4SDimitry Andric
TraverseUserDefinedLiteral(UserDefinedLiteral * S)878cfca06d7SDimitry Andric bool TraverseUserDefinedLiteral(UserDefinedLiteral *S) {
879cfca06d7SDimitry Andric // The semantic AST node `UserDefinedLiteral` (UDL) may have one child node
880cfca06d7SDimitry Andric // referencing the location of the UDL suffix (`_w` in `1.2_w`). The
881cfca06d7SDimitry Andric // UDL suffix location does not point to the beginning of a token, so we
882cfca06d7SDimitry Andric // can't represent the UDL suffix as a separate syntax tree node.
883cfca06d7SDimitry Andric
884cfca06d7SDimitry Andric return WalkUpFromUserDefinedLiteral(S);
885cfca06d7SDimitry Andric }
886cfca06d7SDimitry Andric
887cfca06d7SDimitry Andric syntax::UserDefinedLiteralExpression *
buildUserDefinedLiteral(UserDefinedLiteral * S)888cfca06d7SDimitry Andric buildUserDefinedLiteral(UserDefinedLiteral *S) {
889cfca06d7SDimitry Andric switch (S->getLiteralOperatorKind()) {
890b60736ecSDimitry Andric case UserDefinedLiteral::LOK_Integer:
891cfca06d7SDimitry Andric return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
892b60736ecSDimitry Andric case UserDefinedLiteral::LOK_Floating:
893cfca06d7SDimitry Andric return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
894b60736ecSDimitry Andric case UserDefinedLiteral::LOK_Character:
895cfca06d7SDimitry Andric return new (allocator()) syntax::CharUserDefinedLiteralExpression;
896b60736ecSDimitry Andric case UserDefinedLiteral::LOK_String:
897cfca06d7SDimitry Andric return new (allocator()) syntax::StringUserDefinedLiteralExpression;
898b60736ecSDimitry Andric case UserDefinedLiteral::LOK_Raw:
899b60736ecSDimitry Andric case UserDefinedLiteral::LOK_Template:
900cfca06d7SDimitry Andric // For raw literal operator and numeric literal operator template we
901cfca06d7SDimitry Andric // cannot get the type of the operand in the semantic AST. We get this
902cfca06d7SDimitry Andric // information from the token. As integer and floating point have the same
903cfca06d7SDimitry Andric // token kind, we run `NumericLiteralParser` again to distinguish them.
904cfca06d7SDimitry Andric auto TokLoc = S->getBeginLoc();
905cfca06d7SDimitry Andric auto TokSpelling =
906cfca06d7SDimitry Andric Builder.findToken(TokLoc)->text(Context.getSourceManager());
907cfca06d7SDimitry Andric auto Literal =
908cfca06d7SDimitry Andric NumericLiteralParser(TokSpelling, TokLoc, Context.getSourceManager(),
909cfca06d7SDimitry Andric Context.getLangOpts(), Context.getTargetInfo(),
910cfca06d7SDimitry Andric Context.getDiagnostics());
911cfca06d7SDimitry Andric if (Literal.isIntegerLiteral())
912cfca06d7SDimitry Andric return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
913cfca06d7SDimitry Andric else {
914cfca06d7SDimitry Andric assert(Literal.isFloatingLiteral());
915cfca06d7SDimitry Andric return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
916cfca06d7SDimitry Andric }
917cfca06d7SDimitry Andric }
918cfca06d7SDimitry Andric llvm_unreachable("Unknown literal operator kind.");
919cfca06d7SDimitry Andric }
920cfca06d7SDimitry Andric
WalkUpFromUserDefinedLiteral(UserDefinedLiteral * S)921cfca06d7SDimitry Andric bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) {
922cfca06d7SDimitry Andric Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
923cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S), buildUserDefinedLiteral(S), S);
924cfca06d7SDimitry Andric return true;
925cfca06d7SDimitry Andric }
926cfca06d7SDimitry Andric
927b60736ecSDimitry Andric // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the
928b60736ecSDimitry Andric // `DependentTemplateSpecializationType` case.
929b60736ecSDimitry Andric /// Given a nested-name-specifier return the range for the last name
930b60736ecSDimitry Andric /// specifier.
931b60736ecSDimitry Andric ///
932b60736ecSDimitry Andric /// e.g. `std::T::template X<U>::` => `template X<U>::`
getLocalSourceRange(const NestedNameSpecifierLoc & NNSLoc)933b60736ecSDimitry Andric SourceRange getLocalSourceRange(const NestedNameSpecifierLoc &NNSLoc) {
934b60736ecSDimitry Andric auto SR = NNSLoc.getLocalSourceRange();
935cfca06d7SDimitry Andric
936b60736ecSDimitry Andric // The method `NestedNameSpecifierLoc::getLocalSourceRange` *should*
937b60736ecSDimitry Andric // return the desired `SourceRange`, but there is a corner case. For a
938b60736ecSDimitry Andric // `DependentTemplateSpecializationType` this method returns its
939b60736ecSDimitry Andric // qualifiers as well, in other words in the example above this method
940b60736ecSDimitry Andric // returns `T::template X<U>::` instead of only `template X<U>::`
941b60736ecSDimitry Andric if (auto TL = NNSLoc.getTypeLoc()) {
942b60736ecSDimitry Andric if (auto DependentTL =
943b60736ecSDimitry Andric TL.getAs<DependentTemplateSpecializationTypeLoc>()) {
944b60736ecSDimitry Andric // The 'template' keyword is always present in dependent template
945b60736ecSDimitry Andric // specializations. Except in the case of incorrect code
946b60736ecSDimitry Andric // TODO: Treat the case of incorrect code.
947b60736ecSDimitry Andric SR.setBegin(DependentTL.getTemplateKeywordLoc());
948cfca06d7SDimitry Andric }
949b60736ecSDimitry Andric }
950b60736ecSDimitry Andric
951b60736ecSDimitry Andric return SR;
952b60736ecSDimitry Andric }
953b60736ecSDimitry Andric
getNameSpecifierKind(const NestedNameSpecifier & NNS)954b60736ecSDimitry Andric syntax::NodeKind getNameSpecifierKind(const NestedNameSpecifier &NNS) {
955b60736ecSDimitry Andric switch (NNS.getKind()) {
956b60736ecSDimitry Andric case NestedNameSpecifier::Global:
957b60736ecSDimitry Andric return syntax::NodeKind::GlobalNameSpecifier;
958b60736ecSDimitry Andric case NestedNameSpecifier::Namespace:
959b60736ecSDimitry Andric case NestedNameSpecifier::NamespaceAlias:
960b60736ecSDimitry Andric case NestedNameSpecifier::Identifier:
961b60736ecSDimitry Andric return syntax::NodeKind::IdentifierNameSpecifier;
962b60736ecSDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate:
963b60736ecSDimitry Andric return syntax::NodeKind::SimpleTemplateNameSpecifier;
964b60736ecSDimitry Andric case NestedNameSpecifier::TypeSpec: {
965b60736ecSDimitry Andric const auto *NNSType = NNS.getAsType();
966b60736ecSDimitry Andric assert(NNSType);
967b60736ecSDimitry Andric if (isa<DecltypeType>(NNSType))
968b60736ecSDimitry Andric return syntax::NodeKind::DecltypeNameSpecifier;
969b60736ecSDimitry Andric if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(
970b60736ecSDimitry Andric NNSType))
971b60736ecSDimitry Andric return syntax::NodeKind::SimpleTemplateNameSpecifier;
972b60736ecSDimitry Andric return syntax::NodeKind::IdentifierNameSpecifier;
973b60736ecSDimitry Andric }
974b60736ecSDimitry Andric default:
975b60736ecSDimitry Andric // FIXME: Support Microsoft's __super
976b60736ecSDimitry Andric llvm::report_fatal_error("We don't yet support the __super specifier",
977b60736ecSDimitry Andric true);
978b60736ecSDimitry Andric }
979b60736ecSDimitry Andric }
980b60736ecSDimitry Andric
981b60736ecSDimitry Andric syntax::NameSpecifier *
buildNameSpecifier(const NestedNameSpecifierLoc & NNSLoc)982b60736ecSDimitry Andric buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) {
983b60736ecSDimitry Andric assert(NNSLoc.hasQualifier());
984b60736ecSDimitry Andric auto NameSpecifierTokens =
985b60736ecSDimitry Andric Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back();
986b60736ecSDimitry Andric switch (getNameSpecifierKind(*NNSLoc.getNestedNameSpecifier())) {
987b60736ecSDimitry Andric case syntax::NodeKind::GlobalNameSpecifier:
988b60736ecSDimitry Andric return new (allocator()) syntax::GlobalNameSpecifier;
989b60736ecSDimitry Andric case syntax::NodeKind::IdentifierNameSpecifier: {
990b60736ecSDimitry Andric assert(NameSpecifierTokens.size() == 1);
991b60736ecSDimitry Andric Builder.markChildToken(NameSpecifierTokens.begin(),
992b60736ecSDimitry Andric syntax::NodeRole::Unknown);
993b60736ecSDimitry Andric auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
994b60736ecSDimitry Andric Builder.foldNode(NameSpecifierTokens, NS, nullptr);
995b60736ecSDimitry Andric return NS;
996b60736ecSDimitry Andric }
997b60736ecSDimitry Andric case syntax::NodeKind::SimpleTemplateNameSpecifier: {
998b60736ecSDimitry Andric // TODO: Build `SimpleTemplateNameSpecifier` children and implement
999b60736ecSDimitry Andric // accessors to them.
1000b60736ecSDimitry Andric // Be aware, we cannot do that simply by calling `TraverseTypeLoc`,
1001b60736ecSDimitry Andric // some `TypeLoc`s have inside them the previous name specifier and
1002b60736ecSDimitry Andric // we want to treat them independently.
1003b60736ecSDimitry Andric auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
1004b60736ecSDimitry Andric Builder.foldNode(NameSpecifierTokens, NS, nullptr);
1005b60736ecSDimitry Andric return NS;
1006b60736ecSDimitry Andric }
1007b60736ecSDimitry Andric case syntax::NodeKind::DecltypeNameSpecifier: {
1008b60736ecSDimitry Andric const auto TL = NNSLoc.getTypeLoc().castAs<DecltypeTypeLoc>();
1009b60736ecSDimitry Andric if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL))
1010b60736ecSDimitry Andric return nullptr;
1011b60736ecSDimitry Andric auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
1012b60736ecSDimitry Andric // TODO: Implement accessor to `DecltypeNameSpecifier` inner
1013b60736ecSDimitry Andric // `DecltypeTypeLoc`.
1014b60736ecSDimitry Andric // For that add mapping from `TypeLoc` to `syntax::Node*` then:
1015b60736ecSDimitry Andric // Builder.markChild(TypeLoc, syntax::NodeRole);
1016b60736ecSDimitry Andric Builder.foldNode(NameSpecifierTokens, NS, nullptr);
1017b60736ecSDimitry Andric return NS;
1018b60736ecSDimitry Andric }
1019b60736ecSDimitry Andric default:
1020b60736ecSDimitry Andric llvm_unreachable("getChildKind() does not return this value");
1021b60736ecSDimitry Andric }
1022b60736ecSDimitry Andric }
1023b60736ecSDimitry Andric
1024b60736ecSDimitry Andric // To build syntax tree nodes for NestedNameSpecifierLoc we override
1025b60736ecSDimitry Andric // Traverse instead of WalkUpFrom because we want to traverse the children
1026b60736ecSDimitry Andric // ourselves and build a list instead of a nested tree of name specifier
1027b60736ecSDimitry Andric // prefixes.
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc)1028b60736ecSDimitry Andric bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) {
1029b60736ecSDimitry Andric if (!QualifierLoc)
1030b60736ecSDimitry Andric return true;
1031b60736ecSDimitry Andric for (auto It = QualifierLoc; It; It = It.getPrefix()) {
1032b60736ecSDimitry Andric auto *NS = buildNameSpecifier(It);
1033b60736ecSDimitry Andric if (!NS)
1034b60736ecSDimitry Andric return false;
1035b60736ecSDimitry Andric Builder.markChild(NS, syntax::NodeRole::ListElement);
1036b60736ecSDimitry Andric Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter);
1037b60736ecSDimitry Andric }
1038b60736ecSDimitry Andric Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()),
1039b60736ecSDimitry Andric new (allocator()) syntax::NestedNameSpecifier,
1040b60736ecSDimitry Andric QualifierLoc);
1041b60736ecSDimitry Andric return true;
1042b60736ecSDimitry Andric }
1043b60736ecSDimitry Andric
buildIdExpression(NestedNameSpecifierLoc QualifierLoc,SourceLocation TemplateKeywordLoc,SourceRange UnqualifiedIdLoc,ASTPtr From)1044b60736ecSDimitry Andric syntax::IdExpression *buildIdExpression(NestedNameSpecifierLoc QualifierLoc,
1045b60736ecSDimitry Andric SourceLocation TemplateKeywordLoc,
1046b60736ecSDimitry Andric SourceRange UnqualifiedIdLoc,
1047b60736ecSDimitry Andric ASTPtr From) {
1048b60736ecSDimitry Andric if (QualifierLoc) {
1049b60736ecSDimitry Andric Builder.markChild(QualifierLoc, syntax::NodeRole::Qualifier);
1050b60736ecSDimitry Andric if (TemplateKeywordLoc.isValid())
1051b60736ecSDimitry Andric Builder.markChildToken(TemplateKeywordLoc,
1052b60736ecSDimitry Andric syntax::NodeRole::TemplateKeyword);
1053b60736ecSDimitry Andric }
1054b60736ecSDimitry Andric
1055b60736ecSDimitry Andric auto *TheUnqualifiedId = new (allocator()) syntax::UnqualifiedId;
1056b60736ecSDimitry Andric Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId,
1057b60736ecSDimitry Andric nullptr);
1058b60736ecSDimitry Andric Builder.markChild(TheUnqualifiedId, syntax::NodeRole::UnqualifiedId);
1059b60736ecSDimitry Andric
1060b60736ecSDimitry Andric auto IdExpressionBeginLoc =
1061b60736ecSDimitry Andric QualifierLoc ? QualifierLoc.getBeginLoc() : UnqualifiedIdLoc.getBegin();
1062b60736ecSDimitry Andric
1063b60736ecSDimitry Andric auto *TheIdExpression = new (allocator()) syntax::IdExpression;
1064b60736ecSDimitry Andric Builder.foldNode(
1065b60736ecSDimitry Andric Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.getEnd()),
1066b60736ecSDimitry Andric TheIdExpression, From);
1067b60736ecSDimitry Andric
1068b60736ecSDimitry Andric return TheIdExpression;
1069b60736ecSDimitry Andric }
1070b60736ecSDimitry Andric
WalkUpFromMemberExpr(MemberExpr * S)1071b60736ecSDimitry Andric bool WalkUpFromMemberExpr(MemberExpr *S) {
1072b60736ecSDimitry Andric // For `MemberExpr` with implicit `this->` we generate a simple
1073b60736ecSDimitry Andric // `id-expression` syntax node, beacuse an implicit `member-expression` is
1074b60736ecSDimitry Andric // syntactically undistinguishable from an `id-expression`
1075b60736ecSDimitry Andric if (S->isImplicitAccess()) {
1076b60736ecSDimitry Andric buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1077b60736ecSDimitry Andric SourceRange(S->getMemberLoc(), S->getEndLoc()), S);
1078b60736ecSDimitry Andric return true;
1079b60736ecSDimitry Andric }
1080b60736ecSDimitry Andric
1081b60736ecSDimitry Andric auto *TheIdExpression = buildIdExpression(
1082b60736ecSDimitry Andric S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1083b60736ecSDimitry Andric SourceRange(S->getMemberLoc(), S->getEndLoc()), nullptr);
1084b60736ecSDimitry Andric
1085b60736ecSDimitry Andric Builder.markChild(TheIdExpression, syntax::NodeRole::Member);
1086b60736ecSDimitry Andric
1087b60736ecSDimitry Andric Builder.markExprChild(S->getBase(), syntax::NodeRole::Object);
1088b60736ecSDimitry Andric Builder.markChildToken(S->getOperatorLoc(), syntax::NodeRole::AccessToken);
1089cfca06d7SDimitry Andric
1090cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1091b60736ecSDimitry Andric new (allocator()) syntax::MemberExpression, S);
1092b60736ecSDimitry Andric return true;
1093b60736ecSDimitry Andric }
1094b60736ecSDimitry Andric
WalkUpFromDeclRefExpr(DeclRefExpr * S)1095b60736ecSDimitry Andric bool WalkUpFromDeclRefExpr(DeclRefExpr *S) {
1096b60736ecSDimitry Andric buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1097b60736ecSDimitry Andric SourceRange(S->getLocation(), S->getEndLoc()), S);
1098b60736ecSDimitry Andric
1099b60736ecSDimitry Andric return true;
1100b60736ecSDimitry Andric }
1101b60736ecSDimitry Andric
1102b60736ecSDimitry Andric // Same logic as DeclRefExpr.
WalkUpFromDependentScopeDeclRefExpr(DependentScopeDeclRefExpr * S)1103b60736ecSDimitry Andric bool WalkUpFromDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
1104b60736ecSDimitry Andric buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1105b60736ecSDimitry Andric SourceRange(S->getLocation(), S->getEndLoc()), S);
1106b60736ecSDimitry Andric
1107b60736ecSDimitry Andric return true;
1108b60736ecSDimitry Andric }
1109b60736ecSDimitry Andric
WalkUpFromCXXThisExpr(CXXThisExpr * S)1110b60736ecSDimitry Andric bool WalkUpFromCXXThisExpr(CXXThisExpr *S) {
1111b60736ecSDimitry Andric if (!S->isImplicit()) {
1112b60736ecSDimitry Andric Builder.markChildToken(S->getLocation(),
1113b60736ecSDimitry Andric syntax::NodeRole::IntroducerKeyword);
1114b60736ecSDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1115b60736ecSDimitry Andric new (allocator()) syntax::ThisExpression, S);
1116b60736ecSDimitry Andric }
1117cfca06d7SDimitry Andric return true;
1118cfca06d7SDimitry Andric }
1119cfca06d7SDimitry Andric
WalkUpFromParenExpr(ParenExpr * S)1120cfca06d7SDimitry Andric bool WalkUpFromParenExpr(ParenExpr *S) {
1121cfca06d7SDimitry Andric Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen);
1122b60736ecSDimitry Andric Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::SubExpression);
1123cfca06d7SDimitry Andric Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen);
1124cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1125cfca06d7SDimitry Andric new (allocator()) syntax::ParenExpression, S);
1126cfca06d7SDimitry Andric return true;
1127cfca06d7SDimitry Andric }
1128cfca06d7SDimitry Andric
WalkUpFromIntegerLiteral(IntegerLiteral * S)1129cfca06d7SDimitry Andric bool WalkUpFromIntegerLiteral(IntegerLiteral *S) {
1130cfca06d7SDimitry Andric Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1131cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1132cfca06d7SDimitry Andric new (allocator()) syntax::IntegerLiteralExpression, S);
1133cfca06d7SDimitry Andric return true;
1134cfca06d7SDimitry Andric }
1135cfca06d7SDimitry Andric
WalkUpFromCharacterLiteral(CharacterLiteral * S)1136cfca06d7SDimitry Andric bool WalkUpFromCharacterLiteral(CharacterLiteral *S) {
1137cfca06d7SDimitry Andric Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1138cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1139cfca06d7SDimitry Andric new (allocator()) syntax::CharacterLiteralExpression, S);
1140cfca06d7SDimitry Andric return true;
1141cfca06d7SDimitry Andric }
1142cfca06d7SDimitry Andric
WalkUpFromFloatingLiteral(FloatingLiteral * S)1143cfca06d7SDimitry Andric bool WalkUpFromFloatingLiteral(FloatingLiteral *S) {
1144cfca06d7SDimitry Andric Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1145cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1146cfca06d7SDimitry Andric new (allocator()) syntax::FloatingLiteralExpression, S);
1147cfca06d7SDimitry Andric return true;
1148cfca06d7SDimitry Andric }
1149cfca06d7SDimitry Andric
WalkUpFromStringLiteral(StringLiteral * S)1150cfca06d7SDimitry Andric bool WalkUpFromStringLiteral(StringLiteral *S) {
1151cfca06d7SDimitry Andric Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
1152cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1153cfca06d7SDimitry Andric new (allocator()) syntax::StringLiteralExpression, S);
1154cfca06d7SDimitry Andric return true;
1155cfca06d7SDimitry Andric }
1156cfca06d7SDimitry Andric
WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr * S)1157cfca06d7SDimitry Andric bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) {
1158cfca06d7SDimitry Andric Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1159cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1160cfca06d7SDimitry Andric new (allocator()) syntax::BoolLiteralExpression, S);
1161cfca06d7SDimitry Andric return true;
1162cfca06d7SDimitry Andric }
1163cfca06d7SDimitry Andric
WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr * S)1164cfca06d7SDimitry Andric bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) {
1165cfca06d7SDimitry Andric Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1166cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1167cfca06d7SDimitry Andric new (allocator()) syntax::CxxNullPtrExpression, S);
1168cfca06d7SDimitry Andric return true;
1169cfca06d7SDimitry Andric }
1170cfca06d7SDimitry Andric
WalkUpFromUnaryOperator(UnaryOperator * S)1171cfca06d7SDimitry Andric bool WalkUpFromUnaryOperator(UnaryOperator *S) {
1172cfca06d7SDimitry Andric Builder.markChildToken(S->getOperatorLoc(),
1173b60736ecSDimitry Andric syntax::NodeRole::OperatorToken);
1174b60736ecSDimitry Andric Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::Operand);
1175cfca06d7SDimitry Andric
1176cfca06d7SDimitry Andric if (S->isPostfix())
1177cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1178cfca06d7SDimitry Andric new (allocator()) syntax::PostfixUnaryOperatorExpression,
1179cfca06d7SDimitry Andric S);
1180cfca06d7SDimitry Andric else
1181cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1182cfca06d7SDimitry Andric new (allocator()) syntax::PrefixUnaryOperatorExpression,
1183cfca06d7SDimitry Andric S);
1184cfca06d7SDimitry Andric
1185cfca06d7SDimitry Andric return true;
1186cfca06d7SDimitry Andric }
1187cfca06d7SDimitry Andric
WalkUpFromBinaryOperator(BinaryOperator * S)1188cfca06d7SDimitry Andric bool WalkUpFromBinaryOperator(BinaryOperator *S) {
1189b60736ecSDimitry Andric Builder.markExprChild(S->getLHS(), syntax::NodeRole::LeftHandSide);
1190cfca06d7SDimitry Andric Builder.markChildToken(S->getOperatorLoc(),
1191b60736ecSDimitry Andric syntax::NodeRole::OperatorToken);
1192b60736ecSDimitry Andric Builder.markExprChild(S->getRHS(), syntax::NodeRole::RightHandSide);
1193cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1194cfca06d7SDimitry Andric new (allocator()) syntax::BinaryOperatorExpression, S);
1195cfca06d7SDimitry Andric return true;
1196cfca06d7SDimitry Andric }
1197cfca06d7SDimitry Andric
1198b60736ecSDimitry Andric /// Builds `CallArguments` syntax node from arguments that appear in source
1199b60736ecSDimitry Andric /// code, i.e. not default arguments.
1200b60736ecSDimitry Andric syntax::CallArguments *
buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs)1201b60736ecSDimitry Andric buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs) {
1202b60736ecSDimitry Andric auto Args = dropDefaultArgs(ArgsAndDefaultArgs);
1203b60736ecSDimitry Andric for (auto *Arg : Args) {
1204b60736ecSDimitry Andric Builder.markExprChild(Arg, syntax::NodeRole::ListElement);
1205b60736ecSDimitry Andric const auto *DelimiterToken =
1206b60736ecSDimitry Andric std::next(Builder.findToken(Arg->getEndLoc()));
1207b60736ecSDimitry Andric if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1208b60736ecSDimitry Andric Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1209b60736ecSDimitry Andric }
1210b60736ecSDimitry Andric
1211b60736ecSDimitry Andric auto *Arguments = new (allocator()) syntax::CallArguments;
1212b60736ecSDimitry Andric if (!Args.empty())
1213b60736ecSDimitry Andric Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(),
1214b60736ecSDimitry Andric (*(Args.end() - 1))->getEndLoc()),
1215b60736ecSDimitry Andric Arguments, nullptr);
1216b60736ecSDimitry Andric
1217b60736ecSDimitry Andric return Arguments;
1218b60736ecSDimitry Andric }
1219b60736ecSDimitry Andric
WalkUpFromCallExpr(CallExpr * S)1220b60736ecSDimitry Andric bool WalkUpFromCallExpr(CallExpr *S) {
1221b60736ecSDimitry Andric Builder.markExprChild(S->getCallee(), syntax::NodeRole::Callee);
1222b60736ecSDimitry Andric
1223b60736ecSDimitry Andric const auto *LParenToken =
1224b60736ecSDimitry Andric std::next(Builder.findToken(S->getCallee()->getEndLoc()));
1225b60736ecSDimitry Andric // FIXME: Assert that `LParenToken` is indeed a `l_paren` once we have fixed
1226b60736ecSDimitry Andric // the test on decltype desctructors.
1227b60736ecSDimitry Andric if (LParenToken->kind() == clang::tok::l_paren)
1228b60736ecSDimitry Andric Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);
1229b60736ecSDimitry Andric
1230b60736ecSDimitry Andric Builder.markChild(buildCallArguments(S->arguments()),
1231b60736ecSDimitry Andric syntax::NodeRole::Arguments);
1232b60736ecSDimitry Andric
1233b60736ecSDimitry Andric Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);
1234b60736ecSDimitry Andric
1235b60736ecSDimitry Andric Builder.foldNode(Builder.getRange(S->getSourceRange()),
1236b60736ecSDimitry Andric new (allocator()) syntax::CallExpression, S);
1237b60736ecSDimitry Andric return true;
1238b60736ecSDimitry Andric }
1239b60736ecSDimitry Andric
WalkUpFromCXXConstructExpr(CXXConstructExpr * S)1240b60736ecSDimitry Andric bool WalkUpFromCXXConstructExpr(CXXConstructExpr *S) {
1241b60736ecSDimitry Andric // Ignore the implicit calls to default constructors.
1242b60736ecSDimitry Andric if ((S->getNumArgs() == 0 || isa<CXXDefaultArgExpr>(S->getArg(0))) &&
1243b60736ecSDimitry Andric S->getParenOrBraceRange().isInvalid())
1244b60736ecSDimitry Andric return true;
1245b60736ecSDimitry Andric return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S);
1246b60736ecSDimitry Andric }
1247b60736ecSDimitry Andric
TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * S)1248cfca06d7SDimitry Andric bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
1249b60736ecSDimitry Andric // To construct a syntax tree of the same shape for calls to built-in and
1250b60736ecSDimitry Andric // user-defined operators, ignore the `DeclRefExpr` that refers to the
1251b60736ecSDimitry Andric // operator and treat it as a simple token. Do that by traversing
1252b60736ecSDimitry Andric // arguments instead of children.
1253b60736ecSDimitry Andric for (auto *child : S->arguments()) {
1254cfca06d7SDimitry Andric // A postfix unary operator is declared as taking two operands. The
1255cfca06d7SDimitry Andric // second operand is used to distinguish from its prefix counterpart. In
1256cfca06d7SDimitry Andric // the semantic AST this "phantom" operand is represented as a
1257cfca06d7SDimitry Andric // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this
1258cfca06d7SDimitry Andric // operand because it does not correspond to anything written in source
1259b60736ecSDimitry Andric // code.
1260b60736ecSDimitry Andric if (child->getSourceRange().isInvalid()) {
1261b60736ecSDimitry Andric assert(getOperatorNodeKind(*S) ==
1262b60736ecSDimitry Andric syntax::NodeKind::PostfixUnaryOperatorExpression);
1263cfca06d7SDimitry Andric continue;
1264b60736ecSDimitry Andric }
1265cfca06d7SDimitry Andric if (!TraverseStmt(child))
1266cfca06d7SDimitry Andric return false;
1267cfca06d7SDimitry Andric }
1268cfca06d7SDimitry Andric return WalkUpFromCXXOperatorCallExpr(S);
1269cfca06d7SDimitry Andric }
1270cfca06d7SDimitry Andric
WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr * S)1271cfca06d7SDimitry Andric bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
1272cfca06d7SDimitry Andric switch (getOperatorNodeKind(*S)) {
1273cfca06d7SDimitry Andric case syntax::NodeKind::BinaryOperatorExpression:
1274b60736ecSDimitry Andric Builder.markExprChild(S->getArg(0), syntax::NodeRole::LeftHandSide);
1275b60736ecSDimitry Andric Builder.markChildToken(S->getOperatorLoc(),
1276b60736ecSDimitry Andric syntax::NodeRole::OperatorToken);
1277b60736ecSDimitry Andric Builder.markExprChild(S->getArg(1), syntax::NodeRole::RightHandSide);
1278cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1279cfca06d7SDimitry Andric new (allocator()) syntax::BinaryOperatorExpression, S);
1280cfca06d7SDimitry Andric return true;
1281cfca06d7SDimitry Andric case syntax::NodeKind::PrefixUnaryOperatorExpression:
1282b60736ecSDimitry Andric Builder.markChildToken(S->getOperatorLoc(),
1283b60736ecSDimitry Andric syntax::NodeRole::OperatorToken);
1284b60736ecSDimitry Andric Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);
1285cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1286cfca06d7SDimitry Andric new (allocator()) syntax::PrefixUnaryOperatorExpression,
1287cfca06d7SDimitry Andric S);
1288cfca06d7SDimitry Andric return true;
1289cfca06d7SDimitry Andric case syntax::NodeKind::PostfixUnaryOperatorExpression:
1290b60736ecSDimitry Andric Builder.markChildToken(S->getOperatorLoc(),
1291b60736ecSDimitry Andric syntax::NodeRole::OperatorToken);
1292b60736ecSDimitry Andric Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);
1293cfca06d7SDimitry Andric Builder.foldNode(Builder.getExprRange(S),
1294cfca06d7SDimitry Andric new (allocator()) syntax::PostfixUnaryOperatorExpression,
1295cfca06d7SDimitry Andric S);
1296cfca06d7SDimitry Andric return true;
1297b60736ecSDimitry Andric case syntax::NodeKind::CallExpression: {
1298b60736ecSDimitry Andric Builder.markExprChild(S->getArg(0), syntax::NodeRole::Callee);
1299b60736ecSDimitry Andric
1300b60736ecSDimitry Andric const auto *LParenToken =
1301b60736ecSDimitry Andric std::next(Builder.findToken(S->getArg(0)->getEndLoc()));
1302b60736ecSDimitry Andric // FIXME: Assert that `LParenToken` is indeed a `l_paren` once we have
1303b60736ecSDimitry Andric // fixed the test on decltype desctructors.
1304b60736ecSDimitry Andric if (LParenToken->kind() == clang::tok::l_paren)
1305b60736ecSDimitry Andric Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);
1306b60736ecSDimitry Andric
1307b60736ecSDimitry Andric Builder.markChild(buildCallArguments(CallExpr::arg_range(
1308b60736ecSDimitry Andric S->arg_begin() + 1, S->arg_end())),
1309b60736ecSDimitry Andric syntax::NodeRole::Arguments);
1310b60736ecSDimitry Andric
1311b60736ecSDimitry Andric Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);
1312b60736ecSDimitry Andric
1313b60736ecSDimitry Andric Builder.foldNode(Builder.getRange(S->getSourceRange()),
1314b60736ecSDimitry Andric new (allocator()) syntax::CallExpression, S);
1315b60736ecSDimitry Andric return true;
1316b60736ecSDimitry Andric }
1317cfca06d7SDimitry Andric case syntax::NodeKind::UnknownExpression:
1318b60736ecSDimitry Andric return WalkUpFromExpr(S);
1319cfca06d7SDimitry Andric default:
1320cfca06d7SDimitry Andric llvm_unreachable("getOperatorNodeKind() does not return this value");
1321cfca06d7SDimitry Andric }
1322cfca06d7SDimitry Andric }
1323cfca06d7SDimitry Andric
WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr * S)1324b60736ecSDimitry Andric bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; }
1325b60736ecSDimitry Andric
WalkUpFromNamespaceDecl(NamespaceDecl * S)1326706b4fc4SDimitry Andric bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {
1327cfca06d7SDimitry Andric auto Tokens = Builder.getDeclarationRange(S);
1328706b4fc4SDimitry Andric if (Tokens.front().kind() == tok::coloncolon) {
1329706b4fc4SDimitry Andric // Handle nested namespace definitions. Those start at '::' token, e.g.
1330706b4fc4SDimitry Andric // namespace a^::b {}
1331706b4fc4SDimitry Andric // FIXME: build corresponding nodes for the name of this namespace.
1332706b4fc4SDimitry Andric return true;
1333706b4fc4SDimitry Andric }
1334cfca06d7SDimitry Andric Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition, S);
1335cfca06d7SDimitry Andric return true;
1336cfca06d7SDimitry Andric }
1337cfca06d7SDimitry Andric
1338b60736ecSDimitry Andric // FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test
1339b60736ecSDimitry Andric // results. Find test coverage or remove it.
TraverseParenTypeLoc(ParenTypeLoc L)1340cfca06d7SDimitry Andric bool TraverseParenTypeLoc(ParenTypeLoc L) {
1341cfca06d7SDimitry Andric // We reverse order of traversal to get the proper syntax structure.
1342cfca06d7SDimitry Andric if (!WalkUpFromParenTypeLoc(L))
1343cfca06d7SDimitry Andric return false;
1344cfca06d7SDimitry Andric return TraverseTypeLoc(L.getInnerLoc());
1345cfca06d7SDimitry Andric }
1346cfca06d7SDimitry Andric
WalkUpFromParenTypeLoc(ParenTypeLoc L)1347cfca06d7SDimitry Andric bool WalkUpFromParenTypeLoc(ParenTypeLoc L) {
1348cfca06d7SDimitry Andric Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
1349cfca06d7SDimitry Andric Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
1350cfca06d7SDimitry Andric Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getRParenLoc()),
1351cfca06d7SDimitry Andric new (allocator()) syntax::ParenDeclarator, L);
1352cfca06d7SDimitry Andric return true;
1353cfca06d7SDimitry Andric }
1354cfca06d7SDimitry Andric
1355cfca06d7SDimitry Andric // Declarator chunks, they are produced by type locs and some clang::Decls.
WalkUpFromArrayTypeLoc(ArrayTypeLoc L)1356cfca06d7SDimitry Andric bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L) {
1357cfca06d7SDimitry Andric Builder.markChildToken(L.getLBracketLoc(), syntax::NodeRole::OpenParen);
1358b60736ecSDimitry Andric Builder.markExprChild(L.getSizeExpr(), syntax::NodeRole::Size);
1359cfca06d7SDimitry Andric Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen);
1360cfca06d7SDimitry Andric Builder.foldNode(Builder.getRange(L.getLBracketLoc(), L.getRBracketLoc()),
1361cfca06d7SDimitry Andric new (allocator()) syntax::ArraySubscript, L);
1362cfca06d7SDimitry Andric return true;
1363cfca06d7SDimitry Andric }
1364cfca06d7SDimitry Andric
1365b60736ecSDimitry Andric syntax::ParameterDeclarationList *
buildParameterDeclarationList(ArrayRef<ParmVarDecl * > Params)1366b60736ecSDimitry Andric buildParameterDeclarationList(ArrayRef<ParmVarDecl *> Params) {
1367b60736ecSDimitry Andric for (auto *P : Params) {
1368b60736ecSDimitry Andric Builder.markChild(P, syntax::NodeRole::ListElement);
1369b60736ecSDimitry Andric const auto *DelimiterToken = std::next(Builder.findToken(P->getEndLoc()));
1370b60736ecSDimitry Andric if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1371b60736ecSDimitry Andric Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1372b60736ecSDimitry Andric }
1373b60736ecSDimitry Andric auto *Parameters = new (allocator()) syntax::ParameterDeclarationList;
1374b60736ecSDimitry Andric if (!Params.empty())
1375b60736ecSDimitry Andric Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(),
1376b60736ecSDimitry Andric Params.back()->getEndLoc()),
1377b60736ecSDimitry Andric Parameters, nullptr);
1378b60736ecSDimitry Andric return Parameters;
1379b60736ecSDimitry Andric }
1380b60736ecSDimitry Andric
WalkUpFromFunctionTypeLoc(FunctionTypeLoc L)1381cfca06d7SDimitry Andric bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L) {
1382cfca06d7SDimitry Andric Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
1383b60736ecSDimitry Andric
1384b60736ecSDimitry Andric Builder.markChild(buildParameterDeclarationList(L.getParams()),
1385b60736ecSDimitry Andric syntax::NodeRole::Parameters);
1386b60736ecSDimitry Andric
1387cfca06d7SDimitry Andric Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
1388cfca06d7SDimitry Andric Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()),
1389cfca06d7SDimitry Andric new (allocator()) syntax::ParametersAndQualifiers, L);
1390cfca06d7SDimitry Andric return true;
1391cfca06d7SDimitry Andric }
1392cfca06d7SDimitry Andric
WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L)1393cfca06d7SDimitry Andric bool WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L) {
1394cfca06d7SDimitry Andric if (!L.getTypePtr()->hasTrailingReturn())
1395cfca06d7SDimitry Andric return WalkUpFromFunctionTypeLoc(L);
1396cfca06d7SDimitry Andric
1397b60736ecSDimitry Andric auto *TrailingReturnTokens = buildTrailingReturn(L);
1398cfca06d7SDimitry Andric // Finish building the node for parameters.
1399b60736ecSDimitry Andric Builder.markChild(TrailingReturnTokens, syntax::NodeRole::TrailingReturn);
1400cfca06d7SDimitry Andric return WalkUpFromFunctionTypeLoc(L);
1401cfca06d7SDimitry Andric }
1402cfca06d7SDimitry Andric
TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L)1403b60736ecSDimitry Andric bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) {
1404b60736ecSDimitry Andric // In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds
1405b60736ecSDimitry Andric // to "Y::*" but it points to a `ParenTypeLoc` that corresponds to
1406b60736ecSDimitry Andric // "(Y::*mp)" We thus reverse the order of traversal to get the proper
1407b60736ecSDimitry Andric // syntax structure.
1408b60736ecSDimitry Andric if (!WalkUpFromMemberPointerTypeLoc(L))
1409b60736ecSDimitry Andric return false;
1410b60736ecSDimitry Andric return TraverseTypeLoc(L.getPointeeLoc());
1411b60736ecSDimitry Andric }
1412b60736ecSDimitry Andric
WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L)1413cfca06d7SDimitry Andric bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) {
1414cfca06d7SDimitry Andric auto SR = L.getLocalSourceRange();
1415cfca06d7SDimitry Andric Builder.foldNode(Builder.getRange(SR),
1416cfca06d7SDimitry Andric new (allocator()) syntax::MemberPointer, L);
1417706b4fc4SDimitry Andric return true;
1418706b4fc4SDimitry Andric }
1419706b4fc4SDimitry Andric
1420706b4fc4SDimitry Andric // The code below is very regular, it could even be generated with some
1421706b4fc4SDimitry Andric // preprocessor magic. We merely assign roles to the corresponding children
1422706b4fc4SDimitry Andric // and fold resulting nodes.
WalkUpFromDeclStmt(DeclStmt * S)1423706b4fc4SDimitry Andric bool WalkUpFromDeclStmt(DeclStmt *S) {
1424706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1425cfca06d7SDimitry Andric new (allocator()) syntax::DeclarationStatement, S);
1426706b4fc4SDimitry Andric return true;
1427706b4fc4SDimitry Andric }
1428706b4fc4SDimitry Andric
WalkUpFromNullStmt(NullStmt * S)1429706b4fc4SDimitry Andric bool WalkUpFromNullStmt(NullStmt *S) {
1430706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1431cfca06d7SDimitry Andric new (allocator()) syntax::EmptyStatement, S);
1432706b4fc4SDimitry Andric return true;
1433706b4fc4SDimitry Andric }
1434706b4fc4SDimitry Andric
WalkUpFromSwitchStmt(SwitchStmt * S)1435706b4fc4SDimitry Andric bool WalkUpFromSwitchStmt(SwitchStmt *S) {
1436706b4fc4SDimitry Andric Builder.markChildToken(S->getSwitchLoc(),
1437706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1438706b4fc4SDimitry Andric Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1439706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1440cfca06d7SDimitry Andric new (allocator()) syntax::SwitchStatement, S);
1441706b4fc4SDimitry Andric return true;
1442706b4fc4SDimitry Andric }
1443706b4fc4SDimitry Andric
WalkUpFromCaseStmt(CaseStmt * S)1444706b4fc4SDimitry Andric bool WalkUpFromCaseStmt(CaseStmt *S) {
1445706b4fc4SDimitry Andric Builder.markChildToken(S->getKeywordLoc(),
1446706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1447b60736ecSDimitry Andric Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseValue);
1448706b4fc4SDimitry Andric Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
1449706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1450cfca06d7SDimitry Andric new (allocator()) syntax::CaseStatement, S);
1451706b4fc4SDimitry Andric return true;
1452706b4fc4SDimitry Andric }
1453706b4fc4SDimitry Andric
WalkUpFromDefaultStmt(DefaultStmt * S)1454706b4fc4SDimitry Andric bool WalkUpFromDefaultStmt(DefaultStmt *S) {
1455706b4fc4SDimitry Andric Builder.markChildToken(S->getKeywordLoc(),
1456706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1457706b4fc4SDimitry Andric Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
1458706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1459cfca06d7SDimitry Andric new (allocator()) syntax::DefaultStatement, S);
1460706b4fc4SDimitry Andric return true;
1461706b4fc4SDimitry Andric }
1462706b4fc4SDimitry Andric
WalkUpFromIfStmt(IfStmt * S)1463706b4fc4SDimitry Andric bool WalkUpFromIfStmt(IfStmt *S) {
1464706b4fc4SDimitry Andric Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword);
1465344a3780SDimitry Andric Stmt *ConditionStatement = S->getCond();
1466344a3780SDimitry Andric if (S->hasVarStorage())
1467344a3780SDimitry Andric ConditionStatement = S->getConditionVariableDeclStmt();
1468344a3780SDimitry Andric Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition);
1469b60736ecSDimitry Andric Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement);
1470b60736ecSDimitry Andric Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword);
1471b60736ecSDimitry Andric Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement);
1472706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1473cfca06d7SDimitry Andric new (allocator()) syntax::IfStatement, S);
1474706b4fc4SDimitry Andric return true;
1475706b4fc4SDimitry Andric }
1476706b4fc4SDimitry Andric
WalkUpFromForStmt(ForStmt * S)1477706b4fc4SDimitry Andric bool WalkUpFromForStmt(ForStmt *S) {
1478706b4fc4SDimitry Andric Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
1479706b4fc4SDimitry Andric Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1480706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1481cfca06d7SDimitry Andric new (allocator()) syntax::ForStatement, S);
1482706b4fc4SDimitry Andric return true;
1483706b4fc4SDimitry Andric }
1484706b4fc4SDimitry Andric
WalkUpFromWhileStmt(WhileStmt * S)1485706b4fc4SDimitry Andric bool WalkUpFromWhileStmt(WhileStmt *S) {
1486706b4fc4SDimitry Andric Builder.markChildToken(S->getWhileLoc(),
1487706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1488706b4fc4SDimitry Andric Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1489706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1490cfca06d7SDimitry Andric new (allocator()) syntax::WhileStatement, S);
1491706b4fc4SDimitry Andric return true;
1492706b4fc4SDimitry Andric }
1493706b4fc4SDimitry Andric
WalkUpFromContinueStmt(ContinueStmt * S)1494706b4fc4SDimitry Andric bool WalkUpFromContinueStmt(ContinueStmt *S) {
1495706b4fc4SDimitry Andric Builder.markChildToken(S->getContinueLoc(),
1496706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1497706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1498cfca06d7SDimitry Andric new (allocator()) syntax::ContinueStatement, S);
1499706b4fc4SDimitry Andric return true;
1500706b4fc4SDimitry Andric }
1501706b4fc4SDimitry Andric
WalkUpFromBreakStmt(BreakStmt * S)1502706b4fc4SDimitry Andric bool WalkUpFromBreakStmt(BreakStmt *S) {
1503706b4fc4SDimitry Andric Builder.markChildToken(S->getBreakLoc(),
1504706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1505706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1506cfca06d7SDimitry Andric new (allocator()) syntax::BreakStatement, S);
1507706b4fc4SDimitry Andric return true;
1508706b4fc4SDimitry Andric }
1509706b4fc4SDimitry Andric
WalkUpFromReturnStmt(ReturnStmt * S)1510706b4fc4SDimitry Andric bool WalkUpFromReturnStmt(ReturnStmt *S) {
1511706b4fc4SDimitry Andric Builder.markChildToken(S->getReturnLoc(),
1512706b4fc4SDimitry Andric syntax::NodeRole::IntroducerKeyword);
1513b60736ecSDimitry Andric Builder.markExprChild(S->getRetValue(), syntax::NodeRole::ReturnValue);
1514706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1515cfca06d7SDimitry Andric new (allocator()) syntax::ReturnStatement, S);
1516706b4fc4SDimitry Andric return true;
1517706b4fc4SDimitry Andric }
1518706b4fc4SDimitry Andric
WalkUpFromCXXForRangeStmt(CXXForRangeStmt * S)1519706b4fc4SDimitry Andric bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) {
1520706b4fc4SDimitry Andric Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
1521706b4fc4SDimitry Andric Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1522706b4fc4SDimitry Andric Builder.foldNode(Builder.getStmtRange(S),
1523cfca06d7SDimitry Andric new (allocator()) syntax::RangeBasedForStatement, S);
1524706b4fc4SDimitry Andric return true;
1525706b4fc4SDimitry Andric }
1526706b4fc4SDimitry Andric
WalkUpFromEmptyDecl(EmptyDecl * S)1527706b4fc4SDimitry Andric bool WalkUpFromEmptyDecl(EmptyDecl *S) {
1528cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1529cfca06d7SDimitry Andric new (allocator()) syntax::EmptyDeclaration, S);
1530706b4fc4SDimitry Andric return true;
1531706b4fc4SDimitry Andric }
1532706b4fc4SDimitry Andric
WalkUpFromStaticAssertDecl(StaticAssertDecl * S)1533706b4fc4SDimitry Andric bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) {
1534b60736ecSDimitry Andric Builder.markExprChild(S->getAssertExpr(), syntax::NodeRole::Condition);
1535b60736ecSDimitry Andric Builder.markExprChild(S->getMessage(), syntax::NodeRole::Message);
1536cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1537cfca06d7SDimitry Andric new (allocator()) syntax::StaticAssertDeclaration, S);
1538706b4fc4SDimitry Andric return true;
1539706b4fc4SDimitry Andric }
1540706b4fc4SDimitry Andric
WalkUpFromLinkageSpecDecl(LinkageSpecDecl * S)1541706b4fc4SDimitry Andric bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) {
1542cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1543cfca06d7SDimitry Andric new (allocator()) syntax::LinkageSpecificationDeclaration,
1544cfca06d7SDimitry Andric S);
1545706b4fc4SDimitry Andric return true;
1546706b4fc4SDimitry Andric }
1547706b4fc4SDimitry Andric
WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl * S)1548706b4fc4SDimitry Andric bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) {
1549cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1550cfca06d7SDimitry Andric new (allocator()) syntax::NamespaceAliasDefinition, S);
1551706b4fc4SDimitry Andric return true;
1552706b4fc4SDimitry Andric }
1553706b4fc4SDimitry Andric
WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl * S)1554706b4fc4SDimitry Andric bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) {
1555cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1556cfca06d7SDimitry Andric new (allocator()) syntax::UsingNamespaceDirective, S);
1557706b4fc4SDimitry Andric return true;
1558706b4fc4SDimitry Andric }
1559706b4fc4SDimitry Andric
WalkUpFromUsingDecl(UsingDecl * S)1560706b4fc4SDimitry Andric bool WalkUpFromUsingDecl(UsingDecl *S) {
1561cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1562cfca06d7SDimitry Andric new (allocator()) syntax::UsingDeclaration, S);
1563706b4fc4SDimitry Andric return true;
1564706b4fc4SDimitry Andric }
1565706b4fc4SDimitry Andric
WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl * S)1566706b4fc4SDimitry Andric bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) {
1567cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1568cfca06d7SDimitry Andric new (allocator()) syntax::UsingDeclaration, S);
1569706b4fc4SDimitry Andric return true;
1570706b4fc4SDimitry Andric }
1571706b4fc4SDimitry Andric
WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl * S)1572706b4fc4SDimitry Andric bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) {
1573cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1574cfca06d7SDimitry Andric new (allocator()) syntax::UsingDeclaration, S);
1575706b4fc4SDimitry Andric return true;
1576706b4fc4SDimitry Andric }
1577706b4fc4SDimitry Andric
WalkUpFromTypeAliasDecl(TypeAliasDecl * S)1578706b4fc4SDimitry Andric bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) {
1579cfca06d7SDimitry Andric Builder.foldNode(Builder.getDeclarationRange(S),
1580cfca06d7SDimitry Andric new (allocator()) syntax::TypeAliasDeclaration, S);
1581706b4fc4SDimitry Andric return true;
1582706b4fc4SDimitry Andric }
1583706b4fc4SDimitry Andric
158422989816SDimitry Andric private:
1585cfca06d7SDimitry Andric /// Folds SimpleDeclarator node (if present) and in case this is the last
1586cfca06d7SDimitry Andric /// declarator in the chain it also folds SimpleDeclaration node.
processDeclaratorAndDeclaration(T * D)1587cfca06d7SDimitry Andric template <class T> bool processDeclaratorAndDeclaration(T *D) {
1588b60736ecSDimitry Andric auto Range = getDeclaratorRange(
1589b60736ecSDimitry Andric Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(),
1590b60736ecSDimitry Andric getQualifiedNameStart(D), getInitializerRange(D));
1591cfca06d7SDimitry Andric
1592cfca06d7SDimitry Andric // There doesn't have to be a declarator (e.g. `void foo(int)` only has
1593cfca06d7SDimitry Andric // declaration, but no declarator).
1594b60736ecSDimitry Andric if (!Range.getBegin().isValid()) {
1595b60736ecSDimitry Andric Builder.markChild(new (allocator()) syntax::DeclaratorList,
1596b60736ecSDimitry Andric syntax::NodeRole::Declarators);
1597b60736ecSDimitry Andric Builder.foldNode(Builder.getDeclarationRange(D),
1598b60736ecSDimitry Andric new (allocator()) syntax::SimpleDeclaration, D);
1599b60736ecSDimitry Andric return true;
1600cfca06d7SDimitry Andric }
1601cfca06d7SDimitry Andric
1602b60736ecSDimitry Andric auto *N = new (allocator()) syntax::SimpleDeclarator;
1603b60736ecSDimitry Andric Builder.foldNode(Builder.getRange(Range), N, nullptr);
1604b60736ecSDimitry Andric Builder.markChild(N, syntax::NodeRole::ListElement);
1605b60736ecSDimitry Andric
1606b60736ecSDimitry Andric if (!Builder.isResponsibleForCreatingDeclaration(D)) {
1607b60736ecSDimitry Andric // If this is not the last declarator in the declaration we expect a
1608b60736ecSDimitry Andric // delimiter after it.
1609b60736ecSDimitry Andric const auto *DelimiterToken = std::next(Builder.findToken(Range.getEnd()));
1610b60736ecSDimitry Andric if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1611b60736ecSDimitry Andric Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1612b60736ecSDimitry Andric } else {
1613b60736ecSDimitry Andric auto *DL = new (allocator()) syntax::DeclaratorList;
1614b60736ecSDimitry Andric auto DeclarationRange = Builder.getDeclarationRange(D);
1615b60736ecSDimitry Andric Builder.foldList(DeclarationRange, DL, nullptr);
1616b60736ecSDimitry Andric
1617b60736ecSDimitry Andric Builder.markChild(DL, syntax::NodeRole::Declarators);
1618b60736ecSDimitry Andric Builder.foldNode(DeclarationRange,
1619cfca06d7SDimitry Andric new (allocator()) syntax::SimpleDeclaration, D);
1620cfca06d7SDimitry Andric }
1621cfca06d7SDimitry Andric return true;
1622cfca06d7SDimitry Andric }
1623cfca06d7SDimitry Andric
1624cfca06d7SDimitry Andric /// Returns the range of the built node.
buildTrailingReturn(FunctionProtoTypeLoc L)1625b60736ecSDimitry Andric syntax::TrailingReturnType *buildTrailingReturn(FunctionProtoTypeLoc L) {
1626cfca06d7SDimitry Andric assert(L.getTypePtr()->hasTrailingReturn());
1627cfca06d7SDimitry Andric
1628cfca06d7SDimitry Andric auto ReturnedType = L.getReturnLoc();
1629cfca06d7SDimitry Andric // Build node for the declarator, if any.
1630b60736ecSDimitry Andric auto ReturnDeclaratorRange = SourceRange(GetStartLoc().Visit(ReturnedType),
1631b60736ecSDimitry Andric ReturnedType.getEndLoc());
1632cfca06d7SDimitry Andric syntax::SimpleDeclarator *ReturnDeclarator = nullptr;
1633cfca06d7SDimitry Andric if (ReturnDeclaratorRange.isValid()) {
1634cfca06d7SDimitry Andric ReturnDeclarator = new (allocator()) syntax::SimpleDeclarator;
1635cfca06d7SDimitry Andric Builder.foldNode(Builder.getRange(ReturnDeclaratorRange),
1636cfca06d7SDimitry Andric ReturnDeclarator, nullptr);
1637cfca06d7SDimitry Andric }
1638cfca06d7SDimitry Andric
1639cfca06d7SDimitry Andric // Build node for trailing return type.
1640cfca06d7SDimitry Andric auto Return = Builder.getRange(ReturnedType.getSourceRange());
1641cfca06d7SDimitry Andric const auto *Arrow = Return.begin() - 1;
1642cfca06d7SDimitry Andric assert(Arrow->kind() == tok::arrow);
1643e3b55780SDimitry Andric auto Tokens = llvm::ArrayRef(Arrow, Return.end());
1644cfca06d7SDimitry Andric Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken);
1645cfca06d7SDimitry Andric if (ReturnDeclarator)
1646b60736ecSDimitry Andric Builder.markChild(ReturnDeclarator, syntax::NodeRole::Declarator);
1647cfca06d7SDimitry Andric auto *R = new (allocator()) syntax::TrailingReturnType;
1648cfca06d7SDimitry Andric Builder.foldNode(Tokens, R, L);
1649cfca06d7SDimitry Andric return R;
1650cfca06d7SDimitry Andric }
1651cfca06d7SDimitry Andric
foldExplicitTemplateInstantiation(ArrayRef<syntax::Token> Range,const syntax::Token * ExternKW,const syntax::Token * TemplateKW,syntax::SimpleDeclaration * InnerDeclaration,Decl * From)1652cfca06d7SDimitry Andric void foldExplicitTemplateInstantiation(
1653cfca06d7SDimitry Andric ArrayRef<syntax::Token> Range, const syntax::Token *ExternKW,
1654cfca06d7SDimitry Andric const syntax::Token *TemplateKW,
1655cfca06d7SDimitry Andric syntax::SimpleDeclaration *InnerDeclaration, Decl *From) {
1656cfca06d7SDimitry Andric assert(!ExternKW || ExternKW->kind() == tok::kw_extern);
1657cfca06d7SDimitry Andric assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
1658cfca06d7SDimitry Andric Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword);
1659cfca06d7SDimitry Andric Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1660b60736ecSDimitry Andric Builder.markChild(InnerDeclaration, syntax::NodeRole::Declaration);
1661cfca06d7SDimitry Andric Builder.foldNode(
1662cfca06d7SDimitry Andric Range, new (allocator()) syntax::ExplicitTemplateInstantiation, From);
1663cfca06d7SDimitry Andric }
1664cfca06d7SDimitry Andric
foldTemplateDeclaration(ArrayRef<syntax::Token> Range,const syntax::Token * TemplateKW,ArrayRef<syntax::Token> TemplatedDeclaration,Decl * From)1665cfca06d7SDimitry Andric syntax::TemplateDeclaration *foldTemplateDeclaration(
1666cfca06d7SDimitry Andric ArrayRef<syntax::Token> Range, const syntax::Token *TemplateKW,
1667cfca06d7SDimitry Andric ArrayRef<syntax::Token> TemplatedDeclaration, Decl *From) {
1668cfca06d7SDimitry Andric assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
1669cfca06d7SDimitry Andric Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1670cfca06d7SDimitry Andric
1671cfca06d7SDimitry Andric auto *N = new (allocator()) syntax::TemplateDeclaration;
1672cfca06d7SDimitry Andric Builder.foldNode(Range, N, From);
1673b60736ecSDimitry Andric Builder.markChild(N, syntax::NodeRole::Declaration);
1674cfca06d7SDimitry Andric return N;
1675cfca06d7SDimitry Andric }
1676cfca06d7SDimitry Andric
167722989816SDimitry Andric /// A small helper to save some typing.
allocator()167822989816SDimitry Andric llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); }
167922989816SDimitry Andric
168022989816SDimitry Andric syntax::TreeBuilder &Builder;
1681cfca06d7SDimitry Andric const ASTContext &Context;
168222989816SDimitry Andric };
168322989816SDimitry Andric } // namespace
168422989816SDimitry Andric
noticeDeclWithoutSemicolon(Decl * D)1685cfca06d7SDimitry Andric void syntax::TreeBuilder::noticeDeclWithoutSemicolon(Decl *D) {
1686706b4fc4SDimitry Andric DeclsWithoutSemicolons.insert(D);
1687706b4fc4SDimitry Andric }
1688706b4fc4SDimitry Andric
markChildToken(SourceLocation Loc,NodeRole Role)1689706b4fc4SDimitry Andric void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) {
169022989816SDimitry Andric if (Loc.isInvalid())
169122989816SDimitry Andric return;
169222989816SDimitry Andric Pending.assignRole(*findToken(Loc), Role);
169322989816SDimitry Andric }
169422989816SDimitry Andric
markChildToken(const syntax::Token * T,NodeRole R)1695cfca06d7SDimitry Andric void syntax::TreeBuilder::markChildToken(const syntax::Token *T, NodeRole R) {
1696cfca06d7SDimitry Andric if (!T)
1697cfca06d7SDimitry Andric return;
1698cfca06d7SDimitry Andric Pending.assignRole(*T, R);
1699cfca06d7SDimitry Andric }
1700cfca06d7SDimitry Andric
markChild(syntax::Node * N,NodeRole R)1701cfca06d7SDimitry Andric void syntax::TreeBuilder::markChild(syntax::Node *N, NodeRole R) {
1702cfca06d7SDimitry Andric assert(N);
1703cfca06d7SDimitry Andric setRole(N, R);
1704cfca06d7SDimitry Andric }
1705cfca06d7SDimitry Andric
markChild(ASTPtr N,NodeRole R)1706cfca06d7SDimitry Andric void syntax::TreeBuilder::markChild(ASTPtr N, NodeRole R) {
1707cfca06d7SDimitry Andric auto *SN = Mapping.find(N);
1708cfca06d7SDimitry Andric assert(SN != nullptr);
1709cfca06d7SDimitry Andric setRole(SN, R);
1710cfca06d7SDimitry Andric }
markChild(NestedNameSpecifierLoc NNSLoc,NodeRole R)1711b60736ecSDimitry Andric void syntax::TreeBuilder::markChild(NestedNameSpecifierLoc NNSLoc, NodeRole R) {
1712b60736ecSDimitry Andric auto *SN = Mapping.find(NNSLoc);
1713b60736ecSDimitry Andric assert(SN != nullptr);
1714b60736ecSDimitry Andric setRole(SN, R);
1715b60736ecSDimitry Andric }
1716cfca06d7SDimitry Andric
markStmtChild(Stmt * Child,NodeRole Role)1717706b4fc4SDimitry Andric void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
1718706b4fc4SDimitry Andric if (!Child)
1719706b4fc4SDimitry Andric return;
1720706b4fc4SDimitry Andric
1721cfca06d7SDimitry Andric syntax::Tree *ChildNode;
1722cfca06d7SDimitry Andric if (Expr *ChildExpr = dyn_cast<Expr>(Child)) {
1723706b4fc4SDimitry Andric // This is an expression in a statement position, consume the trailing
1724706b4fc4SDimitry Andric // semicolon and form an 'ExpressionStatement' node.
1725b60736ecSDimitry Andric markExprChild(ChildExpr, NodeRole::Expression);
1726cfca06d7SDimitry Andric ChildNode = new (allocator()) syntax::ExpressionStatement;
1727cfca06d7SDimitry Andric // (!) 'getStmtRange()' ensures this covers a trailing semicolon.
17284b4fe385SDimitry Andric Pending.foldChildren(TBTM.tokenBuffer(), getStmtRange(Child), ChildNode);
1729cfca06d7SDimitry Andric } else {
1730cfca06d7SDimitry Andric ChildNode = Mapping.find(Child);
1731706b4fc4SDimitry Andric }
1732cfca06d7SDimitry Andric assert(ChildNode != nullptr);
1733cfca06d7SDimitry Andric setRole(ChildNode, Role);
1734706b4fc4SDimitry Andric }
1735706b4fc4SDimitry Andric
markExprChild(Expr * Child,NodeRole Role)1736706b4fc4SDimitry Andric void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
1737706b4fc4SDimitry Andric if (!Child)
1738706b4fc4SDimitry Andric return;
1739b60736ecSDimitry Andric Child = IgnoreImplicit(Child);
1740706b4fc4SDimitry Andric
1741cfca06d7SDimitry Andric syntax::Tree *ChildNode = Mapping.find(Child);
1742cfca06d7SDimitry Andric assert(ChildNode != nullptr);
1743cfca06d7SDimitry Andric setRole(ChildNode, Role);
1744706b4fc4SDimitry Andric }
1745706b4fc4SDimitry Andric
findToken(SourceLocation L) const174622989816SDimitry Andric const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
1747cfca06d7SDimitry Andric if (L.isInvalid())
1748cfca06d7SDimitry Andric return nullptr;
1749b60736ecSDimitry Andric auto It = LocationToToken.find(L);
1750706b4fc4SDimitry Andric assert(It != LocationToToken.end());
1751706b4fc4SDimitry Andric return It->second;
175222989816SDimitry Andric }
175322989816SDimitry Andric
buildSyntaxTree(Arena & A,TokenBufferTokenManager & TBTM,ASTContext & Context)1754b60736ecSDimitry Andric syntax::TranslationUnit *syntax::buildSyntaxTree(Arena &A,
17554b4fe385SDimitry Andric TokenBufferTokenManager& TBTM,
1756b60736ecSDimitry Andric ASTContext &Context) {
17574b4fe385SDimitry Andric TreeBuilder Builder(A, TBTM);
1758b60736ecSDimitry Andric BuildTreeVisitor(Context, Builder).TraverseAST(Context);
175922989816SDimitry Andric return std::move(Builder).finalize();
176022989816SDimitry Andric }
1761