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" 9*7d382dcdSMarcel Hlopko #include "clang/AST/ASTFwd.h" 10e702bdb8SIlya Biryukov #include "clang/AST/Decl.h" 11e702bdb8SIlya Biryukov #include "clang/AST/DeclBase.h" 12*7d382dcdSMarcel Hlopko #include "clang/AST/DeclCXX.h" 13*7d382dcdSMarcel Hlopko #include "clang/AST/DeclarationName.h" 149b3f38f9SIlya Biryukov #include "clang/AST/RecursiveASTVisitor.h" 159b3f38f9SIlya Biryukov #include "clang/AST/Stmt.h" 16*7d382dcdSMarcel Hlopko #include "clang/AST/TypeLoc.h" 17*7d382dcdSMarcel Hlopko #include "clang/AST/TypeLocVisitor.h" 189b3f38f9SIlya Biryukov #include "clang/Basic/LLVM.h" 199b3f38f9SIlya Biryukov #include "clang/Basic/SourceLocation.h" 209b3f38f9SIlya Biryukov #include "clang/Basic/SourceManager.h" 219b3f38f9SIlya Biryukov #include "clang/Basic/TokenKinds.h" 229b3f38f9SIlya Biryukov #include "clang/Lex/Lexer.h" 239b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/Nodes.h" 249b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/Tokens.h" 259b3f38f9SIlya Biryukov #include "clang/Tooling/Syntax/Tree.h" 269b3f38f9SIlya Biryukov #include "llvm/ADT/ArrayRef.h" 279b3f38f9SIlya Biryukov #include "llvm/ADT/STLExtras.h" 28*7d382dcdSMarcel Hlopko #include "llvm/ADT/ScopeExit.h" 299b3f38f9SIlya Biryukov #include "llvm/ADT/SmallVector.h" 309b3f38f9SIlya Biryukov #include "llvm/Support/Allocator.h" 319b3f38f9SIlya Biryukov #include "llvm/Support/Casting.h" 3296065cf7SIlya Biryukov #include "llvm/Support/Compiler.h" 339b3f38f9SIlya Biryukov #include "llvm/Support/FormatVariadic.h" 341ad15046SIlya Biryukov #include "llvm/Support/MemoryBuffer.h" 359b3f38f9SIlya Biryukov #include "llvm/Support/raw_ostream.h" 369b3f38f9SIlya Biryukov #include <map> 379b3f38f9SIlya Biryukov 389b3f38f9SIlya Biryukov using namespace clang; 399b3f38f9SIlya Biryukov 4096065cf7SIlya Biryukov LLVM_ATTRIBUTE_UNUSED 4158fa50f4SIlya Biryukov static bool isImplicitExpr(clang::Expr *E) { return E->IgnoreImplicit() != E; } 4258fa50f4SIlya Biryukov 43*7d382dcdSMarcel Hlopko static SourceLocation getQualifiedNameStart(DeclaratorDecl *D) { 44*7d382dcdSMarcel Hlopko auto DN = D->getDeclName(); 45*7d382dcdSMarcel Hlopko bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo(); 46*7d382dcdSMarcel Hlopko if (IsAnonymous) 47*7d382dcdSMarcel Hlopko return SourceLocation(); 48*7d382dcdSMarcel Hlopko return D->getQualifierLoc() ? D->getQualifierLoc().getBeginLoc() 49*7d382dcdSMarcel Hlopko : D->getLocation(); 50*7d382dcdSMarcel Hlopko } 51*7d382dcdSMarcel Hlopko 52*7d382dcdSMarcel Hlopko namespace { 53*7d382dcdSMarcel Hlopko /// Get start location of the Declarator from the TypeLoc. 54*7d382dcdSMarcel Hlopko /// E.g.: 55*7d382dcdSMarcel Hlopko /// loc of `(` in `int (a)` 56*7d382dcdSMarcel Hlopko /// loc of `*` in `int *(a)` 57*7d382dcdSMarcel Hlopko /// loc of the first `(` in `int (*a)(int)` 58*7d382dcdSMarcel Hlopko /// loc of the `*` in `int *(a)(int)` 59*7d382dcdSMarcel Hlopko /// loc of the first `*` in `const int *const *volatile a;` 60*7d382dcdSMarcel Hlopko /// 61*7d382dcdSMarcel Hlopko /// It is non-trivial to get the start location because TypeLocs are stored 62*7d382dcdSMarcel Hlopko /// inside out. In the example above `*volatile` is the TypeLoc returned 63*7d382dcdSMarcel Hlopko /// by `Decl.getTypeSourceInfo()`, and `*const` is what `.getPointeeLoc()` 64*7d382dcdSMarcel Hlopko /// returns. 65*7d382dcdSMarcel Hlopko struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> { 66*7d382dcdSMarcel Hlopko SourceLocation VisitParenTypeLoc(ParenTypeLoc T) { 67*7d382dcdSMarcel Hlopko auto L = Visit(T.getInnerLoc()); 68*7d382dcdSMarcel Hlopko if (L.isValid()) 69*7d382dcdSMarcel Hlopko return L; 70*7d382dcdSMarcel Hlopko return T.getLParenLoc(); 71*7d382dcdSMarcel Hlopko } 72*7d382dcdSMarcel Hlopko 73*7d382dcdSMarcel Hlopko // Types spelled in the prefix part of the declarator. 74*7d382dcdSMarcel Hlopko SourceLocation VisitPointerTypeLoc(PointerTypeLoc T) { 75*7d382dcdSMarcel Hlopko return HandlePointer(T); 76*7d382dcdSMarcel Hlopko } 77*7d382dcdSMarcel Hlopko 78*7d382dcdSMarcel Hlopko SourceLocation VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) { 79*7d382dcdSMarcel Hlopko return HandlePointer(T); 80*7d382dcdSMarcel Hlopko } 81*7d382dcdSMarcel Hlopko 82*7d382dcdSMarcel Hlopko SourceLocation VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) { 83*7d382dcdSMarcel Hlopko return HandlePointer(T); 84*7d382dcdSMarcel Hlopko } 85*7d382dcdSMarcel Hlopko 86*7d382dcdSMarcel Hlopko SourceLocation VisitReferenceTypeLoc(ReferenceTypeLoc T) { 87*7d382dcdSMarcel Hlopko return HandlePointer(T); 88*7d382dcdSMarcel Hlopko } 89*7d382dcdSMarcel Hlopko 90*7d382dcdSMarcel Hlopko SourceLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc T) { 91*7d382dcdSMarcel Hlopko return HandlePointer(T); 92*7d382dcdSMarcel Hlopko } 93*7d382dcdSMarcel Hlopko 94*7d382dcdSMarcel Hlopko // All other cases are not important, as they are either part of declaration 95*7d382dcdSMarcel Hlopko // specifiers (e.g. inheritors of TypeSpecTypeLoc) or introduce modifiers on 96*7d382dcdSMarcel Hlopko // existing declarators (e.g. QualifiedTypeLoc). They cannot start the 97*7d382dcdSMarcel Hlopko // declarator themselves, but their underlying type can. 98*7d382dcdSMarcel Hlopko SourceLocation VisitTypeLoc(TypeLoc T) { 99*7d382dcdSMarcel Hlopko auto N = T.getNextTypeLoc(); 100*7d382dcdSMarcel Hlopko if (!N) 101*7d382dcdSMarcel Hlopko return SourceLocation(); 102*7d382dcdSMarcel Hlopko return Visit(N); 103*7d382dcdSMarcel Hlopko } 104*7d382dcdSMarcel Hlopko 105*7d382dcdSMarcel Hlopko SourceLocation VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc T) { 106*7d382dcdSMarcel Hlopko if (T.getTypePtr()->hasTrailingReturn()) 107*7d382dcdSMarcel Hlopko return SourceLocation(); // avoid recursing into the suffix of declarator. 108*7d382dcdSMarcel Hlopko return VisitTypeLoc(T); 109*7d382dcdSMarcel Hlopko } 110*7d382dcdSMarcel Hlopko 111*7d382dcdSMarcel Hlopko private: 112*7d382dcdSMarcel Hlopko template <class PtrLoc> SourceLocation HandlePointer(PtrLoc T) { 113*7d382dcdSMarcel Hlopko auto L = Visit(T.getPointeeLoc()); 114*7d382dcdSMarcel Hlopko if (L.isValid()) 115*7d382dcdSMarcel Hlopko return L; 116*7d382dcdSMarcel Hlopko return T.getLocalSourceRange().getBegin(); 117*7d382dcdSMarcel Hlopko } 118*7d382dcdSMarcel Hlopko }; 119*7d382dcdSMarcel Hlopko } // namespace 120*7d382dcdSMarcel Hlopko 121*7d382dcdSMarcel Hlopko /// Gets the range of declarator as defined by the C++ grammar. E.g. 122*7d382dcdSMarcel Hlopko /// `int a;` -> range of `a`, 123*7d382dcdSMarcel Hlopko /// `int *a;` -> range of `*a`, 124*7d382dcdSMarcel Hlopko /// `int a[10];` -> range of `a[10]`, 125*7d382dcdSMarcel Hlopko /// `int a[1][2][3];` -> range of `a[1][2][3]`, 126*7d382dcdSMarcel Hlopko /// `int *a = nullptr` -> range of `*a = nullptr`. 127*7d382dcdSMarcel Hlopko /// FIMXE: \p Name must be a source range, e.g. for `operator+`. 128*7d382dcdSMarcel Hlopko static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, 129*7d382dcdSMarcel Hlopko SourceLocation Name, 130*7d382dcdSMarcel Hlopko SourceRange Initializer) { 131*7d382dcdSMarcel Hlopko SourceLocation Start = GetStartLoc().Visit(T); 132*7d382dcdSMarcel Hlopko SourceLocation End = T.getSourceRange().getEnd(); 133*7d382dcdSMarcel Hlopko assert(End.isValid()); 134*7d382dcdSMarcel Hlopko if (Name.isValid()) { 135*7d382dcdSMarcel Hlopko if (Start.isInvalid()) 136*7d382dcdSMarcel Hlopko Start = Name; 137*7d382dcdSMarcel Hlopko if (SM.isBeforeInTranslationUnit(End, Name)) 138*7d382dcdSMarcel Hlopko End = Name; 139*7d382dcdSMarcel Hlopko } 140*7d382dcdSMarcel Hlopko if (Initializer.isValid()) { 141*7d382dcdSMarcel Hlopko assert(SM.isBeforeInTranslationUnit(End, Initializer.getEnd())); 142*7d382dcdSMarcel Hlopko End = Initializer.getEnd(); 143*7d382dcdSMarcel Hlopko } 144*7d382dcdSMarcel Hlopko return SourceRange(Start, End); 145*7d382dcdSMarcel Hlopko } 146*7d382dcdSMarcel Hlopko 1479b3f38f9SIlya Biryukov /// A helper class for constructing the syntax tree while traversing a clang 1489b3f38f9SIlya Biryukov /// AST. 1499b3f38f9SIlya Biryukov /// 1509b3f38f9SIlya Biryukov /// At each point of the traversal we maintain a list of pending nodes. 1519b3f38f9SIlya Biryukov /// Initially all tokens are added as pending nodes. When processing a clang AST 1529b3f38f9SIlya Biryukov /// node, the clients need to: 1539b3f38f9SIlya Biryukov /// - create a corresponding syntax node, 1549b3f38f9SIlya Biryukov /// - assign roles to all pending child nodes with 'markChild' and 1559b3f38f9SIlya Biryukov /// 'markChildToken', 1569b3f38f9SIlya Biryukov /// - replace the child nodes with the new syntax node in the pending list 1579b3f38f9SIlya Biryukov /// with 'foldNode'. 1589b3f38f9SIlya Biryukov /// 1599b3f38f9SIlya Biryukov /// Note that all children are expected to be processed when building a node. 1609b3f38f9SIlya Biryukov /// 1619b3f38f9SIlya Biryukov /// Call finalize() to finish building the tree and consume the root node. 1629b3f38f9SIlya Biryukov class syntax::TreeBuilder { 1639b3f38f9SIlya Biryukov public: 164c1bbefefSIlya Biryukov TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) { 165c1bbefefSIlya Biryukov for (const auto &T : Arena.tokenBuffer().expandedTokens()) 166c1bbefefSIlya Biryukov LocationToToken.insert({T.location().getRawEncoding(), &T}); 167c1bbefefSIlya Biryukov } 1689b3f38f9SIlya Biryukov 1699b3f38f9SIlya Biryukov llvm::BumpPtrAllocator &allocator() { return Arena.allocator(); } 170*7d382dcdSMarcel Hlopko const SourceManager &sourceManager() const { return Arena.sourceManager(); } 1719b3f38f9SIlya Biryukov 1729b3f38f9SIlya Biryukov /// Populate children for \p New node, assuming it covers tokens from \p 1739b3f38f9SIlya Biryukov /// Range. 1749b3f38f9SIlya Biryukov void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New); 1759b3f38f9SIlya Biryukov 176e702bdb8SIlya Biryukov /// Must be called with the range of each `DeclaratorDecl`. Ensures the 177e702bdb8SIlya Biryukov /// corresponding declarator nodes are covered by `SimpleDeclaration`. 178*7d382dcdSMarcel Hlopko void noticeDeclRange(llvm::ArrayRef<syntax::Token> Range); 179e702bdb8SIlya Biryukov 180e702bdb8SIlya Biryukov /// Notifies that we should not consume trailing semicolon when computing 181e702bdb8SIlya Biryukov /// token range of \p D. 182*7d382dcdSMarcel Hlopko void noticeDeclWithoutSemicolon(Decl *D); 183e702bdb8SIlya Biryukov 18458fa50f4SIlya Biryukov /// Mark the \p Child node with a corresponding \p Role. All marked children 18558fa50f4SIlya Biryukov /// should be consumed by foldNode. 186*7d382dcdSMarcel Hlopko /// When called on expressions (clang::Expr is derived from clang::Stmt), 18758fa50f4SIlya Biryukov /// wraps expressions into expression statement. 18858fa50f4SIlya Biryukov void markStmtChild(Stmt *Child, NodeRole Role); 18958fa50f4SIlya Biryukov /// Should be called for expressions in non-statement position to avoid 19058fa50f4SIlya Biryukov /// wrapping into expression statement. 19158fa50f4SIlya Biryukov void markExprChild(Expr *Child, NodeRole Role); 19258fa50f4SIlya Biryukov 1939b3f38f9SIlya Biryukov /// Set role for a token starting at \p Loc. 194def65bb4SIlya Biryukov void markChildToken(SourceLocation Loc, NodeRole R); 195*7d382dcdSMarcel Hlopko /// Set role for \p T. 196*7d382dcdSMarcel Hlopko void markChildToken(const syntax::Token *T, NodeRole R); 197*7d382dcdSMarcel Hlopko 198*7d382dcdSMarcel Hlopko /// Set role for the node that spans exactly \p Range. 199*7d382dcdSMarcel Hlopko void markChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R); 200*7d382dcdSMarcel Hlopko /// Set role for the delayed node that spans exactly \p Range. 201*7d382dcdSMarcel Hlopko void markDelayedChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R); 2029b3f38f9SIlya Biryukov 2039b3f38f9SIlya Biryukov /// Finish building the tree and consume the root node. 2049b3f38f9SIlya Biryukov syntax::TranslationUnit *finalize() && { 2059b3f38f9SIlya Biryukov auto Tokens = Arena.tokenBuffer().expandedTokens(); 206bfbf6b6cSIlya Biryukov assert(!Tokens.empty()); 207bfbf6b6cSIlya Biryukov assert(Tokens.back().kind() == tok::eof); 208bfbf6b6cSIlya Biryukov 2099b3f38f9SIlya Biryukov // Build the root of the tree, consuming all the children. 2101ad15046SIlya Biryukov Pending.foldChildren(Arena, Tokens.drop_back(), 2119b3f38f9SIlya Biryukov new (Arena.allocator()) syntax::TranslationUnit); 2129b3f38f9SIlya Biryukov 2133b929fe7SIlya Biryukov auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).finalize()); 2143b929fe7SIlya Biryukov TU->assertInvariantsRecursive(); 2153b929fe7SIlya Biryukov return TU; 2169b3f38f9SIlya Biryukov } 2179b3f38f9SIlya Biryukov 2189b3f38f9SIlya Biryukov /// getRange() finds the syntax tokens corresponding to the passed source 2199b3f38f9SIlya Biryukov /// locations. 2209b3f38f9SIlya Biryukov /// \p First is the start position of the first token and \p Last is the start 2219b3f38f9SIlya Biryukov /// position of the last token. 2229b3f38f9SIlya Biryukov llvm::ArrayRef<syntax::Token> getRange(SourceLocation First, 2239b3f38f9SIlya Biryukov SourceLocation Last) const { 2249b3f38f9SIlya Biryukov assert(First.isValid()); 2259b3f38f9SIlya Biryukov assert(Last.isValid()); 2269b3f38f9SIlya Biryukov assert(First == Last || 2279b3f38f9SIlya Biryukov Arena.sourceManager().isBeforeInTranslationUnit(First, Last)); 2289b3f38f9SIlya Biryukov return llvm::makeArrayRef(findToken(First), std::next(findToken(Last))); 2299b3f38f9SIlya Biryukov } 2309b3f38f9SIlya Biryukov llvm::ArrayRef<syntax::Token> getRange(const Decl *D) const { 231e702bdb8SIlya Biryukov auto Tokens = getRange(D->getBeginLoc(), D->getEndLoc()); 232e702bdb8SIlya Biryukov if (llvm::isa<NamespaceDecl>(D)) 233e702bdb8SIlya Biryukov return Tokens; 234e702bdb8SIlya Biryukov if (DeclsWithoutSemicolons.count(D)) 235e702bdb8SIlya Biryukov return Tokens; 236e702bdb8SIlya Biryukov // FIXME: do not consume trailing semicolon on function definitions. 237e702bdb8SIlya Biryukov // Most declarations own a semicolon in syntax trees, but not in clang AST. 238e702bdb8SIlya Biryukov return withTrailingSemicolon(Tokens); 2399b3f38f9SIlya Biryukov } 24058fa50f4SIlya Biryukov llvm::ArrayRef<syntax::Token> getExprRange(const Expr *E) const { 24158fa50f4SIlya Biryukov return getRange(E->getBeginLoc(), E->getEndLoc()); 24258fa50f4SIlya Biryukov } 24358fa50f4SIlya Biryukov /// Find the adjusted range for the statement, consuming the trailing 24458fa50f4SIlya Biryukov /// semicolon when needed. 24558fa50f4SIlya Biryukov llvm::ArrayRef<syntax::Token> getStmtRange(const Stmt *S) const { 24658fa50f4SIlya Biryukov auto Tokens = getRange(S->getBeginLoc(), S->getEndLoc()); 24758fa50f4SIlya Biryukov if (isa<CompoundStmt>(S)) 24858fa50f4SIlya Biryukov return Tokens; 24958fa50f4SIlya Biryukov 25058fa50f4SIlya Biryukov // Some statements miss a trailing semicolon, e.g. 'return', 'continue' and 25158fa50f4SIlya Biryukov // all statements that end with those. Consume this semicolon here. 252e702bdb8SIlya Biryukov if (Tokens.back().kind() == tok::semi) 253e702bdb8SIlya Biryukov return Tokens; 254e702bdb8SIlya Biryukov return withTrailingSemicolon(Tokens); 255e702bdb8SIlya Biryukov } 256e702bdb8SIlya Biryukov 257e702bdb8SIlya Biryukov private: 258e702bdb8SIlya Biryukov llvm::ArrayRef<syntax::Token> 259e702bdb8SIlya Biryukov withTrailingSemicolon(llvm::ArrayRef<syntax::Token> Tokens) const { 260e702bdb8SIlya Biryukov assert(!Tokens.empty()); 261e702bdb8SIlya Biryukov assert(Tokens.back().kind() != tok::eof); 262*7d382dcdSMarcel Hlopko // We never consume 'eof', so looking at the next token is ok. 26358fa50f4SIlya Biryukov if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi) 26458fa50f4SIlya Biryukov return llvm::makeArrayRef(Tokens.begin(), Tokens.end() + 1); 26558fa50f4SIlya Biryukov return Tokens; 2669b3f38f9SIlya Biryukov } 2679b3f38f9SIlya Biryukov 2689b3f38f9SIlya Biryukov /// Finds a token starting at \p L. The token must exist. 2699b3f38f9SIlya Biryukov const syntax::Token *findToken(SourceLocation L) const; 2709b3f38f9SIlya Biryukov 2719b3f38f9SIlya Biryukov /// A collection of trees covering the input tokens. 2729b3f38f9SIlya Biryukov /// When created, each tree corresponds to a single token in the file. 2739b3f38f9SIlya Biryukov /// Clients call 'foldChildren' to attach one or more subtrees to a parent 2749b3f38f9SIlya Biryukov /// node and update the list of trees accordingly. 2759b3f38f9SIlya Biryukov /// 2769b3f38f9SIlya Biryukov /// Ensures that added nodes properly nest and cover the whole token stream. 2779b3f38f9SIlya Biryukov struct Forest { 2789b3f38f9SIlya Biryukov Forest(syntax::Arena &A) { 279bfbf6b6cSIlya Biryukov assert(!A.tokenBuffer().expandedTokens().empty()); 280bfbf6b6cSIlya Biryukov assert(A.tokenBuffer().expandedTokens().back().kind() == tok::eof); 2819b3f38f9SIlya Biryukov // Create all leaf nodes. 282bfbf6b6cSIlya Biryukov // Note that we do not have 'eof' in the tree. 2831ad15046SIlya Biryukov for (auto &T : A.tokenBuffer().expandedTokens().drop_back()) { 2841ad15046SIlya Biryukov auto *L = new (A.allocator()) syntax::Leaf(&T); 2851ad15046SIlya Biryukov L->Original = true; 2861ad15046SIlya Biryukov L->CanModify = A.tokenBuffer().spelledForExpanded(T).hasValue(); 2871ad15046SIlya Biryukov Trees.insert(Trees.end(), {&T, NodeAndRole{L}}); 2881ad15046SIlya Biryukov } 2899b3f38f9SIlya Biryukov } 2909b3f38f9SIlya Biryukov 291e702bdb8SIlya Biryukov ~Forest() { assert(DelayedFolds.empty()); } 292e702bdb8SIlya Biryukov 293*7d382dcdSMarcel Hlopko void assignRoleDelayed(llvm::ArrayRef<syntax::Token> Range, 294*7d382dcdSMarcel Hlopko syntax::NodeRole Role) { 295*7d382dcdSMarcel Hlopko auto It = DelayedFolds.find(Range.begin()); 296*7d382dcdSMarcel Hlopko assert(It != DelayedFolds.end()); 297*7d382dcdSMarcel Hlopko assert(It->second.End == Range.end()); 298*7d382dcdSMarcel Hlopko It->second.Role = Role; 299*7d382dcdSMarcel Hlopko } 300*7d382dcdSMarcel Hlopko 3019b3f38f9SIlya Biryukov void assignRole(llvm::ArrayRef<syntax::Token> Range, 3029b3f38f9SIlya Biryukov syntax::NodeRole Role) { 3039b3f38f9SIlya Biryukov assert(!Range.empty()); 3049b3f38f9SIlya Biryukov auto It = Trees.lower_bound(Range.begin()); 3059b3f38f9SIlya Biryukov assert(It != Trees.end() && "no node found"); 3069b3f38f9SIlya Biryukov assert(It->first == Range.begin() && "no child with the specified range"); 3079b3f38f9SIlya Biryukov assert((std::next(It) == Trees.end() || 3089b3f38f9SIlya Biryukov std::next(It)->first == Range.end()) && 3099b3f38f9SIlya Biryukov "no child with the specified range"); 3109b3f38f9SIlya Biryukov It->second.Role = Role; 3119b3f38f9SIlya Biryukov } 3129b3f38f9SIlya Biryukov 313e702bdb8SIlya Biryukov /// Add \p Node to the forest and attach child nodes based on \p Tokens. 3141ad15046SIlya Biryukov void foldChildren(const syntax::Arena &A, 3151ad15046SIlya Biryukov llvm::ArrayRef<syntax::Token> Tokens, 3169b3f38f9SIlya Biryukov syntax::Tree *Node) { 317e702bdb8SIlya Biryukov // Execute delayed folds inside `Tokens`. 318*7d382dcdSMarcel Hlopko auto BeginFolds = DelayedFolds.lower_bound(Tokens.begin()); 319*7d382dcdSMarcel Hlopko auto EndFolds = BeginFolds; 320*7d382dcdSMarcel Hlopko for (; EndFolds != DelayedFolds.end() && 321*7d382dcdSMarcel Hlopko EndFolds->second.End <= Tokens.end(); 322*7d382dcdSMarcel Hlopko ++EndFolds) 323*7d382dcdSMarcel Hlopko ; 324*7d382dcdSMarcel Hlopko // We go in reverse order to ensure we fold deeper nodes first. 325*7d382dcdSMarcel Hlopko for (auto RevIt = EndFolds; RevIt != BeginFolds; --RevIt) { 326*7d382dcdSMarcel Hlopko auto It = std::prev(RevIt); 3271ad15046SIlya Biryukov foldChildrenEager(A, llvm::makeArrayRef(It->first, It->second.End), 328e702bdb8SIlya Biryukov It->second.Node); 329*7d382dcdSMarcel Hlopko } 330*7d382dcdSMarcel Hlopko DelayedFolds.erase(BeginFolds, EndFolds); 3319b3f38f9SIlya Biryukov 332e702bdb8SIlya Biryukov // Attach children to `Node`. 3331ad15046SIlya Biryukov foldChildrenEager(A, Tokens, Node); 334e702bdb8SIlya Biryukov } 3359b3f38f9SIlya Biryukov 336e702bdb8SIlya Biryukov /// Schedule a call to `foldChildren` that will only be executed when 337e702bdb8SIlya Biryukov /// containing node is folded. The range of delayed nodes can be extended by 338e702bdb8SIlya Biryukov /// calling `extendDelayedFold`. Only one delayed node for each starting 339e702bdb8SIlya Biryukov /// token is allowed. 340e702bdb8SIlya Biryukov void foldChildrenDelayed(llvm::ArrayRef<syntax::Token> Tokens, 341e702bdb8SIlya Biryukov syntax::Tree *Node) { 342e702bdb8SIlya Biryukov assert(!Tokens.empty()); 343e702bdb8SIlya Biryukov bool Inserted = 344e702bdb8SIlya Biryukov DelayedFolds.insert({Tokens.begin(), DelayedFold{Tokens.end(), Node}}) 345e702bdb8SIlya Biryukov .second; 346e702bdb8SIlya Biryukov (void)Inserted; 347e702bdb8SIlya Biryukov assert(Inserted && "Multiple delayed folds start at the same token"); 348e702bdb8SIlya Biryukov } 3499b3f38f9SIlya Biryukov 350e702bdb8SIlya Biryukov /// If there a delayed fold, starting at `ExtendedRange.begin()`, extends 351e702bdb8SIlya Biryukov /// its endpoint to `ExtendedRange.end()` and returns true. 352e702bdb8SIlya Biryukov /// Otherwise, returns false. 353e702bdb8SIlya Biryukov bool extendDelayedFold(llvm::ArrayRef<syntax::Token> ExtendedRange) { 354e702bdb8SIlya Biryukov assert(!ExtendedRange.empty()); 355e702bdb8SIlya Biryukov auto It = DelayedFolds.find(ExtendedRange.data()); 356e702bdb8SIlya Biryukov if (It == DelayedFolds.end()) 357e702bdb8SIlya Biryukov return false; 358e702bdb8SIlya Biryukov assert(It->second.End <= ExtendedRange.end()); 359e702bdb8SIlya Biryukov It->second.End = ExtendedRange.end(); 360e702bdb8SIlya Biryukov return true; 3619b3f38f9SIlya Biryukov } 3629b3f38f9SIlya Biryukov 3639b3f38f9SIlya Biryukov // EXPECTS: all tokens were consumed and are owned by a single root node. 3649b3f38f9SIlya Biryukov syntax::Node *finalize() && { 3659b3f38f9SIlya Biryukov assert(Trees.size() == 1); 3669b3f38f9SIlya Biryukov auto *Root = Trees.begin()->second.Node; 3679b3f38f9SIlya Biryukov Trees = {}; 3689b3f38f9SIlya Biryukov return Root; 3699b3f38f9SIlya Biryukov } 3709b3f38f9SIlya Biryukov 3719b3f38f9SIlya Biryukov std::string str(const syntax::Arena &A) const { 3729b3f38f9SIlya Biryukov std::string R; 3739b3f38f9SIlya Biryukov for (auto It = Trees.begin(); It != Trees.end(); ++It) { 3749b3f38f9SIlya Biryukov unsigned CoveredTokens = 3759b3f38f9SIlya Biryukov It != Trees.end() 3769b3f38f9SIlya Biryukov ? (std::next(It)->first - It->first) 3779b3f38f9SIlya Biryukov : A.tokenBuffer().expandedTokens().end() - It->first; 3789b3f38f9SIlya Biryukov 379adcd0268SBenjamin Kramer R += std::string(llvm::formatv( 380adcd0268SBenjamin Kramer "- '{0}' covers '{1}'+{2} tokens\n", It->second.Node->kind(), 381adcd0268SBenjamin Kramer It->first->text(A.sourceManager()), CoveredTokens)); 3829b3f38f9SIlya Biryukov R += It->second.Node->dump(A); 3839b3f38f9SIlya Biryukov } 3849b3f38f9SIlya Biryukov return R; 3859b3f38f9SIlya Biryukov } 3869b3f38f9SIlya Biryukov 3879b3f38f9SIlya Biryukov private: 388e702bdb8SIlya Biryukov /// Implementation detail of `foldChildren`, does acutal folding ignoring 389e702bdb8SIlya Biryukov /// delayed folds. 3901ad15046SIlya Biryukov void foldChildrenEager(const syntax::Arena &A, 3911ad15046SIlya Biryukov llvm::ArrayRef<syntax::Token> Tokens, 392e702bdb8SIlya Biryukov syntax::Tree *Node) { 393e702bdb8SIlya Biryukov assert(Node->firstChild() == nullptr && "node already has children"); 394e702bdb8SIlya Biryukov 395e702bdb8SIlya Biryukov auto *FirstToken = Tokens.begin(); 396e702bdb8SIlya Biryukov auto BeginChildren = Trees.lower_bound(FirstToken); 397e702bdb8SIlya Biryukov assert((BeginChildren == Trees.end() || 398e702bdb8SIlya Biryukov BeginChildren->first == FirstToken) && 399e702bdb8SIlya Biryukov "fold crosses boundaries of existing subtrees"); 400e702bdb8SIlya Biryukov auto EndChildren = Trees.lower_bound(Tokens.end()); 401e702bdb8SIlya Biryukov assert( 402e702bdb8SIlya Biryukov (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) && 403e702bdb8SIlya Biryukov "fold crosses boundaries of existing subtrees"); 404e702bdb8SIlya Biryukov 405*7d382dcdSMarcel Hlopko // We need to go in reverse order, because we can only prepend. 406e702bdb8SIlya Biryukov for (auto It = EndChildren; It != BeginChildren; --It) 407e702bdb8SIlya Biryukov Node->prependChildLowLevel(std::prev(It)->second.Node, 408e702bdb8SIlya Biryukov std::prev(It)->second.Role); 409e702bdb8SIlya Biryukov 4101ad15046SIlya Biryukov // Mark that this node came from the AST and is backed by the source code. 4111ad15046SIlya Biryukov Node->Original = true; 4121ad15046SIlya Biryukov Node->CanModify = A.tokenBuffer().spelledForExpanded(Tokens).hasValue(); 4131ad15046SIlya Biryukov 414e702bdb8SIlya Biryukov Trees.erase(BeginChildren, EndChildren); 415e702bdb8SIlya Biryukov Trees.insert({FirstToken, NodeAndRole(Node)}); 416e702bdb8SIlya Biryukov } 4179b3f38f9SIlya Biryukov /// A with a role that should be assigned to it when adding to a parent. 4189b3f38f9SIlya Biryukov struct NodeAndRole { 4199b3f38f9SIlya Biryukov explicit NodeAndRole(syntax::Node *Node) 42051dad419SIlya Biryukov : Node(Node), Role(NodeRole::Unknown) {} 4219b3f38f9SIlya Biryukov 4229b3f38f9SIlya Biryukov syntax::Node *Node; 4239b3f38f9SIlya Biryukov NodeRole Role; 4249b3f38f9SIlya Biryukov }; 4259b3f38f9SIlya Biryukov 4269b3f38f9SIlya Biryukov /// Maps from the start token to a subtree starting at that token. 427302cb3bcSIlya Biryukov /// Keys in the map are pointers into the array of expanded tokens, so 428302cb3bcSIlya Biryukov /// pointer order corresponds to the order of preprocessor tokens. 4299b3f38f9SIlya Biryukov /// FIXME: storing the end tokens is redundant. 4309b3f38f9SIlya Biryukov /// FIXME: the key of a map is redundant, it is also stored in NodeForRange. 4319b3f38f9SIlya Biryukov std::map<const syntax::Token *, NodeAndRole> Trees; 432e702bdb8SIlya Biryukov 433e702bdb8SIlya Biryukov /// See documentation of `foldChildrenDelayed` for details. 434e702bdb8SIlya Biryukov struct DelayedFold { 435e702bdb8SIlya Biryukov const syntax::Token *End = nullptr; 436e702bdb8SIlya Biryukov syntax::Tree *Node = nullptr; 437*7d382dcdSMarcel Hlopko NodeRole Role = NodeRole::Unknown; 438e702bdb8SIlya Biryukov }; 439e702bdb8SIlya Biryukov std::map<const syntax::Token *, DelayedFold> DelayedFolds; 4409b3f38f9SIlya Biryukov }; 4419b3f38f9SIlya Biryukov 4429b3f38f9SIlya Biryukov /// For debugging purposes. 4439b3f38f9SIlya Biryukov std::string str() { return Pending.str(Arena); } 4449b3f38f9SIlya Biryukov 4459b3f38f9SIlya Biryukov syntax::Arena &Arena; 446c1bbefefSIlya Biryukov /// To quickly find tokens by their start location. 447c1bbefefSIlya Biryukov llvm::DenseMap</*SourceLocation*/ unsigned, const syntax::Token *> 448c1bbefefSIlya Biryukov LocationToToken; 4499b3f38f9SIlya Biryukov Forest Pending; 450e702bdb8SIlya Biryukov llvm::DenseSet<Decl *> DeclsWithoutSemicolons; 4519b3f38f9SIlya Biryukov }; 4529b3f38f9SIlya Biryukov 4539b3f38f9SIlya Biryukov namespace { 4549b3f38f9SIlya Biryukov class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> { 4559b3f38f9SIlya Biryukov public: 4569b3f38f9SIlya Biryukov explicit BuildTreeVisitor(ASTContext &Ctx, syntax::TreeBuilder &Builder) 4579b3f38f9SIlya Biryukov : Builder(Builder), LangOpts(Ctx.getLangOpts()) {} 4589b3f38f9SIlya Biryukov 4599b3f38f9SIlya Biryukov bool shouldTraversePostOrder() const { return true; } 4609b3f38f9SIlya Biryukov 461*7d382dcdSMarcel Hlopko bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) { 462e702bdb8SIlya Biryukov // Ensure declarators are covered by SimpleDeclaration. 463*7d382dcdSMarcel Hlopko Builder.noticeDeclRange(Builder.getRange(DD)); 464*7d382dcdSMarcel Hlopko 465*7d382dcdSMarcel Hlopko // Build the declarator node. 466*7d382dcdSMarcel Hlopko SourceRange Initializer; 467*7d382dcdSMarcel Hlopko if (auto *V = llvm::dyn_cast<VarDecl>(DD)) { 468*7d382dcdSMarcel Hlopko auto *I = V->getInit(); 469*7d382dcdSMarcel Hlopko // Initializers in range-based-for are not part of the declarator 470*7d382dcdSMarcel Hlopko if (I && !V->isCXXForRangeDecl()) 471*7d382dcdSMarcel Hlopko Initializer = I->getSourceRange(); 472*7d382dcdSMarcel Hlopko } 473*7d382dcdSMarcel Hlopko auto Declarator = getDeclaratorRange( 474*7d382dcdSMarcel Hlopko Builder.sourceManager(), DD->getTypeSourceInfo()->getTypeLoc(), 475*7d382dcdSMarcel Hlopko getQualifiedNameStart(DD), Initializer); 476*7d382dcdSMarcel Hlopko if (Declarator.isValid()) { 477*7d382dcdSMarcel Hlopko auto Tokens = 478*7d382dcdSMarcel Hlopko Builder.getRange(Declarator.getBegin(), Declarator.getEnd()); 479*7d382dcdSMarcel Hlopko Builder.foldNode(Tokens, new (allocator()) syntax::SimpleDeclarator); 480*7d382dcdSMarcel Hlopko Builder.markChild(Tokens, syntax::NodeRole::SimpleDeclaration_declarator); 481*7d382dcdSMarcel Hlopko } 482*7d382dcdSMarcel Hlopko 483e702bdb8SIlya Biryukov return true; 484e702bdb8SIlya Biryukov } 485*7d382dcdSMarcel Hlopko 486e702bdb8SIlya Biryukov bool WalkUpFromTypedefNameDecl(TypedefNameDecl *D) { 487*7d382dcdSMarcel Hlopko // Ensure declarators are covered by SimpleDeclaration. 488*7d382dcdSMarcel Hlopko Builder.noticeDeclRange(Builder.getRange(D)); 489*7d382dcdSMarcel Hlopko 490*7d382dcdSMarcel Hlopko auto R = getDeclaratorRange( 491*7d382dcdSMarcel Hlopko Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(), 492*7d382dcdSMarcel Hlopko /*Name=*/D->getLocation(), /*Initializer=*/SourceRange()); 493*7d382dcdSMarcel Hlopko if (R.isValid()) { 494*7d382dcdSMarcel Hlopko auto Tokens = Builder.getRange(R.getBegin(), R.getEnd()); 495*7d382dcdSMarcel Hlopko Builder.foldNode(Tokens, new (allocator()) syntax::SimpleDeclarator); 496*7d382dcdSMarcel Hlopko Builder.markChild(Tokens, syntax::NodeRole::SimpleDeclaration_declarator); 497*7d382dcdSMarcel Hlopko } 498e702bdb8SIlya Biryukov return true; 4999b3f38f9SIlya Biryukov } 5009b3f38f9SIlya Biryukov 5019b3f38f9SIlya Biryukov bool VisitDecl(Decl *D) { 5029b3f38f9SIlya Biryukov assert(!D->isImplicit()); 5039b3f38f9SIlya Biryukov Builder.foldNode(Builder.getRange(D), 504e702bdb8SIlya Biryukov new (allocator()) syntax::UnknownDeclaration()); 505e702bdb8SIlya Biryukov return true; 506e702bdb8SIlya Biryukov } 507e702bdb8SIlya Biryukov 508e702bdb8SIlya Biryukov bool WalkUpFromTagDecl(TagDecl *C) { 50904f627f6SIlya Biryukov // FIXME: build the ClassSpecifier node. 51004f627f6SIlya Biryukov if (C->isFreeStanding()) { 51104f627f6SIlya Biryukov // Class is a declaration specifier and needs a spanning declaration node. 51204f627f6SIlya Biryukov Builder.foldNode(Builder.getRange(C), 51304f627f6SIlya Biryukov new (allocator()) syntax::SimpleDeclaration); 51404f627f6SIlya Biryukov return true; 51504f627f6SIlya Biryukov } 5169b3f38f9SIlya Biryukov return true; 5179b3f38f9SIlya Biryukov } 5189b3f38f9SIlya Biryukov 5199b3f38f9SIlya Biryukov bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) { 520*7d382dcdSMarcel Hlopko // We do not want to call VisitDecl(), the declaration for translation 5219b3f38f9SIlya Biryukov // unit is built by finalize(). 5229b3f38f9SIlya Biryukov return true; 5239b3f38f9SIlya Biryukov } 5249b3f38f9SIlya Biryukov 5259b3f38f9SIlya Biryukov bool WalkUpFromCompoundStmt(CompoundStmt *S) { 52651dad419SIlya Biryukov using NodeRole = syntax::NodeRole; 5279b3f38f9SIlya Biryukov 528def65bb4SIlya Biryukov Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen); 52958fa50f4SIlya Biryukov for (auto *Child : S->body()) 53058fa50f4SIlya Biryukov Builder.markStmtChild(Child, NodeRole::CompoundStatement_statement); 531def65bb4SIlya Biryukov Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen); 5329b3f38f9SIlya Biryukov 53358fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 5349b3f38f9SIlya Biryukov new (allocator()) syntax::CompoundStatement); 5359b3f38f9SIlya Biryukov return true; 5369b3f38f9SIlya Biryukov } 5379b3f38f9SIlya Biryukov 53858fa50f4SIlya Biryukov // Some statements are not yet handled by syntax trees. 53958fa50f4SIlya Biryukov bool WalkUpFromStmt(Stmt *S) { 54058fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 54158fa50f4SIlya Biryukov new (allocator()) syntax::UnknownStatement); 54258fa50f4SIlya Biryukov return true; 54358fa50f4SIlya Biryukov } 54458fa50f4SIlya Biryukov 54558fa50f4SIlya Biryukov bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) { 54658fa50f4SIlya Biryukov // We override to traverse range initializer as VarDecl. 54758fa50f4SIlya Biryukov // RAV traverses it as a statement, we produce invalid node kinds in that 54858fa50f4SIlya Biryukov // case. 54958fa50f4SIlya Biryukov // FIXME: should do this in RAV instead? 55058fa50f4SIlya Biryukov if (S->getInit() && !TraverseStmt(S->getInit())) 55158fa50f4SIlya Biryukov return false; 55258fa50f4SIlya Biryukov if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable())) 55358fa50f4SIlya Biryukov return false; 55458fa50f4SIlya Biryukov if (S->getRangeInit() && !TraverseStmt(S->getRangeInit())) 55558fa50f4SIlya Biryukov return false; 55658fa50f4SIlya Biryukov if (S->getBody() && !TraverseStmt(S->getBody())) 55758fa50f4SIlya Biryukov return false; 55858fa50f4SIlya Biryukov return true; 55958fa50f4SIlya Biryukov } 56058fa50f4SIlya Biryukov 56158fa50f4SIlya Biryukov bool TraverseStmt(Stmt *S) { 562e702bdb8SIlya Biryukov if (auto *DS = llvm::dyn_cast_or_null<DeclStmt>(S)) { 563e702bdb8SIlya Biryukov // We want to consume the semicolon, make sure SimpleDeclaration does not. 564e702bdb8SIlya Biryukov for (auto *D : DS->decls()) 565*7d382dcdSMarcel Hlopko Builder.noticeDeclWithoutSemicolon(D); 566e702bdb8SIlya Biryukov } else if (auto *E = llvm::dyn_cast_or_null<Expr>(S)) { 567*7d382dcdSMarcel Hlopko // Do not recurse into subexpressions. 568*7d382dcdSMarcel Hlopko // We do not have syntax trees for expressions yet, so we only want to see 56958fa50f4SIlya Biryukov // the first top-level expression. 57058fa50f4SIlya Biryukov return WalkUpFromExpr(E->IgnoreImplicit()); 57158fa50f4SIlya Biryukov } 57258fa50f4SIlya Biryukov return RecursiveASTVisitor::TraverseStmt(S); 57358fa50f4SIlya Biryukov } 57458fa50f4SIlya Biryukov 57558fa50f4SIlya Biryukov // Some expressions are not yet handled by syntax trees. 57658fa50f4SIlya Biryukov bool WalkUpFromExpr(Expr *E) { 57758fa50f4SIlya Biryukov assert(!isImplicitExpr(E) && "should be handled by TraverseStmt"); 57858fa50f4SIlya Biryukov Builder.foldNode(Builder.getExprRange(E), 57958fa50f4SIlya Biryukov new (allocator()) syntax::UnknownExpression); 58058fa50f4SIlya Biryukov return true; 58158fa50f4SIlya Biryukov } 58258fa50f4SIlya Biryukov 583be14a22bSIlya Biryukov bool WalkUpFromNamespaceDecl(NamespaceDecl *S) { 584be14a22bSIlya Biryukov auto Tokens = Builder.getRange(S); 585be14a22bSIlya Biryukov if (Tokens.front().kind() == tok::coloncolon) { 586be14a22bSIlya Biryukov // Handle nested namespace definitions. Those start at '::' token, e.g. 587be14a22bSIlya Biryukov // namespace a^::b {} 588be14a22bSIlya Biryukov // FIXME: build corresponding nodes for the name of this namespace. 589be14a22bSIlya Biryukov return true; 590be14a22bSIlya Biryukov } 591be14a22bSIlya Biryukov Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition); 592be14a22bSIlya Biryukov return true; 593be14a22bSIlya Biryukov } 594be14a22bSIlya Biryukov 595*7d382dcdSMarcel Hlopko bool TraverseParenTypeLoc(ParenTypeLoc L) { 596*7d382dcdSMarcel Hlopko // We reverse order of traversal to get the proper syntax structure. 597*7d382dcdSMarcel Hlopko if (!WalkUpFromParenTypeLoc(L)) 598*7d382dcdSMarcel Hlopko return false; 599*7d382dcdSMarcel Hlopko return TraverseTypeLoc(L.getInnerLoc()); 600*7d382dcdSMarcel Hlopko } 601*7d382dcdSMarcel Hlopko 602*7d382dcdSMarcel Hlopko bool WalkUpFromParenTypeLoc(ParenTypeLoc L) { 603*7d382dcdSMarcel Hlopko Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen); 604*7d382dcdSMarcel Hlopko Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen); 605*7d382dcdSMarcel Hlopko Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getRParenLoc()), 606*7d382dcdSMarcel Hlopko new (allocator()) syntax::ParenDeclarator); 607*7d382dcdSMarcel Hlopko return true; 608*7d382dcdSMarcel Hlopko } 609*7d382dcdSMarcel Hlopko 610*7d382dcdSMarcel Hlopko // Declarator chunks, they are produced by type locs and some clang::Decls. 611*7d382dcdSMarcel Hlopko bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L) { 612*7d382dcdSMarcel Hlopko Builder.markChildToken(L.getLBracketLoc(), syntax::NodeRole::OpenParen); 613*7d382dcdSMarcel Hlopko Builder.markExprChild(L.getSizeExpr(), 614*7d382dcdSMarcel Hlopko syntax::NodeRole::ArraySubscript_sizeExpression); 615*7d382dcdSMarcel Hlopko Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen); 616*7d382dcdSMarcel Hlopko Builder.foldNode(Builder.getRange(L.getLBracketLoc(), L.getRBracketLoc()), 617*7d382dcdSMarcel Hlopko new (allocator()) syntax::ArraySubscript); 618*7d382dcdSMarcel Hlopko return true; 619*7d382dcdSMarcel Hlopko } 620*7d382dcdSMarcel Hlopko 621*7d382dcdSMarcel Hlopko bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L) { 622*7d382dcdSMarcel Hlopko Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen); 623*7d382dcdSMarcel Hlopko for (auto *P : L.getParams()) 624*7d382dcdSMarcel Hlopko Builder.markDelayedChild( 625*7d382dcdSMarcel Hlopko Builder.getRange(P), 626*7d382dcdSMarcel Hlopko syntax::NodeRole::ParametersAndQualifiers_parameter); 627*7d382dcdSMarcel Hlopko Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen); 628*7d382dcdSMarcel Hlopko Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()), 629*7d382dcdSMarcel Hlopko new (allocator()) syntax::ParametersAndQualifiers); 630*7d382dcdSMarcel Hlopko return true; 631*7d382dcdSMarcel Hlopko } 632*7d382dcdSMarcel Hlopko 633*7d382dcdSMarcel Hlopko bool WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L) { 634*7d382dcdSMarcel Hlopko if (!L.getTypePtr()->hasTrailingReturn()) 635*7d382dcdSMarcel Hlopko return WalkUpFromFunctionTypeLoc(L); 636*7d382dcdSMarcel Hlopko 637*7d382dcdSMarcel Hlopko auto TrailingReturnTokens = BuildTrailingReturn(L); 638*7d382dcdSMarcel Hlopko // Finish building the node for parameters. 639*7d382dcdSMarcel Hlopko Builder.markChild(TrailingReturnTokens, 640*7d382dcdSMarcel Hlopko syntax::NodeRole::ParametersAndQualifiers_trailingReturn); 641*7d382dcdSMarcel Hlopko return WalkUpFromFunctionTypeLoc(L); 642*7d382dcdSMarcel Hlopko } 643*7d382dcdSMarcel Hlopko 644*7d382dcdSMarcel Hlopko bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) { 645*7d382dcdSMarcel Hlopko auto SR = L.getLocalSourceRange(); 646*7d382dcdSMarcel Hlopko Builder.foldNode(Builder.getRange(SR.getBegin(), SR.getEnd()), 647*7d382dcdSMarcel Hlopko new (allocator()) syntax::MemberPointer); 648*7d382dcdSMarcel Hlopko return true; 649*7d382dcdSMarcel Hlopko } 650*7d382dcdSMarcel Hlopko 65158fa50f4SIlya Biryukov // The code below is very regular, it could even be generated with some 65258fa50f4SIlya Biryukov // preprocessor magic. We merely assign roles to the corresponding children 65358fa50f4SIlya Biryukov // and fold resulting nodes. 65458fa50f4SIlya Biryukov bool WalkUpFromDeclStmt(DeclStmt *S) { 65558fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 65658fa50f4SIlya Biryukov new (allocator()) syntax::DeclarationStatement); 65758fa50f4SIlya Biryukov return true; 65858fa50f4SIlya Biryukov } 65958fa50f4SIlya Biryukov 66058fa50f4SIlya Biryukov bool WalkUpFromNullStmt(NullStmt *S) { 66158fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 66258fa50f4SIlya Biryukov new (allocator()) syntax::EmptyStatement); 66358fa50f4SIlya Biryukov return true; 66458fa50f4SIlya Biryukov } 66558fa50f4SIlya Biryukov 66658fa50f4SIlya Biryukov bool WalkUpFromSwitchStmt(SwitchStmt *S) { 667def65bb4SIlya Biryukov Builder.markChildToken(S->getSwitchLoc(), 66858fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 66958fa50f4SIlya Biryukov Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 67058fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 67158fa50f4SIlya Biryukov new (allocator()) syntax::SwitchStatement); 67258fa50f4SIlya Biryukov return true; 67358fa50f4SIlya Biryukov } 67458fa50f4SIlya Biryukov 67558fa50f4SIlya Biryukov bool WalkUpFromCaseStmt(CaseStmt *S) { 676def65bb4SIlya Biryukov Builder.markChildToken(S->getKeywordLoc(), 67758fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 67858fa50f4SIlya Biryukov Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseStatement_value); 67958fa50f4SIlya Biryukov Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 68058fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 68158fa50f4SIlya Biryukov new (allocator()) syntax::CaseStatement); 68258fa50f4SIlya Biryukov return true; 68358fa50f4SIlya Biryukov } 68458fa50f4SIlya Biryukov 68558fa50f4SIlya Biryukov bool WalkUpFromDefaultStmt(DefaultStmt *S) { 686def65bb4SIlya Biryukov Builder.markChildToken(S->getKeywordLoc(), 68758fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 68858fa50f4SIlya Biryukov Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 68958fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 69058fa50f4SIlya Biryukov new (allocator()) syntax::DefaultStatement); 69158fa50f4SIlya Biryukov return true; 69258fa50f4SIlya Biryukov } 69358fa50f4SIlya Biryukov 69458fa50f4SIlya Biryukov bool WalkUpFromIfStmt(IfStmt *S) { 695def65bb4SIlya Biryukov Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword); 69658fa50f4SIlya Biryukov Builder.markStmtChild(S->getThen(), 69758fa50f4SIlya Biryukov syntax::NodeRole::IfStatement_thenStatement); 698def65bb4SIlya Biryukov Builder.markChildToken(S->getElseLoc(), 69958fa50f4SIlya Biryukov syntax::NodeRole::IfStatement_elseKeyword); 70058fa50f4SIlya Biryukov Builder.markStmtChild(S->getElse(), 70158fa50f4SIlya Biryukov syntax::NodeRole::IfStatement_elseStatement); 70258fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 70358fa50f4SIlya Biryukov new (allocator()) syntax::IfStatement); 70458fa50f4SIlya Biryukov return true; 70558fa50f4SIlya Biryukov } 70658fa50f4SIlya Biryukov 70758fa50f4SIlya Biryukov bool WalkUpFromForStmt(ForStmt *S) { 708def65bb4SIlya Biryukov Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 70958fa50f4SIlya Biryukov Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 71058fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 71158fa50f4SIlya Biryukov new (allocator()) syntax::ForStatement); 71258fa50f4SIlya Biryukov return true; 71358fa50f4SIlya Biryukov } 71458fa50f4SIlya Biryukov 71558fa50f4SIlya Biryukov bool WalkUpFromWhileStmt(WhileStmt *S) { 716def65bb4SIlya Biryukov Builder.markChildToken(S->getWhileLoc(), 71758fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 71858fa50f4SIlya Biryukov Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 71958fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 72058fa50f4SIlya Biryukov new (allocator()) syntax::WhileStatement); 72158fa50f4SIlya Biryukov return true; 72258fa50f4SIlya Biryukov } 72358fa50f4SIlya Biryukov 72458fa50f4SIlya Biryukov bool WalkUpFromContinueStmt(ContinueStmt *S) { 725def65bb4SIlya Biryukov Builder.markChildToken(S->getContinueLoc(), 72658fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 72758fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 72858fa50f4SIlya Biryukov new (allocator()) syntax::ContinueStatement); 72958fa50f4SIlya Biryukov return true; 73058fa50f4SIlya Biryukov } 73158fa50f4SIlya Biryukov 73258fa50f4SIlya Biryukov bool WalkUpFromBreakStmt(BreakStmt *S) { 733def65bb4SIlya Biryukov Builder.markChildToken(S->getBreakLoc(), 73458fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 73558fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 73658fa50f4SIlya Biryukov new (allocator()) syntax::BreakStatement); 73758fa50f4SIlya Biryukov return true; 73858fa50f4SIlya Biryukov } 73958fa50f4SIlya Biryukov 74058fa50f4SIlya Biryukov bool WalkUpFromReturnStmt(ReturnStmt *S) { 741def65bb4SIlya Biryukov Builder.markChildToken(S->getReturnLoc(), 74258fa50f4SIlya Biryukov syntax::NodeRole::IntroducerKeyword); 74358fa50f4SIlya Biryukov Builder.markExprChild(S->getRetValue(), 74458fa50f4SIlya Biryukov syntax::NodeRole::ReturnStatement_value); 74558fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 74658fa50f4SIlya Biryukov new (allocator()) syntax::ReturnStatement); 74758fa50f4SIlya Biryukov return true; 74858fa50f4SIlya Biryukov } 74958fa50f4SIlya Biryukov 75058fa50f4SIlya Biryukov bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) { 751def65bb4SIlya Biryukov Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 75258fa50f4SIlya Biryukov Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 75358fa50f4SIlya Biryukov Builder.foldNode(Builder.getStmtRange(S), 75458fa50f4SIlya Biryukov new (allocator()) syntax::RangeBasedForStatement); 75558fa50f4SIlya Biryukov return true; 75658fa50f4SIlya Biryukov } 75758fa50f4SIlya Biryukov 758be14a22bSIlya Biryukov bool WalkUpFromEmptyDecl(EmptyDecl *S) { 759be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 760be14a22bSIlya Biryukov new (allocator()) syntax::EmptyDeclaration); 761be14a22bSIlya Biryukov return true; 762be14a22bSIlya Biryukov } 763be14a22bSIlya Biryukov 764be14a22bSIlya Biryukov bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) { 765be14a22bSIlya Biryukov Builder.markExprChild(S->getAssertExpr(), 766be14a22bSIlya Biryukov syntax::NodeRole::StaticAssertDeclaration_condition); 767be14a22bSIlya Biryukov Builder.markExprChild(S->getMessage(), 768be14a22bSIlya Biryukov syntax::NodeRole::StaticAssertDeclaration_message); 769be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 770be14a22bSIlya Biryukov new (allocator()) syntax::StaticAssertDeclaration); 771be14a22bSIlya Biryukov return true; 772be14a22bSIlya Biryukov } 773be14a22bSIlya Biryukov 774be14a22bSIlya Biryukov bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) { 775be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 776be14a22bSIlya Biryukov new (allocator()) syntax::LinkageSpecificationDeclaration); 777be14a22bSIlya Biryukov return true; 778be14a22bSIlya Biryukov } 779be14a22bSIlya Biryukov 780be14a22bSIlya Biryukov bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) { 781be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 782be14a22bSIlya Biryukov new (allocator()) syntax::NamespaceAliasDefinition); 783be14a22bSIlya Biryukov return true; 784be14a22bSIlya Biryukov } 785be14a22bSIlya Biryukov 786be14a22bSIlya Biryukov bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) { 787be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 788be14a22bSIlya Biryukov new (allocator()) syntax::UsingNamespaceDirective); 789be14a22bSIlya Biryukov return true; 790be14a22bSIlya Biryukov } 791be14a22bSIlya Biryukov 792be14a22bSIlya Biryukov bool WalkUpFromUsingDecl(UsingDecl *S) { 793be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 794be14a22bSIlya Biryukov new (allocator()) syntax::UsingDeclaration); 795be14a22bSIlya Biryukov return true; 796be14a22bSIlya Biryukov } 797be14a22bSIlya Biryukov 798be14a22bSIlya Biryukov bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) { 799be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 800be14a22bSIlya Biryukov new (allocator()) syntax::UsingDeclaration); 801be14a22bSIlya Biryukov return true; 802be14a22bSIlya Biryukov } 803be14a22bSIlya Biryukov 804be14a22bSIlya Biryukov bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) { 805be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 806be14a22bSIlya Biryukov new (allocator()) syntax::UsingDeclaration); 807be14a22bSIlya Biryukov return true; 808be14a22bSIlya Biryukov } 809be14a22bSIlya Biryukov 810be14a22bSIlya Biryukov bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) { 811be14a22bSIlya Biryukov Builder.foldNode(Builder.getRange(S), 812be14a22bSIlya Biryukov new (allocator()) syntax::TypeAliasDeclaration); 813be14a22bSIlya Biryukov return true; 814be14a22bSIlya Biryukov } 815be14a22bSIlya Biryukov 8169b3f38f9SIlya Biryukov private: 817*7d382dcdSMarcel Hlopko /// Returns the range of the built node. 818*7d382dcdSMarcel Hlopko llvm::ArrayRef<syntax::Token> BuildTrailingReturn(FunctionProtoTypeLoc L) { 819*7d382dcdSMarcel Hlopko assert(L.getTypePtr()->hasTrailingReturn()); 820*7d382dcdSMarcel Hlopko 821*7d382dcdSMarcel Hlopko auto ReturnedType = L.getReturnLoc(); 822*7d382dcdSMarcel Hlopko // Build node for the declarator, if any. 823*7d382dcdSMarcel Hlopko auto ReturnDeclaratorRange = 824*7d382dcdSMarcel Hlopko getDeclaratorRange(this->Builder.sourceManager(), ReturnedType, 825*7d382dcdSMarcel Hlopko /*Name=*/SourceLocation(), 826*7d382dcdSMarcel Hlopko /*Initializer=*/SourceLocation()); 827*7d382dcdSMarcel Hlopko llvm::ArrayRef<syntax::Token> ReturnDeclaratorTokens; 828*7d382dcdSMarcel Hlopko if (ReturnDeclaratorRange.isValid()) { 829*7d382dcdSMarcel Hlopko ReturnDeclaratorTokens = Builder.getRange( 830*7d382dcdSMarcel Hlopko ReturnDeclaratorRange.getBegin(), ReturnDeclaratorRange.getEnd()); 831*7d382dcdSMarcel Hlopko Builder.foldNode(ReturnDeclaratorTokens, 832*7d382dcdSMarcel Hlopko new (allocator()) syntax::SimpleDeclarator); 833*7d382dcdSMarcel Hlopko } 834*7d382dcdSMarcel Hlopko 835*7d382dcdSMarcel Hlopko // Build node for trailing return type. 836*7d382dcdSMarcel Hlopko auto Return = 837*7d382dcdSMarcel Hlopko Builder.getRange(ReturnedType.getBeginLoc(), ReturnedType.getEndLoc()); 838*7d382dcdSMarcel Hlopko const auto *Arrow = Return.begin() - 1; 839*7d382dcdSMarcel Hlopko assert(Arrow->kind() == tok::arrow); 840*7d382dcdSMarcel Hlopko auto Tokens = llvm::makeArrayRef(Arrow, Return.end()); 841*7d382dcdSMarcel Hlopko Builder.markChildToken(Arrow, syntax::NodeRole::TrailingReturnType_arrow); 842*7d382dcdSMarcel Hlopko if (!ReturnDeclaratorTokens.empty()) 843*7d382dcdSMarcel Hlopko Builder.markChild(ReturnDeclaratorTokens, 844*7d382dcdSMarcel Hlopko syntax::NodeRole::TrailingReturnType_declarator); 845*7d382dcdSMarcel Hlopko Builder.foldNode(Tokens, new (allocator()) syntax::TrailingReturnType); 846*7d382dcdSMarcel Hlopko return Tokens; 847*7d382dcdSMarcel Hlopko } 8489b3f38f9SIlya Biryukov /// A small helper to save some typing. 8499b3f38f9SIlya Biryukov llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); } 8509b3f38f9SIlya Biryukov 8519b3f38f9SIlya Biryukov syntax::TreeBuilder &Builder; 8529b3f38f9SIlya Biryukov const LangOptions &LangOpts; 8539b3f38f9SIlya Biryukov }; 8549b3f38f9SIlya Biryukov } // namespace 8559b3f38f9SIlya Biryukov 8569b3f38f9SIlya Biryukov void syntax::TreeBuilder::foldNode(llvm::ArrayRef<syntax::Token> Range, 8579b3f38f9SIlya Biryukov syntax::Tree *New) { 8581ad15046SIlya Biryukov Pending.foldChildren(Arena, Range, New); 8599b3f38f9SIlya Biryukov } 8609b3f38f9SIlya Biryukov 861*7d382dcdSMarcel Hlopko void syntax::TreeBuilder::noticeDeclRange(llvm::ArrayRef<syntax::Token> Range) { 862e702bdb8SIlya Biryukov if (Pending.extendDelayedFold(Range)) 863e702bdb8SIlya Biryukov return; 864e702bdb8SIlya Biryukov Pending.foldChildrenDelayed(Range, 865e702bdb8SIlya Biryukov new (allocator()) syntax::SimpleDeclaration); 866e702bdb8SIlya Biryukov } 867e702bdb8SIlya Biryukov 868*7d382dcdSMarcel Hlopko void syntax::TreeBuilder::noticeDeclWithoutSemicolon(Decl *D) { 869e702bdb8SIlya Biryukov DeclsWithoutSemicolons.insert(D); 870e702bdb8SIlya Biryukov } 871e702bdb8SIlya Biryukov 872def65bb4SIlya Biryukov void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) { 8739b3f38f9SIlya Biryukov if (Loc.isInvalid()) 8749b3f38f9SIlya Biryukov return; 8759b3f38f9SIlya Biryukov Pending.assignRole(*findToken(Loc), Role); 8769b3f38f9SIlya Biryukov } 8779b3f38f9SIlya Biryukov 878*7d382dcdSMarcel Hlopko void syntax::TreeBuilder::markChildToken(const syntax::Token *T, NodeRole R) { 879*7d382dcdSMarcel Hlopko if (!T) 880*7d382dcdSMarcel Hlopko return; 881*7d382dcdSMarcel Hlopko Pending.assignRole(*T, R); 882*7d382dcdSMarcel Hlopko } 883*7d382dcdSMarcel Hlopko 884*7d382dcdSMarcel Hlopko void syntax::TreeBuilder::markChild(llvm::ArrayRef<syntax::Token> Range, 885*7d382dcdSMarcel Hlopko NodeRole R) { 886*7d382dcdSMarcel Hlopko Pending.assignRole(Range, R); 887*7d382dcdSMarcel Hlopko } 888*7d382dcdSMarcel Hlopko 889*7d382dcdSMarcel Hlopko void syntax::TreeBuilder::markDelayedChild(llvm::ArrayRef<syntax::Token> Range, 890*7d382dcdSMarcel Hlopko NodeRole R) { 891*7d382dcdSMarcel Hlopko Pending.assignRoleDelayed(Range, R); 892*7d382dcdSMarcel Hlopko } 893*7d382dcdSMarcel Hlopko 89458fa50f4SIlya Biryukov void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) { 89558fa50f4SIlya Biryukov if (!Child) 89658fa50f4SIlya Biryukov return; 89758fa50f4SIlya Biryukov 89858fa50f4SIlya Biryukov auto Range = getStmtRange(Child); 89958fa50f4SIlya Biryukov // This is an expression in a statement position, consume the trailing 90058fa50f4SIlya Biryukov // semicolon and form an 'ExpressionStatement' node. 90158fa50f4SIlya Biryukov if (auto *E = dyn_cast<Expr>(Child)) { 90258fa50f4SIlya Biryukov Pending.assignRole(getExprRange(E), 90358fa50f4SIlya Biryukov NodeRole::ExpressionStatement_expression); 904*7d382dcdSMarcel Hlopko // 'getRange(Stmt)' ensures this already covers a trailing semicolon. 9051ad15046SIlya Biryukov Pending.foldChildren(Arena, Range, 9061ad15046SIlya Biryukov new (allocator()) syntax::ExpressionStatement); 90758fa50f4SIlya Biryukov } 90858fa50f4SIlya Biryukov Pending.assignRole(Range, Role); 90958fa50f4SIlya Biryukov } 91058fa50f4SIlya Biryukov 91158fa50f4SIlya Biryukov void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) { 912be14a22bSIlya Biryukov if (!Child) 913be14a22bSIlya Biryukov return; 914be14a22bSIlya Biryukov 91558fa50f4SIlya Biryukov Pending.assignRole(getExprRange(Child), Role); 91658fa50f4SIlya Biryukov } 91758fa50f4SIlya Biryukov 9189b3f38f9SIlya Biryukov const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const { 919c1bbefefSIlya Biryukov auto It = LocationToToken.find(L.getRawEncoding()); 920c1bbefefSIlya Biryukov assert(It != LocationToToken.end()); 921c1bbefefSIlya Biryukov return It->second; 9229b3f38f9SIlya Biryukov } 9239b3f38f9SIlya Biryukov 9249b3f38f9SIlya Biryukov syntax::TranslationUnit * 9259b3f38f9SIlya Biryukov syntax::buildSyntaxTree(Arena &A, const TranslationUnitDecl &TU) { 9269b3f38f9SIlya Biryukov TreeBuilder Builder(A); 9279b3f38f9SIlya Biryukov BuildTreeVisitor(TU.getASTContext(), Builder).TraverseAST(TU.getASTContext()); 9289b3f38f9SIlya Biryukov return std::move(Builder).finalize(); 9299b3f38f9SIlya Biryukov } 930