19b3f38f9SIlya Biryukov //===- BuildTree.cpp ------------------------------------------*- C++ -*-=====//
29b3f38f9SIlya Biryukov //
39b3f38f9SIlya Biryukov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49b3f38f9SIlya Biryukov // See https://llvm.org/LICENSE.txt for license information.
59b3f38f9SIlya Biryukov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69b3f38f9SIlya Biryukov //
79b3f38f9SIlya Biryukov //===----------------------------------------------------------------------===//
89b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/BuildTree.h"
97d382dcdSMarcel Hlopko #include "clang/AST/ASTFwd.h"
10e702bdb8SIlya Biryukov #include "clang/AST/Decl.h"
11e702bdb8SIlya Biryukov #include "clang/AST/DeclBase.h"
127d382dcdSMarcel Hlopko #include "clang/AST/DeclCXX.h"
137d382dcdSMarcel Hlopko #include "clang/AST/DeclarationName.h"
143785eb83SEduardo Caldas #include "clang/AST/Expr.h"
15*ea8bba7eSEduardo Caldas #include "clang/AST/ExprCXX.h"
169b3f38f9SIlya Biryukov #include "clang/AST/RecursiveASTVisitor.h"
179b3f38f9SIlya Biryukov #include "clang/AST/Stmt.h"
187d382dcdSMarcel Hlopko #include "clang/AST/TypeLoc.h"
197d382dcdSMarcel Hlopko #include "clang/AST/TypeLocVisitor.h"
209b3f38f9SIlya Biryukov #include "clang/Basic/LLVM.h"
219b3f38f9SIlya Biryukov #include "clang/Basic/SourceLocation.h"
229b3f38f9SIlya Biryukov #include "clang/Basic/SourceManager.h"
2388bf9b3dSMarcel Hlopko #include "clang/Basic/Specifiers.h"
249b3f38f9SIlya Biryukov #include "clang/Basic/TokenKinds.h"
259b3f38f9SIlya Biryukov #include "clang/Lex/Lexer.h"
269b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/Nodes.h"
279b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/Tokens.h"
289b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/Tree.h"
299b3f38f9SIlya Biryukov #include "llvm/ADT/ArrayRef.h"
30a711a3a4SMarcel Hlopko #include "llvm/ADT/DenseMap.h"
31a711a3a4SMarcel Hlopko #include "llvm/ADT/PointerUnion.h"
329b3f38f9SIlya Biryukov #include "llvm/ADT/STLExtras.h"
337d382dcdSMarcel Hlopko #include "llvm/ADT/ScopeExit.h"
349b3f38f9SIlya Biryukov #include "llvm/ADT/SmallVector.h"
359b3f38f9SIlya Biryukov #include "llvm/Support/Allocator.h"
369b3f38f9SIlya Biryukov #include "llvm/Support/Casting.h"
3796065cf7SIlya Biryukov #include "llvm/Support/Compiler.h"
389b3f38f9SIlya Biryukov #include "llvm/Support/FormatVariadic.h"
391ad15046SIlya Biryukov #include "llvm/Support/MemoryBuffer.h"
409b3f38f9SIlya Biryukov #include "llvm/Support/raw_ostream.h"
41a711a3a4SMarcel Hlopko #include <cstddef>
429b3f38f9SIlya Biryukov #include <map>
439b3f38f9SIlya Biryukov 
449b3f38f9SIlya Biryukov using namespace clang;
459b3f38f9SIlya Biryukov 
4696065cf7SIlya Biryukov LLVM_ATTRIBUTE_UNUSED
4758fa50f4SIlya Biryukov static bool isImplicitExpr(clang::Expr *E) { return E->IgnoreImplicit() != E; }
4858fa50f4SIlya Biryukov 
497d382dcdSMarcel Hlopko namespace {
507d382dcdSMarcel Hlopko /// Get start location of the Declarator from the TypeLoc.
517d382dcdSMarcel Hlopko /// E.g.:
527d382dcdSMarcel Hlopko ///   loc of `(` in `int (a)`
537d382dcdSMarcel Hlopko ///   loc of `*` in `int *(a)`
547d382dcdSMarcel Hlopko ///   loc of the first `(` in `int (*a)(int)`
557d382dcdSMarcel Hlopko ///   loc of the `*` in `int *(a)(int)`
567d382dcdSMarcel Hlopko ///   loc of the first `*` in `const int *const *volatile a;`
577d382dcdSMarcel Hlopko ///
587d382dcdSMarcel Hlopko /// It is non-trivial to get the start location because TypeLocs are stored
597d382dcdSMarcel Hlopko /// inside out. In the example above `*volatile` is the TypeLoc returned
607d382dcdSMarcel Hlopko /// by `Decl.getTypeSourceInfo()`, and `*const` is what `.getPointeeLoc()`
617d382dcdSMarcel Hlopko /// returns.
627d382dcdSMarcel Hlopko struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> {
637d382dcdSMarcel Hlopko   SourceLocation VisitParenTypeLoc(ParenTypeLoc T) {
647d382dcdSMarcel Hlopko     auto L = Visit(T.getInnerLoc());
657d382dcdSMarcel Hlopko     if (L.isValid())
667d382dcdSMarcel Hlopko       return L;
677d382dcdSMarcel Hlopko     return T.getLParenLoc();
687d382dcdSMarcel Hlopko   }
697d382dcdSMarcel Hlopko 
707d382dcdSMarcel Hlopko   // Types spelled in the prefix part of the declarator.
717d382dcdSMarcel Hlopko   SourceLocation VisitPointerTypeLoc(PointerTypeLoc T) {
727d382dcdSMarcel Hlopko     return HandlePointer(T);
737d382dcdSMarcel Hlopko   }
747d382dcdSMarcel Hlopko 
757d382dcdSMarcel Hlopko   SourceLocation VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
767d382dcdSMarcel Hlopko     return HandlePointer(T);
777d382dcdSMarcel Hlopko   }
787d382dcdSMarcel Hlopko 
797d382dcdSMarcel Hlopko   SourceLocation VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
807d382dcdSMarcel Hlopko     return HandlePointer(T);
817d382dcdSMarcel Hlopko   }
827d382dcdSMarcel Hlopko 
837d382dcdSMarcel Hlopko   SourceLocation VisitReferenceTypeLoc(ReferenceTypeLoc T) {
847d382dcdSMarcel Hlopko     return HandlePointer(T);
857d382dcdSMarcel Hlopko   }
867d382dcdSMarcel Hlopko 
877d382dcdSMarcel Hlopko   SourceLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc T) {
887d382dcdSMarcel Hlopko     return HandlePointer(T);
897d382dcdSMarcel Hlopko   }
907d382dcdSMarcel Hlopko 
917d382dcdSMarcel Hlopko   // All other cases are not important, as they are either part of declaration
927d382dcdSMarcel Hlopko   // specifiers (e.g. inheritors of TypeSpecTypeLoc) or introduce modifiers on
937d382dcdSMarcel Hlopko   // existing declarators (e.g. QualifiedTypeLoc). They cannot start the
947d382dcdSMarcel Hlopko   // declarator themselves, but their underlying type can.
957d382dcdSMarcel Hlopko   SourceLocation VisitTypeLoc(TypeLoc T) {
967d382dcdSMarcel Hlopko     auto N = T.getNextTypeLoc();
977d382dcdSMarcel Hlopko     if (!N)
987d382dcdSMarcel Hlopko       return SourceLocation();
997d382dcdSMarcel Hlopko     return Visit(N);
1007d382dcdSMarcel Hlopko   }
1017d382dcdSMarcel Hlopko 
1027d382dcdSMarcel Hlopko   SourceLocation VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc T) {
1037d382dcdSMarcel Hlopko     if (T.getTypePtr()->hasTrailingReturn())
1047d382dcdSMarcel Hlopko       return SourceLocation(); // avoid recursing into the suffix of declarator.
1057d382dcdSMarcel Hlopko     return VisitTypeLoc(T);
1067d382dcdSMarcel Hlopko   }
1077d382dcdSMarcel Hlopko 
1087d382dcdSMarcel Hlopko private:
1097d382dcdSMarcel Hlopko   template <class PtrLoc> SourceLocation HandlePointer(PtrLoc T) {
1107d382dcdSMarcel Hlopko     auto L = Visit(T.getPointeeLoc());
1117d382dcdSMarcel Hlopko     if (L.isValid())
1127d382dcdSMarcel Hlopko       return L;
1137d382dcdSMarcel Hlopko     return T.getLocalSourceRange().getBegin();
1147d382dcdSMarcel Hlopko   }
1157d382dcdSMarcel Hlopko };
1167d382dcdSMarcel Hlopko } // namespace
1177d382dcdSMarcel Hlopko 
118*ea8bba7eSEduardo Caldas static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) {
119*ea8bba7eSEduardo Caldas   switch (E.getOperator()) {
120*ea8bba7eSEduardo Caldas   // Comparison
121*ea8bba7eSEduardo Caldas   case OO_EqualEqual:
122*ea8bba7eSEduardo Caldas   case OO_ExclaimEqual:
123*ea8bba7eSEduardo Caldas   case OO_Greater:
124*ea8bba7eSEduardo Caldas   case OO_GreaterEqual:
125*ea8bba7eSEduardo Caldas   case OO_Less:
126*ea8bba7eSEduardo Caldas   case OO_LessEqual:
127*ea8bba7eSEduardo Caldas   case OO_Spaceship:
128*ea8bba7eSEduardo Caldas   // Assignment
129*ea8bba7eSEduardo Caldas   case OO_Equal:
130*ea8bba7eSEduardo Caldas   case OO_SlashEqual:
131*ea8bba7eSEduardo Caldas   case OO_PercentEqual:
132*ea8bba7eSEduardo Caldas   case OO_CaretEqual:
133*ea8bba7eSEduardo Caldas   case OO_PipeEqual:
134*ea8bba7eSEduardo Caldas   case OO_LessLessEqual:
135*ea8bba7eSEduardo Caldas   case OO_GreaterGreaterEqual:
136*ea8bba7eSEduardo Caldas   case OO_PlusEqual:
137*ea8bba7eSEduardo Caldas   case OO_MinusEqual:
138*ea8bba7eSEduardo Caldas   case OO_StarEqual:
139*ea8bba7eSEduardo Caldas   case OO_AmpEqual:
140*ea8bba7eSEduardo Caldas   // Binary computation
141*ea8bba7eSEduardo Caldas   case OO_Slash:
142*ea8bba7eSEduardo Caldas   case OO_Percent:
143*ea8bba7eSEduardo Caldas   case OO_Caret:
144*ea8bba7eSEduardo Caldas   case OO_Pipe:
145*ea8bba7eSEduardo Caldas   case OO_LessLess:
146*ea8bba7eSEduardo Caldas   case OO_GreaterGreater:
147*ea8bba7eSEduardo Caldas   case OO_AmpAmp:
148*ea8bba7eSEduardo Caldas   case OO_PipePipe:
149*ea8bba7eSEduardo Caldas   case OO_ArrowStar:
150*ea8bba7eSEduardo Caldas   case OO_Comma:
151*ea8bba7eSEduardo Caldas     return syntax::NodeKind::BinaryOperatorExpression;
152*ea8bba7eSEduardo Caldas   case OO_Tilde:
153*ea8bba7eSEduardo Caldas   case OO_Exclaim:
154*ea8bba7eSEduardo Caldas     return syntax::NodeKind::PrefixUnaryOperatorExpression;
155*ea8bba7eSEduardo Caldas   // Prefix/Postfix increment/decrement
156*ea8bba7eSEduardo Caldas   case OO_PlusPlus:
157*ea8bba7eSEduardo Caldas   case OO_MinusMinus:
158*ea8bba7eSEduardo Caldas     switch (E.getNumArgs()) {
159*ea8bba7eSEduardo Caldas     case 1:
160*ea8bba7eSEduardo Caldas       return syntax::NodeKind::PrefixUnaryOperatorExpression;
161*ea8bba7eSEduardo Caldas     case 2:
162*ea8bba7eSEduardo Caldas       return syntax::NodeKind::PostfixUnaryOperatorExpression;
163*ea8bba7eSEduardo Caldas     default:
164*ea8bba7eSEduardo Caldas       llvm_unreachable("Invalid number of arguments for operator");
165*ea8bba7eSEduardo Caldas     }
166*ea8bba7eSEduardo Caldas   // Operators that can be unary or binary
167*ea8bba7eSEduardo Caldas   case OO_Plus:
168*ea8bba7eSEduardo Caldas   case OO_Minus:
169*ea8bba7eSEduardo Caldas   case OO_Star:
170*ea8bba7eSEduardo Caldas   case OO_Amp:
171*ea8bba7eSEduardo Caldas     switch (E.getNumArgs()) {
172*ea8bba7eSEduardo Caldas     case 1:
173*ea8bba7eSEduardo Caldas       return syntax::NodeKind::PrefixUnaryOperatorExpression;
174*ea8bba7eSEduardo Caldas     case 2:
175*ea8bba7eSEduardo Caldas       return syntax::NodeKind::BinaryOperatorExpression;
176*ea8bba7eSEduardo Caldas     default:
177*ea8bba7eSEduardo Caldas       llvm_unreachable("Invalid number of arguments for operator");
178*ea8bba7eSEduardo Caldas     }
179*ea8bba7eSEduardo Caldas     return syntax::NodeKind::BinaryOperatorExpression;
180*ea8bba7eSEduardo Caldas   // Not yet supported by SyntaxTree
181*ea8bba7eSEduardo Caldas   case OO_New:
182*ea8bba7eSEduardo Caldas   case OO_Delete:
183*ea8bba7eSEduardo Caldas   case OO_Array_New:
184*ea8bba7eSEduardo Caldas   case OO_Array_Delete:
185*ea8bba7eSEduardo Caldas   case OO_Coawait:
186*ea8bba7eSEduardo Caldas   case OO_Call:
187*ea8bba7eSEduardo Caldas   case OO_Subscript:
188*ea8bba7eSEduardo Caldas   case OO_Arrow:
189*ea8bba7eSEduardo Caldas     return syntax::NodeKind::UnknownExpression;
190*ea8bba7eSEduardo Caldas   case OO_Conditional: // not overloadable
191*ea8bba7eSEduardo Caldas   case NUM_OVERLOADED_OPERATORS:
192*ea8bba7eSEduardo Caldas   case OO_None:
193*ea8bba7eSEduardo Caldas     llvm_unreachable("Not an overloadable operator");
194*ea8bba7eSEduardo Caldas   }
195*ea8bba7eSEduardo Caldas }
196*ea8bba7eSEduardo Caldas 
1977d382dcdSMarcel Hlopko /// Gets the range of declarator as defined by the C++ grammar. E.g.
1987d382dcdSMarcel Hlopko ///     `int a;` -> range of `a`,
1997d382dcdSMarcel Hlopko ///     `int *a;` -> range of `*a`,
2007d382dcdSMarcel Hlopko ///     `int a[10];` -> range of `a[10]`,
2017d382dcdSMarcel Hlopko ///     `int a[1][2][3];` -> range of `a[1][2][3]`,
2027d382dcdSMarcel Hlopko ///     `int *a = nullptr` -> range of `*a = nullptr`.
2037d382dcdSMarcel Hlopko /// FIMXE: \p Name must be a source range, e.g. for `operator+`.
2047d382dcdSMarcel Hlopko static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T,
2057d382dcdSMarcel Hlopko                                       SourceLocation Name,
2067d382dcdSMarcel Hlopko                                       SourceRange Initializer) {
2077d382dcdSMarcel Hlopko   SourceLocation Start = GetStartLoc().Visit(T);
2087d382dcdSMarcel Hlopko   SourceLocation End = T.getSourceRange().getEnd();
2097d382dcdSMarcel Hlopko   assert(End.isValid());
2107d382dcdSMarcel Hlopko   if (Name.isValid()) {
2117d382dcdSMarcel Hlopko     if (Start.isInvalid())
2127d382dcdSMarcel Hlopko       Start = Name;
2137d382dcdSMarcel Hlopko     if (SM.isBeforeInTranslationUnit(End, Name))
2147d382dcdSMarcel Hlopko       End = Name;
2157d382dcdSMarcel Hlopko   }
2167d382dcdSMarcel Hlopko   if (Initializer.isValid()) {
217cdce2fe5SMarcel Hlopko     auto InitializerEnd = Initializer.getEnd();
218cdce2fe5SMarcel Hlopko     assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) || End == InitializerEnd);
219cdce2fe5SMarcel Hlopko     End = InitializerEnd;
2207d382dcdSMarcel Hlopko   }
2217d382dcdSMarcel Hlopko   return SourceRange(Start, End);
2227d382dcdSMarcel Hlopko }
2237d382dcdSMarcel Hlopko 
224a711a3a4SMarcel Hlopko namespace {
225a711a3a4SMarcel Hlopko /// All AST hierarchy roots that can be represented as pointers.
226a711a3a4SMarcel Hlopko using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;
227a711a3a4SMarcel Hlopko /// Maintains a mapping from AST to syntax tree nodes. This class will get more
228a711a3a4SMarcel Hlopko /// complicated as we support more kinds of AST nodes, e.g. TypeLocs.
229a711a3a4SMarcel Hlopko /// FIXME: expose this as public API.
230a711a3a4SMarcel Hlopko class ASTToSyntaxMapping {
231a711a3a4SMarcel Hlopko public:
232a711a3a4SMarcel Hlopko   void add(ASTPtr From, syntax::Tree *To) {
233a711a3a4SMarcel Hlopko     assert(To != nullptr);
234a711a3a4SMarcel Hlopko     assert(!From.isNull());
235a711a3a4SMarcel Hlopko 
236a711a3a4SMarcel Hlopko     bool Added = Nodes.insert({From, To}).second;
237a711a3a4SMarcel Hlopko     (void)Added;
238a711a3a4SMarcel Hlopko     assert(Added && "mapping added twice");
239a711a3a4SMarcel Hlopko   }
240a711a3a4SMarcel Hlopko 
241a711a3a4SMarcel Hlopko   syntax::Tree *find(ASTPtr P) const { return Nodes.lookup(P); }
242a711a3a4SMarcel Hlopko 
243a711a3a4SMarcel Hlopko private:
244a711a3a4SMarcel Hlopko   llvm::DenseMap<ASTPtr, syntax::Tree *> Nodes;
245a711a3a4SMarcel Hlopko };
246a711a3a4SMarcel Hlopko } // namespace
247a711a3a4SMarcel Hlopko 
2489b3f38f9SIlya Biryukov /// A helper class for constructing the syntax tree while traversing a clang
2499b3f38f9SIlya Biryukov /// AST.
2509b3f38f9SIlya Biryukov ///
2519b3f38f9SIlya Biryukov /// At each point of the traversal we maintain a list of pending nodes.
2529b3f38f9SIlya Biryukov /// Initially all tokens are added as pending nodes. When processing a clang AST
2539b3f38f9SIlya Biryukov /// node, the clients need to:
2549b3f38f9SIlya Biryukov ///   - create a corresponding syntax node,
2559b3f38f9SIlya Biryukov ///   - assign roles to all pending child nodes with 'markChild' and
2569b3f38f9SIlya Biryukov ///     'markChildToken',
2579b3f38f9SIlya Biryukov ///   - replace the child nodes with the new syntax node in the pending list
2589b3f38f9SIlya Biryukov ///     with 'foldNode'.
2599b3f38f9SIlya Biryukov ///
2609b3f38f9SIlya Biryukov /// Note that all children are expected to be processed when building a node.
2619b3f38f9SIlya Biryukov ///
2629b3f38f9SIlya Biryukov /// Call finalize() to finish building the tree and consume the root node.
2639b3f38f9SIlya Biryukov class syntax::TreeBuilder {
2649b3f38f9SIlya Biryukov public:
265c1bbefefSIlya Biryukov   TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) {
266c1bbefefSIlya Biryukov     for (const auto &T : Arena.tokenBuffer().expandedTokens())
267c1bbefefSIlya Biryukov       LocationToToken.insert({T.location().getRawEncoding(), &T});
268c1bbefefSIlya Biryukov   }
2699b3f38f9SIlya Biryukov 
2709b3f38f9SIlya Biryukov   llvm::BumpPtrAllocator &allocator() { return Arena.allocator(); }
2717d382dcdSMarcel Hlopko   const SourceManager &sourceManager() const { return Arena.sourceManager(); }
2729b3f38f9SIlya Biryukov 
2739b3f38f9SIlya Biryukov   /// Populate children for \p New node, assuming it covers tokens from \p
2749b3f38f9SIlya Biryukov   /// Range.
275a711a3a4SMarcel Hlopko   void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
276a711a3a4SMarcel Hlopko                 ASTPtr From) {
277a711a3a4SMarcel Hlopko     assert(New);
278a711a3a4SMarcel Hlopko     Pending.foldChildren(Arena, Range, New);
279a711a3a4SMarcel Hlopko     if (From)
280a711a3a4SMarcel Hlopko       Mapping.add(From, New);
281a711a3a4SMarcel Hlopko   }
282a711a3a4SMarcel Hlopko   void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
283a711a3a4SMarcel Hlopko                 TypeLoc L) {
284a711a3a4SMarcel Hlopko     // FIXME: add mapping for TypeLocs
285a711a3a4SMarcel Hlopko     foldNode(Range, New, nullptr);
286a711a3a4SMarcel Hlopko   }
2879b3f38f9SIlya Biryukov 
288e702bdb8SIlya Biryukov   /// Notifies that we should not consume trailing semicolon when computing
289e702bdb8SIlya Biryukov   /// token range of \p D.
2907d382dcdSMarcel Hlopko   void noticeDeclWithoutSemicolon(Decl *D);
291e702bdb8SIlya Biryukov 
29258fa50f4SIlya Biryukov   /// Mark the \p Child node with a corresponding \p Role. All marked children
29358fa50f4SIlya Biryukov   /// should be consumed by foldNode.
2947d382dcdSMarcel Hlopko   /// When called on expressions (clang::Expr is derived from clang::Stmt),
29558fa50f4SIlya Biryukov   /// wraps expressions into expression statement.
29658fa50f4SIlya Biryukov   void markStmtChild(Stmt *Child, NodeRole Role);
29758fa50f4SIlya Biryukov   /// Should be called for expressions in non-statement position to avoid
29858fa50f4SIlya Biryukov   /// wrapping into expression statement.
29958fa50f4SIlya Biryukov   void markExprChild(Expr *Child, NodeRole Role);
3009b3f38f9SIlya Biryukov   /// Set role for a token starting at \p Loc.
301def65bb4SIlya Biryukov   void markChildToken(SourceLocation Loc, NodeRole R);
3027d382dcdSMarcel Hlopko   /// Set role for \p T.
3037d382dcdSMarcel Hlopko   void markChildToken(const syntax::Token *T, NodeRole R);
3047d382dcdSMarcel Hlopko 
305a711a3a4SMarcel Hlopko   /// Set role for \p N.
306a711a3a4SMarcel Hlopko   void markChild(syntax::Node *N, NodeRole R);
307a711a3a4SMarcel Hlopko   /// Set role for the syntax node matching \p N.
308a711a3a4SMarcel Hlopko   void markChild(ASTPtr N, NodeRole R);
3099b3f38f9SIlya Biryukov 
3109b3f38f9SIlya Biryukov   /// Finish building the tree and consume the root node.
3119b3f38f9SIlya Biryukov   syntax::TranslationUnit *finalize() && {
3129b3f38f9SIlya Biryukov     auto Tokens = Arena.tokenBuffer().expandedTokens();
313bfbf6b6cSIlya Biryukov     assert(!Tokens.empty());
314bfbf6b6cSIlya Biryukov     assert(Tokens.back().kind() == tok::eof);
315bfbf6b6cSIlya Biryukov 
3169b3f38f9SIlya Biryukov     // Build the root of the tree, consuming all the children.
3171ad15046SIlya Biryukov     Pending.foldChildren(Arena, Tokens.drop_back(),
3189b3f38f9SIlya Biryukov                          new (Arena.allocator()) syntax::TranslationUnit);
3199b3f38f9SIlya Biryukov 
3203b929fe7SIlya Biryukov     auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).finalize());
3213b929fe7SIlya Biryukov     TU->assertInvariantsRecursive();
3223b929fe7SIlya Biryukov     return TU;
3239b3f38f9SIlya Biryukov   }
3249b3f38f9SIlya Biryukov 
32588bf9b3dSMarcel Hlopko   /// Finds a token starting at \p L. The token must exist if \p L is valid.
32688bf9b3dSMarcel Hlopko   const syntax::Token *findToken(SourceLocation L) const;
32788bf9b3dSMarcel Hlopko 
328a711a3a4SMarcel Hlopko   /// Finds the syntax tokens corresponding to the \p SourceRange.
329a711a3a4SMarcel Hlopko   llvm::ArrayRef<syntax::Token> getRange(SourceRange Range) const {
330a711a3a4SMarcel Hlopko     assert(Range.isValid());
331a711a3a4SMarcel Hlopko     return getRange(Range.getBegin(), Range.getEnd());
332a711a3a4SMarcel Hlopko   }
333a711a3a4SMarcel Hlopko 
334a711a3a4SMarcel Hlopko   /// Finds the syntax tokens corresponding to the passed source locations.
3359b3f38f9SIlya Biryukov   /// \p First is the start position of the first token and \p Last is the start
3369b3f38f9SIlya Biryukov   /// position of the last token.
3379b3f38f9SIlya Biryukov   llvm::ArrayRef<syntax::Token> getRange(SourceLocation First,
3389b3f38f9SIlya Biryukov                                          SourceLocation Last) const {
3399b3f38f9SIlya Biryukov     assert(First.isValid());
3409b3f38f9SIlya Biryukov     assert(Last.isValid());
3419b3f38f9SIlya Biryukov     assert(First == Last ||
3429b3f38f9SIlya Biryukov            Arena.sourceManager().isBeforeInTranslationUnit(First, Last));
3439b3f38f9SIlya Biryukov     return llvm::makeArrayRef(findToken(First), std::next(findToken(Last)));
3449b3f38f9SIlya Biryukov   }
34588bf9b3dSMarcel Hlopko 
34688bf9b3dSMarcel Hlopko   llvm::ArrayRef<syntax::Token>
34788bf9b3dSMarcel Hlopko   getTemplateRange(const ClassTemplateSpecializationDecl *D) const {
348a711a3a4SMarcel Hlopko     auto Tokens = getRange(D->getSourceRange());
34988bf9b3dSMarcel Hlopko     return maybeAppendSemicolon(Tokens, D);
35088bf9b3dSMarcel Hlopko   }
35188bf9b3dSMarcel Hlopko 
352cdce2fe5SMarcel Hlopko   /// Returns true if \p D is the last declarator in a chain and is thus
353cdce2fe5SMarcel Hlopko   /// reponsible for creating SimpleDeclaration for the whole chain.
354cdce2fe5SMarcel Hlopko   template <class T>
355cdce2fe5SMarcel Hlopko   bool isResponsibleForCreatingDeclaration(const T *D) const {
356cdce2fe5SMarcel Hlopko     static_assert((std::is_base_of<DeclaratorDecl, T>::value ||
357cdce2fe5SMarcel Hlopko                    std::is_base_of<TypedefNameDecl, T>::value),
358cdce2fe5SMarcel Hlopko                   "only DeclaratorDecl and TypedefNameDecl are supported.");
359cdce2fe5SMarcel Hlopko 
360cdce2fe5SMarcel Hlopko     const Decl *Next = D->getNextDeclInContext();
361cdce2fe5SMarcel Hlopko 
362cdce2fe5SMarcel Hlopko     // There's no next sibling, this one is responsible.
363cdce2fe5SMarcel Hlopko     if (Next == nullptr) {
364cdce2fe5SMarcel Hlopko       return true;
365cdce2fe5SMarcel Hlopko     }
366cdce2fe5SMarcel Hlopko     const auto *NextT = llvm::dyn_cast<T>(Next);
367cdce2fe5SMarcel Hlopko 
368cdce2fe5SMarcel Hlopko     // Next sibling is not the same type, this one is responsible.
369cdce2fe5SMarcel Hlopko     if (NextT == nullptr) {
370cdce2fe5SMarcel Hlopko       return true;
371cdce2fe5SMarcel Hlopko     }
372cdce2fe5SMarcel Hlopko     // Next sibling doesn't begin at the same loc, it must be a different
373cdce2fe5SMarcel Hlopko     // declaration, so this declarator is responsible.
374cdce2fe5SMarcel Hlopko     if (NextT->getBeginLoc() != D->getBeginLoc()) {
375cdce2fe5SMarcel Hlopko       return true;
376cdce2fe5SMarcel Hlopko     }
377cdce2fe5SMarcel Hlopko 
378cdce2fe5SMarcel Hlopko     // NextT is a member of the same declaration, and we need the last member to
379cdce2fe5SMarcel Hlopko     // create declaration. This one is not responsible.
380cdce2fe5SMarcel Hlopko     return false;
381cdce2fe5SMarcel Hlopko   }
382cdce2fe5SMarcel Hlopko 
383cdce2fe5SMarcel Hlopko   llvm::ArrayRef<syntax::Token> getDeclarationRange(Decl *D) {
38488bf9b3dSMarcel Hlopko     llvm::ArrayRef<clang::syntax::Token> Tokens;
38588bf9b3dSMarcel Hlopko     // We want to drop the template parameters for specializations.
38688bf9b3dSMarcel Hlopko     if (const auto *S = llvm::dyn_cast<TagDecl>(D))
38788bf9b3dSMarcel Hlopko       Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());
38888bf9b3dSMarcel Hlopko     else
389a711a3a4SMarcel Hlopko       Tokens = getRange(D->getSourceRange());
39088bf9b3dSMarcel Hlopko     return maybeAppendSemicolon(Tokens, D);
3919b3f38f9SIlya Biryukov   }
392cdce2fe5SMarcel Hlopko 
39358fa50f4SIlya Biryukov   llvm::ArrayRef<syntax::Token> getExprRange(const Expr *E) const {
394a711a3a4SMarcel Hlopko     return getRange(E->getSourceRange());
39558fa50f4SIlya Biryukov   }
396cdce2fe5SMarcel Hlopko 
39758fa50f4SIlya Biryukov   /// Find the adjusted range for the statement, consuming the trailing
39858fa50f4SIlya Biryukov   /// semicolon when needed.
39958fa50f4SIlya Biryukov   llvm::ArrayRef<syntax::Token> getStmtRange(const Stmt *S) const {
400a711a3a4SMarcel Hlopko     auto Tokens = getRange(S->getSourceRange());
40158fa50f4SIlya Biryukov     if (isa<CompoundStmt>(S))
40258fa50f4SIlya Biryukov       return Tokens;
40358fa50f4SIlya Biryukov 
40458fa50f4SIlya Biryukov     // Some statements miss a trailing semicolon, e.g. 'return', 'continue' and
40558fa50f4SIlya Biryukov     // all statements that end with those. Consume this semicolon here.
406e702bdb8SIlya Biryukov     if (Tokens.back().kind() == tok::semi)
407e702bdb8SIlya Biryukov       return Tokens;
408e702bdb8SIlya Biryukov     return withTrailingSemicolon(Tokens);
409e702bdb8SIlya Biryukov   }
410e702bdb8SIlya Biryukov 
411e702bdb8SIlya Biryukov private:
412e702bdb8SIlya Biryukov   llvm::ArrayRef<syntax::Token>
41388bf9b3dSMarcel Hlopko   maybeAppendSemicolon(llvm::ArrayRef<syntax::Token> Tokens,
41488bf9b3dSMarcel Hlopko                        const Decl *D) const {
41588bf9b3dSMarcel Hlopko     if (llvm::isa<NamespaceDecl>(D))
41688bf9b3dSMarcel Hlopko       return Tokens;
41788bf9b3dSMarcel Hlopko     if (DeclsWithoutSemicolons.count(D))
41888bf9b3dSMarcel Hlopko       return Tokens;
41988bf9b3dSMarcel Hlopko     // FIXME: do not consume trailing semicolon on function definitions.
42088bf9b3dSMarcel Hlopko     // Most declarations own a semicolon in syntax trees, but not in clang AST.
42188bf9b3dSMarcel Hlopko     return withTrailingSemicolon(Tokens);
42288bf9b3dSMarcel Hlopko   }
42388bf9b3dSMarcel Hlopko 
42488bf9b3dSMarcel Hlopko   llvm::ArrayRef<syntax::Token>
425e702bdb8SIlya Biryukov   withTrailingSemicolon(llvm::ArrayRef<syntax::Token> Tokens) const {
426e702bdb8SIlya Biryukov     assert(!Tokens.empty());
427e702bdb8SIlya Biryukov     assert(Tokens.back().kind() != tok::eof);
4287d382dcdSMarcel Hlopko     // We never consume 'eof', so looking at the next token is ok.
42958fa50f4SIlya Biryukov     if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi)
43058fa50f4SIlya Biryukov       return llvm::makeArrayRef(Tokens.begin(), Tokens.end() + 1);
43158fa50f4SIlya Biryukov     return Tokens;
4329b3f38f9SIlya Biryukov   }
4339b3f38f9SIlya Biryukov 
434a711a3a4SMarcel Hlopko   void setRole(syntax::Node *N, NodeRole R) {
435a711a3a4SMarcel Hlopko     assert(N->role() == NodeRole::Detached);
436a711a3a4SMarcel Hlopko     N->setRole(R);
437a711a3a4SMarcel Hlopko   }
438a711a3a4SMarcel Hlopko 
4399b3f38f9SIlya Biryukov   /// A collection of trees covering the input tokens.
4409b3f38f9SIlya Biryukov   /// When created, each tree corresponds to a single token in the file.
4419b3f38f9SIlya Biryukov   /// Clients call 'foldChildren' to attach one or more subtrees to a parent
4429b3f38f9SIlya Biryukov   /// node and update the list of trees accordingly.
4439b3f38f9SIlya Biryukov   ///
4449b3f38f9SIlya Biryukov   /// Ensures that added nodes properly nest and cover the whole token stream.
4459b3f38f9SIlya Biryukov   struct Forest {
4469b3f38f9SIlya Biryukov     Forest(syntax::Arena &A) {
447bfbf6b6cSIlya Biryukov       assert(!A.tokenBuffer().expandedTokens().empty());
448bfbf6b6cSIlya Biryukov       assert(A.tokenBuffer().expandedTokens().back().kind() == tok::eof);
4499b3f38f9SIlya Biryukov       // Create all leaf nodes.
450bfbf6b6cSIlya Biryukov       // Note that we do not have 'eof' in the tree.
4511ad15046SIlya Biryukov       for (auto &T : A.tokenBuffer().expandedTokens().drop_back()) {
4521ad15046SIlya Biryukov         auto *L = new (A.allocator()) syntax::Leaf(&T);
4531ad15046SIlya Biryukov         L->Original = true;
4541ad15046SIlya Biryukov         L->CanModify = A.tokenBuffer().spelledForExpanded(T).hasValue();
455a711a3a4SMarcel Hlopko         Trees.insert(Trees.end(), {&T, L});
4561ad15046SIlya Biryukov       }
4579b3f38f9SIlya Biryukov     }
4589b3f38f9SIlya Biryukov 
4599b3f38f9SIlya Biryukov     void assignRole(llvm::ArrayRef<syntax::Token> Range,
4609b3f38f9SIlya Biryukov                     syntax::NodeRole Role) {
4619b3f38f9SIlya Biryukov       assert(!Range.empty());
4629b3f38f9SIlya Biryukov       auto It = Trees.lower_bound(Range.begin());
4639b3f38f9SIlya Biryukov       assert(It != Trees.end() && "no node found");
4649b3f38f9SIlya Biryukov       assert(It->first == Range.begin() && "no child with the specified range");
4659b3f38f9SIlya Biryukov       assert((std::next(It) == Trees.end() ||
4669b3f38f9SIlya Biryukov               std::next(It)->first == Range.end()) &&
4679b3f38f9SIlya Biryukov              "no child with the specified range");
468a711a3a4SMarcel Hlopko       assert(It->second->role() == NodeRole::Detached &&
469a711a3a4SMarcel Hlopko              "re-assigning role for a child");
470a711a3a4SMarcel Hlopko       It->second->setRole(Role);
4719b3f38f9SIlya Biryukov     }
4729b3f38f9SIlya Biryukov 
473e702bdb8SIlya Biryukov     /// Add \p Node to the forest and attach child nodes based on \p Tokens.
4741ad15046SIlya Biryukov     void foldChildren(const syntax::Arena &A,
4751ad15046SIlya Biryukov                       llvm::ArrayRef<syntax::Token> Tokens,
4769b3f38f9SIlya Biryukov                       syntax::Tree *Node) {
477e702bdb8SIlya Biryukov       // Attach children to `Node`.
478cdce2fe5SMarcel Hlopko       assert(Node->firstChild() == nullptr && "node already has children");
479cdce2fe5SMarcel Hlopko 
480cdce2fe5SMarcel Hlopko       auto *FirstToken = Tokens.begin();
481cdce2fe5SMarcel Hlopko       auto BeginChildren = Trees.lower_bound(FirstToken);
482cdce2fe5SMarcel Hlopko 
483cdce2fe5SMarcel Hlopko       assert((BeginChildren == Trees.end() ||
484cdce2fe5SMarcel Hlopko               BeginChildren->first == FirstToken) &&
485cdce2fe5SMarcel Hlopko              "fold crosses boundaries of existing subtrees");
486cdce2fe5SMarcel Hlopko       auto EndChildren = Trees.lower_bound(Tokens.end());
487cdce2fe5SMarcel Hlopko       assert(
488cdce2fe5SMarcel Hlopko           (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) &&
489cdce2fe5SMarcel Hlopko           "fold crosses boundaries of existing subtrees");
490cdce2fe5SMarcel Hlopko 
491cdce2fe5SMarcel Hlopko       // We need to go in reverse order, because we can only prepend.
492cdce2fe5SMarcel Hlopko       for (auto It = EndChildren; It != BeginChildren; --It) {
493cdce2fe5SMarcel Hlopko         auto *C = std::prev(It)->second;
494cdce2fe5SMarcel Hlopko         if (C->role() == NodeRole::Detached)
495cdce2fe5SMarcel Hlopko           C->setRole(NodeRole::Unknown);
496cdce2fe5SMarcel Hlopko         Node->prependChildLowLevel(C);
497e702bdb8SIlya Biryukov       }
4989b3f38f9SIlya Biryukov 
499cdce2fe5SMarcel Hlopko       // Mark that this node came from the AST and is backed by the source code.
500cdce2fe5SMarcel Hlopko       Node->Original = true;
501cdce2fe5SMarcel Hlopko       Node->CanModify = A.tokenBuffer().spelledForExpanded(Tokens).hasValue();
5029b3f38f9SIlya Biryukov 
503cdce2fe5SMarcel Hlopko       Trees.erase(BeginChildren, EndChildren);
504cdce2fe5SMarcel Hlopko       Trees.insert({FirstToken, Node});
5059b3f38f9SIlya Biryukov     }
5069b3f38f9SIlya Biryukov 
5079b3f38f9SIlya Biryukov     // EXPECTS: all tokens were consumed and are owned by a single root node.
5089b3f38f9SIlya Biryukov     syntax::Node *finalize() && {
5099b3f38f9SIlya Biryukov       assert(Trees.size() == 1);
510a711a3a4SMarcel Hlopko       auto *Root = Trees.begin()->second;
5119b3f38f9SIlya Biryukov       Trees = {};
5129b3f38f9SIlya Biryukov       return Root;
5139b3f38f9SIlya Biryukov     }
5149b3f38f9SIlya Biryukov 
5159b3f38f9SIlya Biryukov     std::string str(const syntax::Arena &A) const {
5169b3f38f9SIlya Biryukov       std::string R;
5179b3f38f9SIlya Biryukov       for (auto It = Trees.begin(); It != Trees.end(); ++It) {
5189b3f38f9SIlya Biryukov         unsigned CoveredTokens =
5199b3f38f9SIlya Biryukov             It != Trees.end()
5209b3f38f9SIlya Biryukov                 ? (std::next(It)->first - It->first)
5219b3f38f9SIlya Biryukov                 : A.tokenBuffer().expandedTokens().end() - It->first;
5229b3f38f9SIlya Biryukov 
523adcd0268SBenjamin Kramer         R += std::string(llvm::formatv(
524a711a3a4SMarcel Hlopko             "- '{0}' covers '{1}'+{2} tokens\n", It->second->kind(),
525adcd0268SBenjamin Kramer             It->first->text(A.sourceManager()), CoveredTokens));
526a711a3a4SMarcel Hlopko         R += It->second->dump(A);
5279b3f38f9SIlya Biryukov       }
5289b3f38f9SIlya Biryukov       return R;
5299b3f38f9SIlya Biryukov     }
5309b3f38f9SIlya Biryukov 
5319b3f38f9SIlya Biryukov   private:
5329b3f38f9SIlya Biryukov     /// Maps from the start token to a subtree starting at that token.
533302cb3bcSIlya Biryukov     /// Keys in the map are pointers into the array of expanded tokens, so
534302cb3bcSIlya Biryukov     /// pointer order corresponds to the order of preprocessor tokens.
535a711a3a4SMarcel Hlopko     std::map<const syntax::Token *, syntax::Node *> Trees;
5369b3f38f9SIlya Biryukov   };
5379b3f38f9SIlya Biryukov 
5389b3f38f9SIlya Biryukov   /// For debugging purposes.
5399b3f38f9SIlya Biryukov   std::string str() { return Pending.str(Arena); }
5409b3f38f9SIlya Biryukov 
5419b3f38f9SIlya Biryukov   syntax::Arena &Arena;
542c1bbefefSIlya Biryukov   /// To quickly find tokens by their start location.
543c1bbefefSIlya Biryukov   llvm::DenseMap</*SourceLocation*/ unsigned, const syntax::Token *>
544c1bbefefSIlya Biryukov       LocationToToken;
5459b3f38f9SIlya Biryukov   Forest Pending;
546e702bdb8SIlya Biryukov   llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
547a711a3a4SMarcel Hlopko   ASTToSyntaxMapping Mapping;
5489b3f38f9SIlya Biryukov };
5499b3f38f9SIlya Biryukov 
5509b3f38f9SIlya Biryukov namespace {
5519b3f38f9SIlya Biryukov class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
5529b3f38f9SIlya Biryukov public:
5539b3f38f9SIlya Biryukov   explicit BuildTreeVisitor(ASTContext &Ctx, syntax::TreeBuilder &Builder)
5549b3f38f9SIlya Biryukov       : Builder(Builder), LangOpts(Ctx.getLangOpts()) {}
5559b3f38f9SIlya Biryukov 
5569b3f38f9SIlya Biryukov   bool shouldTraversePostOrder() const { return true; }
5579b3f38f9SIlya Biryukov 
5587d382dcdSMarcel Hlopko   bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) {
559cdce2fe5SMarcel Hlopko     return processDeclaratorAndDeclaration(DD);
5607d382dcdSMarcel Hlopko   }
5617d382dcdSMarcel Hlopko 
562cdce2fe5SMarcel Hlopko   bool WalkUpFromTypedefNameDecl(TypedefNameDecl *TD) {
563cdce2fe5SMarcel Hlopko     return processDeclaratorAndDeclaration(TD);
5649b3f38f9SIlya Biryukov   }
5659b3f38f9SIlya Biryukov 
5669b3f38f9SIlya Biryukov   bool VisitDecl(Decl *D) {
5679b3f38f9SIlya Biryukov     assert(!D->isImplicit());
568cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(D),
569a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UnknownDeclaration(), D);
570e702bdb8SIlya Biryukov     return true;
571e702bdb8SIlya Biryukov   }
572e702bdb8SIlya Biryukov 
57388bf9b3dSMarcel Hlopko   // RAV does not call WalkUpFrom* on explicit instantiations, so we have to
57488bf9b3dSMarcel Hlopko   // override Traverse.
57588bf9b3dSMarcel Hlopko   // FIXME: make RAV call WalkUpFrom* instead.
57688bf9b3dSMarcel Hlopko   bool
57788bf9b3dSMarcel Hlopko   TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) {
57888bf9b3dSMarcel Hlopko     if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))
57988bf9b3dSMarcel Hlopko       return false;
58088bf9b3dSMarcel Hlopko     if (C->isExplicitSpecialization())
58188bf9b3dSMarcel Hlopko       return true; // we are only interested in explicit instantiations.
582a711a3a4SMarcel Hlopko     auto *Declaration =
583a711a3a4SMarcel Hlopko         cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C));
58488bf9b3dSMarcel Hlopko     foldExplicitTemplateInstantiation(
58588bf9b3dSMarcel Hlopko         Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()),
586a711a3a4SMarcel Hlopko         Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
58788bf9b3dSMarcel Hlopko     return true;
58888bf9b3dSMarcel Hlopko   }
58988bf9b3dSMarcel Hlopko 
59088bf9b3dSMarcel Hlopko   bool WalkUpFromTemplateDecl(TemplateDecl *S) {
59188bf9b3dSMarcel Hlopko     foldTemplateDeclaration(
592cdce2fe5SMarcel Hlopko         Builder.getDeclarationRange(S),
59388bf9b3dSMarcel Hlopko         Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),
594cdce2fe5SMarcel Hlopko         Builder.getDeclarationRange(S->getTemplatedDecl()), S);
59588bf9b3dSMarcel Hlopko     return true;
59688bf9b3dSMarcel Hlopko   }
59788bf9b3dSMarcel Hlopko 
598e702bdb8SIlya Biryukov   bool WalkUpFromTagDecl(TagDecl *C) {
59904f627f6SIlya Biryukov     // FIXME: build the ClassSpecifier node.
60088bf9b3dSMarcel Hlopko     if (!C->isFreeStanding()) {
60188bf9b3dSMarcel Hlopko       assert(C->getNumTemplateParameterLists() == 0);
60204f627f6SIlya Biryukov       return true;
60304f627f6SIlya Biryukov     }
604a711a3a4SMarcel Hlopko     handleFreeStandingTagDecl(C);
605a711a3a4SMarcel Hlopko     return true;
606a711a3a4SMarcel Hlopko   }
607a711a3a4SMarcel Hlopko 
608a711a3a4SMarcel Hlopko   syntax::Declaration *handleFreeStandingTagDecl(TagDecl *C) {
609a711a3a4SMarcel Hlopko     assert(C->isFreeStanding());
61088bf9b3dSMarcel Hlopko     // Class is a declaration specifier and needs a spanning declaration node.
611cdce2fe5SMarcel Hlopko     auto DeclarationRange = Builder.getDeclarationRange(C);
612a711a3a4SMarcel Hlopko     syntax::Declaration *Result = new (allocator()) syntax::SimpleDeclaration;
613a711a3a4SMarcel Hlopko     Builder.foldNode(DeclarationRange, Result, nullptr);
61488bf9b3dSMarcel Hlopko 
61588bf9b3dSMarcel Hlopko     // Build TemplateDeclaration nodes if we had template parameters.
61688bf9b3dSMarcel Hlopko     auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) {
61788bf9b3dSMarcel Hlopko       const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
61888bf9b3dSMarcel Hlopko       auto R = llvm::makeArrayRef(TemplateKW, DeclarationRange.end());
619a711a3a4SMarcel Hlopko       Result =
620a711a3a4SMarcel Hlopko           foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);
62188bf9b3dSMarcel Hlopko       DeclarationRange = R;
62288bf9b3dSMarcel Hlopko     };
62388bf9b3dSMarcel Hlopko     if (auto *S = llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
62488bf9b3dSMarcel Hlopko       ConsumeTemplateParameters(*S->getTemplateParameters());
62588bf9b3dSMarcel Hlopko     for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
62688bf9b3dSMarcel Hlopko       ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
627a711a3a4SMarcel Hlopko     return Result;
6289b3f38f9SIlya Biryukov   }
6299b3f38f9SIlya Biryukov 
6309b3f38f9SIlya Biryukov   bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) {
6317d382dcdSMarcel Hlopko     // We do not want to call VisitDecl(), the declaration for translation
6329b3f38f9SIlya Biryukov     // unit is built by finalize().
6339b3f38f9SIlya Biryukov     return true;
6349b3f38f9SIlya Biryukov   }
6359b3f38f9SIlya Biryukov 
6369b3f38f9SIlya Biryukov   bool WalkUpFromCompoundStmt(CompoundStmt *S) {
63751dad419SIlya Biryukov     using NodeRole = syntax::NodeRole;
6389b3f38f9SIlya Biryukov 
639def65bb4SIlya Biryukov     Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen);
64058fa50f4SIlya Biryukov     for (auto *Child : S->body())
64158fa50f4SIlya Biryukov       Builder.markStmtChild(Child, NodeRole::CompoundStatement_statement);
642def65bb4SIlya Biryukov     Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);
6439b3f38f9SIlya Biryukov 
64458fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
645a711a3a4SMarcel Hlopko                      new (allocator()) syntax::CompoundStatement, S);
6469b3f38f9SIlya Biryukov     return true;
6479b3f38f9SIlya Biryukov   }
6489b3f38f9SIlya Biryukov 
64958fa50f4SIlya Biryukov   // Some statements are not yet handled by syntax trees.
65058fa50f4SIlya Biryukov   bool WalkUpFromStmt(Stmt *S) {
65158fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
652a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UnknownStatement, S);
65358fa50f4SIlya Biryukov     return true;
65458fa50f4SIlya Biryukov   }
65558fa50f4SIlya Biryukov 
65658fa50f4SIlya Biryukov   bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) {
65758fa50f4SIlya Biryukov     // We override to traverse range initializer as VarDecl.
65858fa50f4SIlya Biryukov     // RAV traverses it as a statement, we produce invalid node kinds in that
65958fa50f4SIlya Biryukov     // case.
66058fa50f4SIlya Biryukov     // FIXME: should do this in RAV instead?
6617349479fSDmitri Gribenko     bool Result = [&, this]() {
66258fa50f4SIlya Biryukov       if (S->getInit() && !TraverseStmt(S->getInit()))
66358fa50f4SIlya Biryukov         return false;
66458fa50f4SIlya Biryukov       if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable()))
66558fa50f4SIlya Biryukov         return false;
66658fa50f4SIlya Biryukov       if (S->getRangeInit() && !TraverseStmt(S->getRangeInit()))
66758fa50f4SIlya Biryukov         return false;
66858fa50f4SIlya Biryukov       if (S->getBody() && !TraverseStmt(S->getBody()))
66958fa50f4SIlya Biryukov         return false;
67058fa50f4SIlya Biryukov       return true;
6717349479fSDmitri Gribenko     }();
6727349479fSDmitri Gribenko     WalkUpFromCXXForRangeStmt(S);
6737349479fSDmitri Gribenko     return Result;
67458fa50f4SIlya Biryukov   }
67558fa50f4SIlya Biryukov 
67658fa50f4SIlya Biryukov   bool TraverseStmt(Stmt *S) {
677e702bdb8SIlya Biryukov     if (auto *DS = llvm::dyn_cast_or_null<DeclStmt>(S)) {
678e702bdb8SIlya Biryukov       // We want to consume the semicolon, make sure SimpleDeclaration does not.
679e702bdb8SIlya Biryukov       for (auto *D : DS->decls())
6807d382dcdSMarcel Hlopko         Builder.noticeDeclWithoutSemicolon(D);
681e702bdb8SIlya Biryukov     } else if (auto *E = llvm::dyn_cast_or_null<Expr>(S)) {
6823785eb83SEduardo Caldas       return RecursiveASTVisitor::TraverseStmt(E->IgnoreImplicit());
68358fa50f4SIlya Biryukov     }
68458fa50f4SIlya Biryukov     return RecursiveASTVisitor::TraverseStmt(S);
68558fa50f4SIlya Biryukov   }
68658fa50f4SIlya Biryukov 
68758fa50f4SIlya Biryukov   // Some expressions are not yet handled by syntax trees.
68858fa50f4SIlya Biryukov   bool WalkUpFromExpr(Expr *E) {
68958fa50f4SIlya Biryukov     assert(!isImplicitExpr(E) && "should be handled by TraverseStmt");
69058fa50f4SIlya Biryukov     Builder.foldNode(Builder.getExprRange(E),
691a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UnknownExpression, E);
69258fa50f4SIlya Biryukov     return true;
69358fa50f4SIlya Biryukov   }
69458fa50f4SIlya Biryukov 
6951b2f6b4aSEduardo Caldas   syntax::NestedNameSpecifier *
6961b2f6b4aSEduardo Caldas   BuildNestedNameSpecifier(NestedNameSpecifierLoc QualifierLoc) {
6971b2f6b4aSEduardo Caldas     if (!QualifierLoc)
6981b2f6b4aSEduardo Caldas       return nullptr;
6991b2f6b4aSEduardo Caldas     for (auto it = QualifierLoc; it; it = it.getPrefix()) {
7001b2f6b4aSEduardo Caldas       auto *NS = new (allocator()) syntax::NameSpecifier;
7011b2f6b4aSEduardo Caldas       Builder.foldNode(Builder.getRange(it.getLocalSourceRange()), NS, nullptr);
7021b2f6b4aSEduardo Caldas       Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier);
7031b2f6b4aSEduardo Caldas     }
7041b2f6b4aSEduardo Caldas     auto *NNS = new (allocator()) syntax::NestedNameSpecifier;
7051b2f6b4aSEduardo Caldas     Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), NNS,
7061b2f6b4aSEduardo Caldas                      nullptr);
7071b2f6b4aSEduardo Caldas     return NNS;
7081b2f6b4aSEduardo Caldas   }
7091b2f6b4aSEduardo Caldas 
7101b2f6b4aSEduardo Caldas   bool WalkUpFromDeclRefExpr(DeclRefExpr *S) {
7111b2f6b4aSEduardo Caldas     if (auto *NNS = BuildNestedNameSpecifier(S->getQualifierLoc()))
7121b2f6b4aSEduardo Caldas       Builder.markChild(NNS, syntax::NodeRole::IdExpression_qualifier);
7131b2f6b4aSEduardo Caldas 
7141b2f6b4aSEduardo Caldas     auto *unqualifiedId = new (allocator()) syntax::UnqualifiedId;
7151b2f6b4aSEduardo Caldas     // Get `UnqualifiedId` from `DeclRefExpr`.
7161b2f6b4aSEduardo Caldas     // FIXME: Extract this logic so that it can be used by `MemberExpr`,
7171b2f6b4aSEduardo Caldas     // and other semantic constructs, now it is tied to `DeclRefExpr`.
7181b2f6b4aSEduardo Caldas     if (!S->hasExplicitTemplateArgs()) {
7191b2f6b4aSEduardo Caldas       Builder.foldNode(Builder.getRange(S->getNameInfo().getSourceRange()),
7201b2f6b4aSEduardo Caldas                        unqualifiedId, nullptr);
7211b2f6b4aSEduardo Caldas     } else {
7221b2f6b4aSEduardo Caldas       auto templateIdSourceRange =
7231b2f6b4aSEduardo Caldas           SourceRange(S->getNameInfo().getBeginLoc(), S->getRAngleLoc());
7241b2f6b4aSEduardo Caldas       Builder.foldNode(Builder.getRange(templateIdSourceRange), unqualifiedId,
7251b2f6b4aSEduardo Caldas                        nullptr);
7261b2f6b4aSEduardo Caldas     }
7271b2f6b4aSEduardo Caldas     Builder.markChild(unqualifiedId, syntax::NodeRole::IdExpression_id);
7281b2f6b4aSEduardo Caldas 
7291b2f6b4aSEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
7301b2f6b4aSEduardo Caldas                      new (allocator()) syntax::IdExpression, S);
7311b2f6b4aSEduardo Caldas     return true;
7321b2f6b4aSEduardo Caldas   }
7331b2f6b4aSEduardo Caldas 
734fdbd7833SEduardo Caldas   bool WalkUpFromParenExpr(ParenExpr *S) {
735fdbd7833SEduardo Caldas     Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen);
736fdbd7833SEduardo Caldas     Builder.markExprChild(S->getSubExpr(),
737fdbd7833SEduardo Caldas                           syntax::NodeRole::ParenExpression_subExpression);
738fdbd7833SEduardo Caldas     Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen);
739fdbd7833SEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
740fdbd7833SEduardo Caldas                      new (allocator()) syntax::ParenExpression, S);
741fdbd7833SEduardo Caldas     return true;
742fdbd7833SEduardo Caldas   }
743fdbd7833SEduardo Caldas 
7443b739690SEduardo Caldas   bool WalkUpFromIntegerLiteral(IntegerLiteral *S) {
74542f6fec3SEduardo Caldas     Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
7463b739690SEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
7473b739690SEduardo Caldas                      new (allocator()) syntax::IntegerLiteralExpression, S);
7483b739690SEduardo Caldas     return true;
7493b739690SEduardo Caldas   }
7503b739690SEduardo Caldas 
751221d7bbeSEduardo Caldas   bool WalkUpFromCharacterLiteral(CharacterLiteral *S) {
752221d7bbeSEduardo Caldas     Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
753221d7bbeSEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
754221d7bbeSEduardo Caldas                      new (allocator()) syntax::CharacterLiteralExpression, S);
755221d7bbeSEduardo Caldas     return true;
756221d7bbeSEduardo Caldas   }
7577b404b6dSEduardo Caldas 
7587b404b6dSEduardo Caldas   bool WalkUpFromFloatingLiteral(FloatingLiteral *S) {
7597b404b6dSEduardo Caldas     Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
7607b404b6dSEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
7617b404b6dSEduardo Caldas                      new (allocator()) syntax::FloatingLiteralExpression, S);
7627b404b6dSEduardo Caldas     return true;
7637b404b6dSEduardo Caldas   }
7647b404b6dSEduardo Caldas 
765466e8b7eSEduardo Caldas   bool WalkUpFromStringLiteral(StringLiteral *S) {
766466e8b7eSEduardo Caldas     Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
767466e8b7eSEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
768466e8b7eSEduardo Caldas                      new (allocator()) syntax::StringLiteralExpression, S);
769466e8b7eSEduardo Caldas     return true;
770466e8b7eSEduardo Caldas   }
771221d7bbeSEduardo Caldas 
7727b404b6dSEduardo Caldas   bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) {
7737b404b6dSEduardo Caldas     Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
7747b404b6dSEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
7757b404b6dSEduardo Caldas                      new (allocator()) syntax::BoolLiteralExpression, S);
7767b404b6dSEduardo Caldas     return true;
7777b404b6dSEduardo Caldas   }
7787b404b6dSEduardo Caldas 
779007098d7SEduardo Caldas   bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) {
78042f6fec3SEduardo Caldas     Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
781007098d7SEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
782007098d7SEduardo Caldas                      new (allocator()) syntax::CxxNullPtrExpression, S);
783007098d7SEduardo Caldas     return true;
784007098d7SEduardo Caldas   }
785007098d7SEduardo Caldas 
786461af57dSEduardo Caldas   bool WalkUpFromUnaryOperator(UnaryOperator *S) {
78742f6fec3SEduardo Caldas     Builder.markChildToken(S->getOperatorLoc(),
78842f6fec3SEduardo Caldas                            syntax::NodeRole::OperatorExpression_operatorToken);
789461af57dSEduardo Caldas     Builder.markExprChild(S->getSubExpr(),
790461af57dSEduardo Caldas                           syntax::NodeRole::UnaryOperatorExpression_operand);
791461af57dSEduardo Caldas 
792461af57dSEduardo Caldas     if (S->isPostfix())
793461af57dSEduardo Caldas       Builder.foldNode(Builder.getExprRange(S),
794461af57dSEduardo Caldas                        new (allocator()) syntax::PostfixUnaryOperatorExpression,
795461af57dSEduardo Caldas                        S);
796461af57dSEduardo Caldas     else
797461af57dSEduardo Caldas       Builder.foldNode(Builder.getExprRange(S),
798461af57dSEduardo Caldas                        new (allocator()) syntax::PrefixUnaryOperatorExpression,
799461af57dSEduardo Caldas                        S);
800461af57dSEduardo Caldas 
801461af57dSEduardo Caldas     return true;
802461af57dSEduardo Caldas   }
803461af57dSEduardo Caldas 
8043785eb83SEduardo Caldas   bool WalkUpFromBinaryOperator(BinaryOperator *S) {
8053785eb83SEduardo Caldas     Builder.markExprChild(
8063785eb83SEduardo Caldas         S->getLHS(), syntax::NodeRole::BinaryOperatorExpression_leftHandSide);
80742f6fec3SEduardo Caldas     Builder.markChildToken(S->getOperatorLoc(),
80842f6fec3SEduardo Caldas                            syntax::NodeRole::OperatorExpression_operatorToken);
8093785eb83SEduardo Caldas     Builder.markExprChild(
8103785eb83SEduardo Caldas         S->getRHS(), syntax::NodeRole::BinaryOperatorExpression_rightHandSide);
8113785eb83SEduardo Caldas     Builder.foldNode(Builder.getExprRange(S),
8123785eb83SEduardo Caldas                      new (allocator()) syntax::BinaryOperatorExpression, S);
8133785eb83SEduardo Caldas     return true;
8143785eb83SEduardo Caldas   }
8153785eb83SEduardo Caldas 
816*ea8bba7eSEduardo Caldas   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
817*ea8bba7eSEduardo Caldas     if (getOperatorNodeKind(*S) ==
818*ea8bba7eSEduardo Caldas         syntax::NodeKind::PostfixUnaryOperatorExpression) {
819*ea8bba7eSEduardo Caldas       // A postfix unary operator is declared as taking two operands. The second
820*ea8bba7eSEduardo Caldas       // operand is used to distinguish from its prefix counterpart. In the
821*ea8bba7eSEduardo Caldas       // semantic AST this "phantom" operand is represented as a
822*ea8bba7eSEduardo Caldas       // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this
823*ea8bba7eSEduardo Caldas       // operand because it does not correspond to anything written in source
824*ea8bba7eSEduardo Caldas       // code
825*ea8bba7eSEduardo Caldas       for (auto *child : S->children()) {
826*ea8bba7eSEduardo Caldas         if (child->getSourceRange().isInvalid())
827*ea8bba7eSEduardo Caldas           continue;
828*ea8bba7eSEduardo Caldas         if (!TraverseStmt(child))
829*ea8bba7eSEduardo Caldas           return false;
830*ea8bba7eSEduardo Caldas       }
831*ea8bba7eSEduardo Caldas       return WalkUpFromCXXOperatorCallExpr(S);
832*ea8bba7eSEduardo Caldas     } else
833*ea8bba7eSEduardo Caldas       return RecursiveASTVisitor::TraverseCXXOperatorCallExpr(S);
834*ea8bba7eSEduardo Caldas   }
835*ea8bba7eSEduardo Caldas 
8363a574a6cSEduardo Caldas   bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
837*ea8bba7eSEduardo Caldas     switch (getOperatorNodeKind(*S)) {
838*ea8bba7eSEduardo Caldas     case syntax::NodeKind::BinaryOperatorExpression:
8393a574a6cSEduardo Caldas       Builder.markExprChild(
8403a574a6cSEduardo Caldas           S->getArg(0),
8413a574a6cSEduardo Caldas           syntax::NodeRole::BinaryOperatorExpression_leftHandSide);
8423a574a6cSEduardo Caldas       Builder.markChildToken(
8433a574a6cSEduardo Caldas           S->getOperatorLoc(),
84442f6fec3SEduardo Caldas           syntax::NodeRole::OperatorExpression_operatorToken);
8453a574a6cSEduardo Caldas       Builder.markExprChild(
8463a574a6cSEduardo Caldas           S->getArg(1),
8473a574a6cSEduardo Caldas           syntax::NodeRole::BinaryOperatorExpression_rightHandSide);
8483a574a6cSEduardo Caldas       Builder.foldNode(Builder.getExprRange(S),
8493a574a6cSEduardo Caldas                        new (allocator()) syntax::BinaryOperatorExpression, S);
8503a574a6cSEduardo Caldas       return true;
851*ea8bba7eSEduardo Caldas     case syntax::NodeKind::PrefixUnaryOperatorExpression:
852*ea8bba7eSEduardo Caldas       Builder.markChildToken(
853*ea8bba7eSEduardo Caldas           S->getOperatorLoc(),
854*ea8bba7eSEduardo Caldas           syntax::NodeRole::OperatorExpression_operatorToken);
855*ea8bba7eSEduardo Caldas       Builder.markExprChild(S->getArg(0),
856*ea8bba7eSEduardo Caldas                             syntax::NodeRole::UnaryOperatorExpression_operand);
857*ea8bba7eSEduardo Caldas       Builder.foldNode(Builder.getExprRange(S),
858*ea8bba7eSEduardo Caldas                        new (allocator()) syntax::PrefixUnaryOperatorExpression,
859*ea8bba7eSEduardo Caldas                        S);
860*ea8bba7eSEduardo Caldas       return true;
861*ea8bba7eSEduardo Caldas     case syntax::NodeKind::PostfixUnaryOperatorExpression:
862*ea8bba7eSEduardo Caldas       Builder.markChildToken(
863*ea8bba7eSEduardo Caldas           S->getOperatorLoc(),
864*ea8bba7eSEduardo Caldas           syntax::NodeRole::OperatorExpression_operatorToken);
865*ea8bba7eSEduardo Caldas       Builder.markExprChild(S->getArg(0),
866*ea8bba7eSEduardo Caldas                             syntax::NodeRole::UnaryOperatorExpression_operand);
867*ea8bba7eSEduardo Caldas       Builder.foldNode(Builder.getExprRange(S),
868*ea8bba7eSEduardo Caldas                        new (allocator()) syntax::PostfixUnaryOperatorExpression,
869*ea8bba7eSEduardo Caldas                        S);
870*ea8bba7eSEduardo Caldas       return true;
871*ea8bba7eSEduardo Caldas     case syntax::NodeKind::UnknownExpression:
8723a574a6cSEduardo Caldas       return RecursiveASTVisitor::WalkUpFromCXXOperatorCallExpr(S);
873*ea8bba7eSEduardo Caldas     default:
874*ea8bba7eSEduardo Caldas       llvm_unreachable("getOperatorNodeKind() does not return this value");
875*ea8bba7eSEduardo Caldas     }
8763a574a6cSEduardo Caldas   }
8773a574a6cSEduardo Caldas 
878be14a22bSIlya Biryukov   bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {
879cdce2fe5SMarcel Hlopko     auto Tokens = Builder.getDeclarationRange(S);
880be14a22bSIlya Biryukov     if (Tokens.front().kind() == tok::coloncolon) {
881be14a22bSIlya Biryukov       // Handle nested namespace definitions. Those start at '::' token, e.g.
882be14a22bSIlya Biryukov       // namespace a^::b {}
883be14a22bSIlya Biryukov       // FIXME: build corresponding nodes for the name of this namespace.
884be14a22bSIlya Biryukov       return true;
885be14a22bSIlya Biryukov     }
886a711a3a4SMarcel Hlopko     Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition, S);
887be14a22bSIlya Biryukov     return true;
888be14a22bSIlya Biryukov   }
889be14a22bSIlya Biryukov 
8907d382dcdSMarcel Hlopko   bool TraverseParenTypeLoc(ParenTypeLoc L) {
8917d382dcdSMarcel Hlopko     // We reverse order of traversal to get the proper syntax structure.
8927d382dcdSMarcel Hlopko     if (!WalkUpFromParenTypeLoc(L))
8937d382dcdSMarcel Hlopko       return false;
8947d382dcdSMarcel Hlopko     return TraverseTypeLoc(L.getInnerLoc());
8957d382dcdSMarcel Hlopko   }
8967d382dcdSMarcel Hlopko 
8977d382dcdSMarcel Hlopko   bool WalkUpFromParenTypeLoc(ParenTypeLoc L) {
8987d382dcdSMarcel Hlopko     Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
8997d382dcdSMarcel Hlopko     Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
9007d382dcdSMarcel Hlopko     Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getRParenLoc()),
901a711a3a4SMarcel Hlopko                      new (allocator()) syntax::ParenDeclarator, L);
9027d382dcdSMarcel Hlopko     return true;
9037d382dcdSMarcel Hlopko   }
9047d382dcdSMarcel Hlopko 
9057d382dcdSMarcel Hlopko   // Declarator chunks, they are produced by type locs and some clang::Decls.
9067d382dcdSMarcel Hlopko   bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L) {
9077d382dcdSMarcel Hlopko     Builder.markChildToken(L.getLBracketLoc(), syntax::NodeRole::OpenParen);
9087d382dcdSMarcel Hlopko     Builder.markExprChild(L.getSizeExpr(),
9097d382dcdSMarcel Hlopko                           syntax::NodeRole::ArraySubscript_sizeExpression);
9107d382dcdSMarcel Hlopko     Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen);
9117d382dcdSMarcel Hlopko     Builder.foldNode(Builder.getRange(L.getLBracketLoc(), L.getRBracketLoc()),
912a711a3a4SMarcel Hlopko                      new (allocator()) syntax::ArraySubscript, L);
9137d382dcdSMarcel Hlopko     return true;
9147d382dcdSMarcel Hlopko   }
9157d382dcdSMarcel Hlopko 
9167d382dcdSMarcel Hlopko   bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L) {
9177d382dcdSMarcel Hlopko     Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
918cdce2fe5SMarcel Hlopko     for (auto *P : L.getParams()) {
919cdce2fe5SMarcel Hlopko       Builder.markChild(P, syntax::NodeRole::ParametersAndQualifiers_parameter);
920cdce2fe5SMarcel Hlopko     }
9217d382dcdSMarcel Hlopko     Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
9227d382dcdSMarcel Hlopko     Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()),
923a711a3a4SMarcel Hlopko                      new (allocator()) syntax::ParametersAndQualifiers, L);
9247d382dcdSMarcel Hlopko     return true;
9257d382dcdSMarcel Hlopko   }
9267d382dcdSMarcel Hlopko 
9277d382dcdSMarcel Hlopko   bool WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L) {
9287d382dcdSMarcel Hlopko     if (!L.getTypePtr()->hasTrailingReturn())
9297d382dcdSMarcel Hlopko       return WalkUpFromFunctionTypeLoc(L);
9307d382dcdSMarcel Hlopko 
931cdce2fe5SMarcel Hlopko     auto *TrailingReturnTokens = BuildTrailingReturn(L);
9327d382dcdSMarcel Hlopko     // Finish building the node for parameters.
9337d382dcdSMarcel Hlopko     Builder.markChild(TrailingReturnTokens,
9347d382dcdSMarcel Hlopko                       syntax::NodeRole::ParametersAndQualifiers_trailingReturn);
9357d382dcdSMarcel Hlopko     return WalkUpFromFunctionTypeLoc(L);
9367d382dcdSMarcel Hlopko   }
9377d382dcdSMarcel Hlopko 
9387d382dcdSMarcel Hlopko   bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) {
9397d382dcdSMarcel Hlopko     auto SR = L.getLocalSourceRange();
940a711a3a4SMarcel Hlopko     Builder.foldNode(Builder.getRange(SR),
941a711a3a4SMarcel Hlopko                      new (allocator()) syntax::MemberPointer, L);
9427d382dcdSMarcel Hlopko     return true;
9437d382dcdSMarcel Hlopko   }
9447d382dcdSMarcel Hlopko 
94558fa50f4SIlya Biryukov   // The code below is very regular, it could even be generated with some
94658fa50f4SIlya Biryukov   // preprocessor magic. We merely assign roles to the corresponding children
94758fa50f4SIlya Biryukov   // and fold resulting nodes.
94858fa50f4SIlya Biryukov   bool WalkUpFromDeclStmt(DeclStmt *S) {
94958fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
950a711a3a4SMarcel Hlopko                      new (allocator()) syntax::DeclarationStatement, S);
95158fa50f4SIlya Biryukov     return true;
95258fa50f4SIlya Biryukov   }
95358fa50f4SIlya Biryukov 
95458fa50f4SIlya Biryukov   bool WalkUpFromNullStmt(NullStmt *S) {
95558fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
956a711a3a4SMarcel Hlopko                      new (allocator()) syntax::EmptyStatement, S);
95758fa50f4SIlya Biryukov     return true;
95858fa50f4SIlya Biryukov   }
95958fa50f4SIlya Biryukov 
96058fa50f4SIlya Biryukov   bool WalkUpFromSwitchStmt(SwitchStmt *S) {
961def65bb4SIlya Biryukov     Builder.markChildToken(S->getSwitchLoc(),
96258fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
96358fa50f4SIlya Biryukov     Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
96458fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
965a711a3a4SMarcel Hlopko                      new (allocator()) syntax::SwitchStatement, S);
96658fa50f4SIlya Biryukov     return true;
96758fa50f4SIlya Biryukov   }
96858fa50f4SIlya Biryukov 
96958fa50f4SIlya Biryukov   bool WalkUpFromCaseStmt(CaseStmt *S) {
970def65bb4SIlya Biryukov     Builder.markChildToken(S->getKeywordLoc(),
97158fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
97258fa50f4SIlya Biryukov     Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseStatement_value);
97358fa50f4SIlya Biryukov     Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
97458fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
975a711a3a4SMarcel Hlopko                      new (allocator()) syntax::CaseStatement, S);
97658fa50f4SIlya Biryukov     return true;
97758fa50f4SIlya Biryukov   }
97858fa50f4SIlya Biryukov 
97958fa50f4SIlya Biryukov   bool WalkUpFromDefaultStmt(DefaultStmt *S) {
980def65bb4SIlya Biryukov     Builder.markChildToken(S->getKeywordLoc(),
98158fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
98258fa50f4SIlya Biryukov     Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
98358fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
984a711a3a4SMarcel Hlopko                      new (allocator()) syntax::DefaultStatement, S);
98558fa50f4SIlya Biryukov     return true;
98658fa50f4SIlya Biryukov   }
98758fa50f4SIlya Biryukov 
98858fa50f4SIlya Biryukov   bool WalkUpFromIfStmt(IfStmt *S) {
989def65bb4SIlya Biryukov     Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword);
99058fa50f4SIlya Biryukov     Builder.markStmtChild(S->getThen(),
99158fa50f4SIlya Biryukov                           syntax::NodeRole::IfStatement_thenStatement);
992def65bb4SIlya Biryukov     Builder.markChildToken(S->getElseLoc(),
99358fa50f4SIlya Biryukov                            syntax::NodeRole::IfStatement_elseKeyword);
99458fa50f4SIlya Biryukov     Builder.markStmtChild(S->getElse(),
99558fa50f4SIlya Biryukov                           syntax::NodeRole::IfStatement_elseStatement);
99658fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
997a711a3a4SMarcel Hlopko                      new (allocator()) syntax::IfStatement, S);
99858fa50f4SIlya Biryukov     return true;
99958fa50f4SIlya Biryukov   }
100058fa50f4SIlya Biryukov 
100158fa50f4SIlya Biryukov   bool WalkUpFromForStmt(ForStmt *S) {
1002def65bb4SIlya Biryukov     Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
100358fa50f4SIlya Biryukov     Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
100458fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
1005a711a3a4SMarcel Hlopko                      new (allocator()) syntax::ForStatement, S);
100658fa50f4SIlya Biryukov     return true;
100758fa50f4SIlya Biryukov   }
100858fa50f4SIlya Biryukov 
100958fa50f4SIlya Biryukov   bool WalkUpFromWhileStmt(WhileStmt *S) {
1010def65bb4SIlya Biryukov     Builder.markChildToken(S->getWhileLoc(),
101158fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
101258fa50f4SIlya Biryukov     Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
101358fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
1014a711a3a4SMarcel Hlopko                      new (allocator()) syntax::WhileStatement, S);
101558fa50f4SIlya Biryukov     return true;
101658fa50f4SIlya Biryukov   }
101758fa50f4SIlya Biryukov 
101858fa50f4SIlya Biryukov   bool WalkUpFromContinueStmt(ContinueStmt *S) {
1019def65bb4SIlya Biryukov     Builder.markChildToken(S->getContinueLoc(),
102058fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
102158fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
1022a711a3a4SMarcel Hlopko                      new (allocator()) syntax::ContinueStatement, S);
102358fa50f4SIlya Biryukov     return true;
102458fa50f4SIlya Biryukov   }
102558fa50f4SIlya Biryukov 
102658fa50f4SIlya Biryukov   bool WalkUpFromBreakStmt(BreakStmt *S) {
1027def65bb4SIlya Biryukov     Builder.markChildToken(S->getBreakLoc(),
102858fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
102958fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
1030a711a3a4SMarcel Hlopko                      new (allocator()) syntax::BreakStatement, S);
103158fa50f4SIlya Biryukov     return true;
103258fa50f4SIlya Biryukov   }
103358fa50f4SIlya Biryukov 
103458fa50f4SIlya Biryukov   bool WalkUpFromReturnStmt(ReturnStmt *S) {
1035def65bb4SIlya Biryukov     Builder.markChildToken(S->getReturnLoc(),
103658fa50f4SIlya Biryukov                            syntax::NodeRole::IntroducerKeyword);
103758fa50f4SIlya Biryukov     Builder.markExprChild(S->getRetValue(),
103858fa50f4SIlya Biryukov                           syntax::NodeRole::ReturnStatement_value);
103958fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
1040a711a3a4SMarcel Hlopko                      new (allocator()) syntax::ReturnStatement, S);
104158fa50f4SIlya Biryukov     return true;
104258fa50f4SIlya Biryukov   }
104358fa50f4SIlya Biryukov 
104458fa50f4SIlya Biryukov   bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) {
1045def65bb4SIlya Biryukov     Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
104658fa50f4SIlya Biryukov     Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
104758fa50f4SIlya Biryukov     Builder.foldNode(Builder.getStmtRange(S),
1048a711a3a4SMarcel Hlopko                      new (allocator()) syntax::RangeBasedForStatement, S);
104958fa50f4SIlya Biryukov     return true;
105058fa50f4SIlya Biryukov   }
105158fa50f4SIlya Biryukov 
1052be14a22bSIlya Biryukov   bool WalkUpFromEmptyDecl(EmptyDecl *S) {
1053cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1054a711a3a4SMarcel Hlopko                      new (allocator()) syntax::EmptyDeclaration, S);
1055be14a22bSIlya Biryukov     return true;
1056be14a22bSIlya Biryukov   }
1057be14a22bSIlya Biryukov 
1058be14a22bSIlya Biryukov   bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) {
1059be14a22bSIlya Biryukov     Builder.markExprChild(S->getAssertExpr(),
1060be14a22bSIlya Biryukov                           syntax::NodeRole::StaticAssertDeclaration_condition);
1061be14a22bSIlya Biryukov     Builder.markExprChild(S->getMessage(),
1062be14a22bSIlya Biryukov                           syntax::NodeRole::StaticAssertDeclaration_message);
1063cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1064a711a3a4SMarcel Hlopko                      new (allocator()) syntax::StaticAssertDeclaration, S);
1065be14a22bSIlya Biryukov     return true;
1066be14a22bSIlya Biryukov   }
1067be14a22bSIlya Biryukov 
1068be14a22bSIlya Biryukov   bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) {
1069cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1070a711a3a4SMarcel Hlopko                      new (allocator()) syntax::LinkageSpecificationDeclaration,
1071a711a3a4SMarcel Hlopko                      S);
1072be14a22bSIlya Biryukov     return true;
1073be14a22bSIlya Biryukov   }
1074be14a22bSIlya Biryukov 
1075be14a22bSIlya Biryukov   bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) {
1076cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1077a711a3a4SMarcel Hlopko                      new (allocator()) syntax::NamespaceAliasDefinition, S);
1078be14a22bSIlya Biryukov     return true;
1079be14a22bSIlya Biryukov   }
1080be14a22bSIlya Biryukov 
1081be14a22bSIlya Biryukov   bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) {
1082cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1083a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UsingNamespaceDirective, S);
1084be14a22bSIlya Biryukov     return true;
1085be14a22bSIlya Biryukov   }
1086be14a22bSIlya Biryukov 
1087be14a22bSIlya Biryukov   bool WalkUpFromUsingDecl(UsingDecl *S) {
1088cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1089a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UsingDeclaration, S);
1090be14a22bSIlya Biryukov     return true;
1091be14a22bSIlya Biryukov   }
1092be14a22bSIlya Biryukov 
1093be14a22bSIlya Biryukov   bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) {
1094cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1095a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UsingDeclaration, S);
1096be14a22bSIlya Biryukov     return true;
1097be14a22bSIlya Biryukov   }
1098be14a22bSIlya Biryukov 
1099be14a22bSIlya Biryukov   bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) {
1100cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1101a711a3a4SMarcel Hlopko                      new (allocator()) syntax::UsingDeclaration, S);
1102be14a22bSIlya Biryukov     return true;
1103be14a22bSIlya Biryukov   }
1104be14a22bSIlya Biryukov 
1105be14a22bSIlya Biryukov   bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) {
1106cdce2fe5SMarcel Hlopko     Builder.foldNode(Builder.getDeclarationRange(S),
1107a711a3a4SMarcel Hlopko                      new (allocator()) syntax::TypeAliasDeclaration, S);
1108be14a22bSIlya Biryukov     return true;
1109be14a22bSIlya Biryukov   }
1110be14a22bSIlya Biryukov 
11119b3f38f9SIlya Biryukov private:
1112cdce2fe5SMarcel Hlopko   template <class T> SourceLocation getQualifiedNameStart(T *D) {
1113cdce2fe5SMarcel Hlopko     static_assert((std::is_base_of<DeclaratorDecl, T>::value ||
1114cdce2fe5SMarcel Hlopko                    std::is_base_of<TypedefNameDecl, T>::value),
1115cdce2fe5SMarcel Hlopko                   "only DeclaratorDecl and TypedefNameDecl are supported.");
1116cdce2fe5SMarcel Hlopko 
1117cdce2fe5SMarcel Hlopko     auto DN = D->getDeclName();
1118cdce2fe5SMarcel Hlopko     bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo();
1119cdce2fe5SMarcel Hlopko     if (IsAnonymous)
1120cdce2fe5SMarcel Hlopko       return SourceLocation();
1121cdce2fe5SMarcel Hlopko 
1122cdce2fe5SMarcel Hlopko     if (const auto *DD = llvm::dyn_cast<DeclaratorDecl>(D)) {
1123cdce2fe5SMarcel Hlopko       if (DD->getQualifierLoc()) {
1124cdce2fe5SMarcel Hlopko         return DD->getQualifierLoc().getBeginLoc();
1125cdce2fe5SMarcel Hlopko       }
1126cdce2fe5SMarcel Hlopko     }
1127cdce2fe5SMarcel Hlopko 
1128cdce2fe5SMarcel Hlopko     return D->getLocation();
1129cdce2fe5SMarcel Hlopko   }
1130cdce2fe5SMarcel Hlopko 
1131cdce2fe5SMarcel Hlopko   SourceRange getInitializerRange(Decl *D) {
1132cdce2fe5SMarcel Hlopko     if (auto *V = llvm::dyn_cast<VarDecl>(D)) {
1133cdce2fe5SMarcel Hlopko       auto *I = V->getInit();
1134cdce2fe5SMarcel Hlopko       // Initializers in range-based-for are not part of the declarator
1135cdce2fe5SMarcel Hlopko       if (I && !V->isCXXForRangeDecl())
1136cdce2fe5SMarcel Hlopko         return I->getSourceRange();
1137cdce2fe5SMarcel Hlopko     }
1138cdce2fe5SMarcel Hlopko 
1139cdce2fe5SMarcel Hlopko     return SourceRange();
1140cdce2fe5SMarcel Hlopko   }
1141cdce2fe5SMarcel Hlopko 
1142cdce2fe5SMarcel Hlopko   /// Folds SimpleDeclarator node (if present) and in case this is the last
1143cdce2fe5SMarcel Hlopko   /// declarator in the chain it also folds SimpleDeclaration node.
1144cdce2fe5SMarcel Hlopko   template <class T> bool processDeclaratorAndDeclaration(T *D) {
1145cdce2fe5SMarcel Hlopko     SourceRange Initializer = getInitializerRange(D);
1146cdce2fe5SMarcel Hlopko     auto Range = getDeclaratorRange(Builder.sourceManager(),
1147cdce2fe5SMarcel Hlopko                                     D->getTypeSourceInfo()->getTypeLoc(),
1148cdce2fe5SMarcel Hlopko                                     getQualifiedNameStart(D), Initializer);
1149cdce2fe5SMarcel Hlopko 
1150cdce2fe5SMarcel Hlopko     // There doesn't have to be a declarator (e.g. `void foo(int)` only has
1151cdce2fe5SMarcel Hlopko     // declaration, but no declarator).
1152cdce2fe5SMarcel Hlopko     if (Range.getBegin().isValid()) {
1153cdce2fe5SMarcel Hlopko       auto *N = new (allocator()) syntax::SimpleDeclarator;
1154cdce2fe5SMarcel Hlopko       Builder.foldNode(Builder.getRange(Range), N, nullptr);
1155cdce2fe5SMarcel Hlopko       Builder.markChild(N, syntax::NodeRole::SimpleDeclaration_declarator);
1156cdce2fe5SMarcel Hlopko     }
1157cdce2fe5SMarcel Hlopko 
1158cdce2fe5SMarcel Hlopko     if (Builder.isResponsibleForCreatingDeclaration(D)) {
1159cdce2fe5SMarcel Hlopko       Builder.foldNode(Builder.getDeclarationRange(D),
1160cdce2fe5SMarcel Hlopko                        new (allocator()) syntax::SimpleDeclaration, D);
1161cdce2fe5SMarcel Hlopko     }
1162cdce2fe5SMarcel Hlopko     return true;
1163cdce2fe5SMarcel Hlopko   }
1164cdce2fe5SMarcel Hlopko 
11657d382dcdSMarcel Hlopko   /// Returns the range of the built node.
1166a711a3a4SMarcel Hlopko   syntax::TrailingReturnType *BuildTrailingReturn(FunctionProtoTypeLoc L) {
11677d382dcdSMarcel Hlopko     assert(L.getTypePtr()->hasTrailingReturn());
11687d382dcdSMarcel Hlopko 
11697d382dcdSMarcel Hlopko     auto ReturnedType = L.getReturnLoc();
11707d382dcdSMarcel Hlopko     // Build node for the declarator, if any.
11717d382dcdSMarcel Hlopko     auto ReturnDeclaratorRange =
11727d382dcdSMarcel Hlopko         getDeclaratorRange(this->Builder.sourceManager(), ReturnedType,
11737d382dcdSMarcel Hlopko                            /*Name=*/SourceLocation(),
11747d382dcdSMarcel Hlopko                            /*Initializer=*/SourceLocation());
1175a711a3a4SMarcel Hlopko     syntax::SimpleDeclarator *ReturnDeclarator = nullptr;
11767d382dcdSMarcel Hlopko     if (ReturnDeclaratorRange.isValid()) {
1177a711a3a4SMarcel Hlopko       ReturnDeclarator = new (allocator()) syntax::SimpleDeclarator;
1178a711a3a4SMarcel Hlopko       Builder.foldNode(Builder.getRange(ReturnDeclaratorRange),
1179a711a3a4SMarcel Hlopko                        ReturnDeclarator, nullptr);
11807d382dcdSMarcel Hlopko     }
11817d382dcdSMarcel Hlopko 
11827d382dcdSMarcel Hlopko     // Build node for trailing return type.
1183a711a3a4SMarcel Hlopko     auto Return = Builder.getRange(ReturnedType.getSourceRange());
11847d382dcdSMarcel Hlopko     const auto *Arrow = Return.begin() - 1;
11857d382dcdSMarcel Hlopko     assert(Arrow->kind() == tok::arrow);
11867d382dcdSMarcel Hlopko     auto Tokens = llvm::makeArrayRef(Arrow, Return.end());
118742f6fec3SEduardo Caldas     Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken);
1188a711a3a4SMarcel Hlopko     if (ReturnDeclarator)
1189a711a3a4SMarcel Hlopko       Builder.markChild(ReturnDeclarator,
11907d382dcdSMarcel Hlopko                         syntax::NodeRole::TrailingReturnType_declarator);
1191a711a3a4SMarcel Hlopko     auto *R = new (allocator()) syntax::TrailingReturnType;
1192cdce2fe5SMarcel Hlopko     Builder.foldNode(Tokens, R, L);
1193a711a3a4SMarcel Hlopko     return R;
11947d382dcdSMarcel Hlopko   }
119588bf9b3dSMarcel Hlopko 
1196a711a3a4SMarcel Hlopko   void foldExplicitTemplateInstantiation(
1197a711a3a4SMarcel Hlopko       ArrayRef<syntax::Token> Range, const syntax::Token *ExternKW,
119888bf9b3dSMarcel Hlopko       const syntax::Token *TemplateKW,
1199a711a3a4SMarcel Hlopko       syntax::SimpleDeclaration *InnerDeclaration, Decl *From) {
120088bf9b3dSMarcel Hlopko     assert(!ExternKW || ExternKW->kind() == tok::kw_extern);
120188bf9b3dSMarcel Hlopko     assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
120242f6fec3SEduardo Caldas     Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword);
120388bf9b3dSMarcel Hlopko     Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
120488bf9b3dSMarcel Hlopko     Builder.markChild(
120588bf9b3dSMarcel Hlopko         InnerDeclaration,
120688bf9b3dSMarcel Hlopko         syntax::NodeRole::ExplicitTemplateInstantiation_declaration);
1207a711a3a4SMarcel Hlopko     Builder.foldNode(
1208a711a3a4SMarcel Hlopko         Range, new (allocator()) syntax::ExplicitTemplateInstantiation, From);
120988bf9b3dSMarcel Hlopko   }
121088bf9b3dSMarcel Hlopko 
1211a711a3a4SMarcel Hlopko   syntax::TemplateDeclaration *foldTemplateDeclaration(
1212a711a3a4SMarcel Hlopko       ArrayRef<syntax::Token> Range, const syntax::Token *TemplateKW,
1213a711a3a4SMarcel Hlopko       ArrayRef<syntax::Token> TemplatedDeclaration, Decl *From) {
121488bf9b3dSMarcel Hlopko     assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
121588bf9b3dSMarcel Hlopko     Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1216a711a3a4SMarcel Hlopko 
1217a711a3a4SMarcel Hlopko     auto *N = new (allocator()) syntax::TemplateDeclaration;
1218a711a3a4SMarcel Hlopko     Builder.foldNode(Range, N, From);
1219cdce2fe5SMarcel Hlopko     Builder.markChild(N, syntax::NodeRole::TemplateDeclaration_declaration);
1220a711a3a4SMarcel Hlopko     return N;
122188bf9b3dSMarcel Hlopko   }
122288bf9b3dSMarcel Hlopko 
12239b3f38f9SIlya Biryukov   /// A small helper to save some typing.
12249b3f38f9SIlya Biryukov   llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); }
12259b3f38f9SIlya Biryukov 
12269b3f38f9SIlya Biryukov   syntax::TreeBuilder &Builder;
12279b3f38f9SIlya Biryukov   const LangOptions &LangOpts;
12289b3f38f9SIlya Biryukov };
12299b3f38f9SIlya Biryukov } // namespace
12309b3f38f9SIlya Biryukov 
12317d382dcdSMarcel Hlopko void syntax::TreeBuilder::noticeDeclWithoutSemicolon(Decl *D) {
1232e702bdb8SIlya Biryukov   DeclsWithoutSemicolons.insert(D);
1233e702bdb8SIlya Biryukov }
1234e702bdb8SIlya Biryukov 
1235def65bb4SIlya Biryukov void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) {
12369b3f38f9SIlya Biryukov   if (Loc.isInvalid())
12379b3f38f9SIlya Biryukov     return;
12389b3f38f9SIlya Biryukov   Pending.assignRole(*findToken(Loc), Role);
12399b3f38f9SIlya Biryukov }
12409b3f38f9SIlya Biryukov 
12417d382dcdSMarcel Hlopko void syntax::TreeBuilder::markChildToken(const syntax::Token *T, NodeRole R) {
12427d382dcdSMarcel Hlopko   if (!T)
12437d382dcdSMarcel Hlopko     return;
12447d382dcdSMarcel Hlopko   Pending.assignRole(*T, R);
12457d382dcdSMarcel Hlopko }
12467d382dcdSMarcel Hlopko 
1247a711a3a4SMarcel Hlopko void syntax::TreeBuilder::markChild(syntax::Node *N, NodeRole R) {
1248a711a3a4SMarcel Hlopko   assert(N);
1249a711a3a4SMarcel Hlopko   setRole(N, R);
1250a711a3a4SMarcel Hlopko }
1251a711a3a4SMarcel Hlopko 
1252a711a3a4SMarcel Hlopko void syntax::TreeBuilder::markChild(ASTPtr N, NodeRole R) {
1253a711a3a4SMarcel Hlopko   auto *SN = Mapping.find(N);
1254a711a3a4SMarcel Hlopko   assert(SN != nullptr);
1255a711a3a4SMarcel Hlopko   setRole(SN, R);
12567d382dcdSMarcel Hlopko }
12577d382dcdSMarcel Hlopko 
125858fa50f4SIlya Biryukov void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
125958fa50f4SIlya Biryukov   if (!Child)
126058fa50f4SIlya Biryukov     return;
126158fa50f4SIlya Biryukov 
1262b34b7691SDmitri Gribenko   syntax::Tree *ChildNode;
1263b34b7691SDmitri Gribenko   if (Expr *ChildExpr = dyn_cast<Expr>(Child)) {
126458fa50f4SIlya Biryukov     // This is an expression in a statement position, consume the trailing
126558fa50f4SIlya Biryukov     // semicolon and form an 'ExpressionStatement' node.
1266b34b7691SDmitri Gribenko     markExprChild(ChildExpr, NodeRole::ExpressionStatement_expression);
1267a711a3a4SMarcel Hlopko     ChildNode = new (allocator()) syntax::ExpressionStatement;
1268a711a3a4SMarcel Hlopko     // (!) 'getStmtRange()' ensures this covers a trailing semicolon.
1269a711a3a4SMarcel Hlopko     Pending.foldChildren(Arena, getStmtRange(Child), ChildNode);
1270b34b7691SDmitri Gribenko   } else {
1271b34b7691SDmitri Gribenko     ChildNode = Mapping.find(Child);
127258fa50f4SIlya Biryukov   }
1273b34b7691SDmitri Gribenko   assert(ChildNode != nullptr);
1274a711a3a4SMarcel Hlopko   setRole(ChildNode, Role);
127558fa50f4SIlya Biryukov }
127658fa50f4SIlya Biryukov 
127758fa50f4SIlya Biryukov void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
1278be14a22bSIlya Biryukov   if (!Child)
1279be14a22bSIlya Biryukov     return;
1280a711a3a4SMarcel Hlopko   Child = Child->IgnoreImplicit();
1281be14a22bSIlya Biryukov 
1282a711a3a4SMarcel Hlopko   syntax::Tree *ChildNode = Mapping.find(Child);
1283a711a3a4SMarcel Hlopko   assert(ChildNode != nullptr);
1284a711a3a4SMarcel Hlopko   setRole(ChildNode, Role);
128558fa50f4SIlya Biryukov }
128658fa50f4SIlya Biryukov 
12879b3f38f9SIlya Biryukov const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
128888bf9b3dSMarcel Hlopko   if (L.isInvalid())
128988bf9b3dSMarcel Hlopko     return nullptr;
1290c1bbefefSIlya Biryukov   auto It = LocationToToken.find(L.getRawEncoding());
1291c1bbefefSIlya Biryukov   assert(It != LocationToToken.end());
1292c1bbefefSIlya Biryukov   return It->second;
12939b3f38f9SIlya Biryukov }
12949b3f38f9SIlya Biryukov 
12959b3f38f9SIlya Biryukov syntax::TranslationUnit *
12969b3f38f9SIlya Biryukov syntax::buildSyntaxTree(Arena &A, const TranslationUnitDecl &TU) {
12979b3f38f9SIlya Biryukov   TreeBuilder Builder(A);
12989b3f38f9SIlya Biryukov   BuildTreeVisitor(TU.getASTContext(), Builder).TraverseAST(TU.getASTContext());
12999b3f38f9SIlya Biryukov   return std::move(Builder).finalize();
13009b3f38f9SIlya Biryukov }
1301