1 //===- BuildTree.cpp ------------------------------------------*- C++ -*-=====// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 #include "clang/Tooling/Syntax/BuildTree.h" 9 #include "clang/AST/Decl.h" 10 #include "clang/AST/DeclBase.h" 11 #include "clang/AST/RecursiveASTVisitor.h" 12 #include "clang/AST/Stmt.h" 13 #include "clang/Basic/LLVM.h" 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Basic/SourceManager.h" 16 #include "clang/Basic/TokenKinds.h" 17 #include "clang/Lex/Lexer.h" 18 #include "clang/Tooling/Syntax/Nodes.h" 19 #include "clang/Tooling/Syntax/Tokens.h" 20 #include "clang/Tooling/Syntax/Tree.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/STLExtras.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/Support/Allocator.h" 25 #include "llvm/Support/Casting.h" 26 #include "llvm/Support/Compiler.h" 27 #include "llvm/Support/FormatVariadic.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <map> 31 32 using namespace clang; 33 34 LLVM_ATTRIBUTE_UNUSED 35 static bool isImplicitExpr(clang::Expr *E) { return E->IgnoreImplicit() != E; } 36 37 /// A helper class for constructing the syntax tree while traversing a clang 38 /// AST. 39 /// 40 /// At each point of the traversal we maintain a list of pending nodes. 41 /// Initially all tokens are added as pending nodes. When processing a clang AST 42 /// node, the clients need to: 43 /// - create a corresponding syntax node, 44 /// - assign roles to all pending child nodes with 'markChild' and 45 /// 'markChildToken', 46 /// - replace the child nodes with the new syntax node in the pending list 47 /// with 'foldNode'. 48 /// 49 /// Note that all children are expected to be processed when building a node. 50 /// 51 /// Call finalize() to finish building the tree and consume the root node. 52 class syntax::TreeBuilder { 53 public: 54 TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) { 55 for (const auto &T : Arena.tokenBuffer().expandedTokens()) 56 LocationToToken.insert({T.location().getRawEncoding(), &T}); 57 } 58 59 llvm::BumpPtrAllocator &allocator() { return Arena.allocator(); } 60 61 /// Populate children for \p New node, assuming it covers tokens from \p 62 /// Range. 63 void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New); 64 65 /// Must be called with the range of each `DeclaratorDecl`. Ensures the 66 /// corresponding declarator nodes are covered by `SimpleDeclaration`. 67 void noticeDeclaratorRange(llvm::ArrayRef<syntax::Token> Range); 68 69 /// Notifies that we should not consume trailing semicolon when computing 70 /// token range of \p D. 71 void noticeDeclaratorWithoutSemicolon(Decl *D); 72 73 /// Mark the \p Child node with a corresponding \p Role. All marked children 74 /// should be consumed by foldNode. 75 /// (!) when called on expressions (clang::Expr is derived from clang::Stmt), 76 /// wraps expressions into expression statement. 77 void markStmtChild(Stmt *Child, NodeRole Role); 78 /// Should be called for expressions in non-statement position to avoid 79 /// wrapping into expression statement. 80 void markExprChild(Expr *Child, NodeRole Role); 81 82 /// Set role for a token starting at \p Loc. 83 void markChildToken(SourceLocation Loc, NodeRole R); 84 85 /// Finish building the tree and consume the root node. 86 syntax::TranslationUnit *finalize() && { 87 auto Tokens = Arena.tokenBuffer().expandedTokens(); 88 assert(!Tokens.empty()); 89 assert(Tokens.back().kind() == tok::eof); 90 91 // Build the root of the tree, consuming all the children. 92 Pending.foldChildren(Arena, Tokens.drop_back(), 93 new (Arena.allocator()) syntax::TranslationUnit); 94 95 return cast<syntax::TranslationUnit>(std::move(Pending).finalize()); 96 } 97 98 /// getRange() finds the syntax tokens corresponding to the passed source 99 /// locations. 100 /// \p First is the start position of the first token and \p Last is the start 101 /// position of the last token. 102 llvm::ArrayRef<syntax::Token> getRange(SourceLocation First, 103 SourceLocation Last) const { 104 assert(First.isValid()); 105 assert(Last.isValid()); 106 assert(First == Last || 107 Arena.sourceManager().isBeforeInTranslationUnit(First, Last)); 108 return llvm::makeArrayRef(findToken(First), std::next(findToken(Last))); 109 } 110 llvm::ArrayRef<syntax::Token> getRange(const Decl *D) const { 111 auto Tokens = getRange(D->getBeginLoc(), D->getEndLoc()); 112 if (llvm::isa<NamespaceDecl>(D)) 113 return Tokens; 114 if (DeclsWithoutSemicolons.count(D)) 115 return Tokens; 116 // FIXME: do not consume trailing semicolon on function definitions. 117 // Most declarations own a semicolon in syntax trees, but not in clang AST. 118 return withTrailingSemicolon(Tokens); 119 } 120 llvm::ArrayRef<syntax::Token> getExprRange(const Expr *E) const { 121 return getRange(E->getBeginLoc(), E->getEndLoc()); 122 } 123 /// Find the adjusted range for the statement, consuming the trailing 124 /// semicolon when needed. 125 llvm::ArrayRef<syntax::Token> getStmtRange(const Stmt *S) const { 126 auto Tokens = getRange(S->getBeginLoc(), S->getEndLoc()); 127 if (isa<CompoundStmt>(S)) 128 return Tokens; 129 130 // Some statements miss a trailing semicolon, e.g. 'return', 'continue' and 131 // all statements that end with those. Consume this semicolon here. 132 if (Tokens.back().kind() == tok::semi) 133 return Tokens; 134 return withTrailingSemicolon(Tokens); 135 } 136 137 private: 138 llvm::ArrayRef<syntax::Token> 139 withTrailingSemicolon(llvm::ArrayRef<syntax::Token> Tokens) const { 140 assert(!Tokens.empty()); 141 assert(Tokens.back().kind() != tok::eof); 142 // (!) we never consume 'eof', so looking at the next token is ok. 143 if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi) 144 return llvm::makeArrayRef(Tokens.begin(), Tokens.end() + 1); 145 return Tokens; 146 } 147 148 /// Finds a token starting at \p L. The token must exist. 149 const syntax::Token *findToken(SourceLocation L) const; 150 151 /// A collection of trees covering the input tokens. 152 /// When created, each tree corresponds to a single token in the file. 153 /// Clients call 'foldChildren' to attach one or more subtrees to a parent 154 /// node and update the list of trees accordingly. 155 /// 156 /// Ensures that added nodes properly nest and cover the whole token stream. 157 struct Forest { 158 Forest(syntax::Arena &A) { 159 assert(!A.tokenBuffer().expandedTokens().empty()); 160 assert(A.tokenBuffer().expandedTokens().back().kind() == tok::eof); 161 // Create all leaf nodes. 162 // Note that we do not have 'eof' in the tree. 163 for (auto &T : A.tokenBuffer().expandedTokens().drop_back()) { 164 auto *L = new (A.allocator()) syntax::Leaf(&T); 165 L->Original = true; 166 L->CanModify = A.tokenBuffer().spelledForExpanded(T).hasValue(); 167 Trees.insert(Trees.end(), {&T, NodeAndRole{L}}); 168 } 169 } 170 171 ~Forest() { assert(DelayedFolds.empty()); } 172 173 void assignRole(llvm::ArrayRef<syntax::Token> Range, 174 syntax::NodeRole Role) { 175 assert(!Range.empty()); 176 auto It = Trees.lower_bound(Range.begin()); 177 assert(It != Trees.end() && "no node found"); 178 assert(It->first == Range.begin() && "no child with the specified range"); 179 assert((std::next(It) == Trees.end() || 180 std::next(It)->first == Range.end()) && 181 "no child with the specified range"); 182 It->second.Role = Role; 183 } 184 185 /// Add \p Node to the forest and attach child nodes based on \p Tokens. 186 void foldChildren(const syntax::Arena &A, 187 llvm::ArrayRef<syntax::Token> Tokens, 188 syntax::Tree *Node) { 189 // Execute delayed folds inside `Tokens`. 190 auto BeginExecuted = DelayedFolds.lower_bound(Tokens.begin()); 191 auto It = BeginExecuted; 192 for (; It != DelayedFolds.end() && It->second.End <= Tokens.end(); ++It) 193 foldChildrenEager(A, llvm::makeArrayRef(It->first, It->second.End), 194 It->second.Node); 195 DelayedFolds.erase(BeginExecuted, It); 196 197 // Attach children to `Node`. 198 foldChildrenEager(A, Tokens, Node); 199 } 200 201 /// Schedule a call to `foldChildren` that will only be executed when 202 /// containing node is folded. The range of delayed nodes can be extended by 203 /// calling `extendDelayedFold`. Only one delayed node for each starting 204 /// token is allowed. 205 void foldChildrenDelayed(llvm::ArrayRef<syntax::Token> Tokens, 206 syntax::Tree *Node) { 207 assert(!Tokens.empty()); 208 bool Inserted = 209 DelayedFolds.insert({Tokens.begin(), DelayedFold{Tokens.end(), Node}}) 210 .second; 211 (void)Inserted; 212 assert(Inserted && "Multiple delayed folds start at the same token"); 213 } 214 215 /// If there a delayed fold, starting at `ExtendedRange.begin()`, extends 216 /// its endpoint to `ExtendedRange.end()` and returns true. 217 /// Otherwise, returns false. 218 bool extendDelayedFold(llvm::ArrayRef<syntax::Token> ExtendedRange) { 219 assert(!ExtendedRange.empty()); 220 auto It = DelayedFolds.find(ExtendedRange.data()); 221 if (It == DelayedFolds.end()) 222 return false; 223 assert(It->second.End <= ExtendedRange.end()); 224 It->second.End = ExtendedRange.end(); 225 return true; 226 } 227 228 // EXPECTS: all tokens were consumed and are owned by a single root node. 229 syntax::Node *finalize() && { 230 assert(Trees.size() == 1); 231 auto *Root = Trees.begin()->second.Node; 232 Trees = {}; 233 return Root; 234 } 235 236 std::string str(const syntax::Arena &A) const { 237 std::string R; 238 for (auto It = Trees.begin(); It != Trees.end(); ++It) { 239 unsigned CoveredTokens = 240 It != Trees.end() 241 ? (std::next(It)->first - It->first) 242 : A.tokenBuffer().expandedTokens().end() - It->first; 243 244 R += llvm::formatv("- '{0}' covers '{1}'+{2} tokens\n", 245 It->second.Node->kind(), 246 It->first->text(A.sourceManager()), CoveredTokens); 247 R += It->second.Node->dump(A); 248 } 249 return R; 250 } 251 252 private: 253 /// Implementation detail of `foldChildren`, does acutal folding ignoring 254 /// delayed folds. 255 void foldChildrenEager(const syntax::Arena &A, 256 llvm::ArrayRef<syntax::Token> Tokens, 257 syntax::Tree *Node) { 258 assert(Node->firstChild() == nullptr && "node already has children"); 259 260 auto *FirstToken = Tokens.begin(); 261 auto BeginChildren = Trees.lower_bound(FirstToken); 262 assert((BeginChildren == Trees.end() || 263 BeginChildren->first == FirstToken) && 264 "fold crosses boundaries of existing subtrees"); 265 auto EndChildren = Trees.lower_bound(Tokens.end()); 266 assert( 267 (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) && 268 "fold crosses boundaries of existing subtrees"); 269 270 // (!) we need to go in reverse order, because we can only prepend. 271 for (auto It = EndChildren; It != BeginChildren; --It) 272 Node->prependChildLowLevel(std::prev(It)->second.Node, 273 std::prev(It)->second.Role); 274 275 // Mark that this node came from the AST and is backed by the source code. 276 Node->Original = true; 277 Node->CanModify = A.tokenBuffer().spelledForExpanded(Tokens).hasValue(); 278 279 Trees.erase(BeginChildren, EndChildren); 280 Trees.insert({FirstToken, NodeAndRole(Node)}); 281 } 282 /// A with a role that should be assigned to it when adding to a parent. 283 struct NodeAndRole { 284 explicit NodeAndRole(syntax::Node *Node) 285 : Node(Node), Role(NodeRole::Unknown) {} 286 287 syntax::Node *Node; 288 NodeRole Role; 289 }; 290 291 /// Maps from the start token to a subtree starting at that token. 292 /// Keys in the map are pointers into the array of expanded tokens, so 293 /// pointer order corresponds to the order of preprocessor tokens. 294 /// FIXME: storing the end tokens is redundant. 295 /// FIXME: the key of a map is redundant, it is also stored in NodeForRange. 296 std::map<const syntax::Token *, NodeAndRole> Trees; 297 298 /// See documentation of `foldChildrenDelayed` for details. 299 struct DelayedFold { 300 const syntax::Token *End = nullptr; 301 syntax::Tree *Node = nullptr; 302 }; 303 std::map<const syntax::Token *, DelayedFold> DelayedFolds; 304 }; 305 306 /// For debugging purposes. 307 std::string str() { return Pending.str(Arena); } 308 309 syntax::Arena &Arena; 310 /// To quickly find tokens by their start location. 311 llvm::DenseMap</*SourceLocation*/ unsigned, const syntax::Token *> 312 LocationToToken; 313 Forest Pending; 314 llvm::DenseSet<Decl *> DeclsWithoutSemicolons; 315 }; 316 317 namespace { 318 class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> { 319 public: 320 explicit BuildTreeVisitor(ASTContext &Ctx, syntax::TreeBuilder &Builder) 321 : Builder(Builder), LangOpts(Ctx.getLangOpts()) {} 322 323 bool shouldTraversePostOrder() const { return true; } 324 325 bool WalkUpFromDeclaratorDecl(DeclaratorDecl *D) { 326 // Ensure declarators are covered by SimpleDeclaration. 327 Builder.noticeDeclaratorRange(Builder.getRange(D)); 328 // FIXME: build nodes for the declarator too. 329 return true; 330 } 331 bool WalkUpFromTypedefNameDecl(TypedefNameDecl *D) { 332 // Also a declarator. 333 Builder.noticeDeclaratorRange(Builder.getRange(D)); 334 // FIXME: build nodes for the declarator too. 335 return true; 336 } 337 338 bool VisitDecl(Decl *D) { 339 assert(!D->isImplicit()); 340 Builder.foldNode(Builder.getRange(D), 341 new (allocator()) syntax::UnknownDeclaration()); 342 return true; 343 } 344 345 bool WalkUpFromTagDecl(TagDecl *C) { 346 // Avoid building UnknownDeclaration here, syntatically 'struct X {}' and 347 // similar are part of declaration specifiers and do not introduce a new 348 // top-level declaration. 349 return true; 350 } 351 352 bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) { 353 // (!) we do not want to call VisitDecl(), the declaration for translation 354 // unit is built by finalize(). 355 return true; 356 } 357 358 bool WalkUpFromCompoundStmt(CompoundStmt *S) { 359 using NodeRole = syntax::NodeRole; 360 361 Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen); 362 for (auto *Child : S->body()) 363 Builder.markStmtChild(Child, NodeRole::CompoundStatement_statement); 364 Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen); 365 366 Builder.foldNode(Builder.getStmtRange(S), 367 new (allocator()) syntax::CompoundStatement); 368 return true; 369 } 370 371 // Some statements are not yet handled by syntax trees. 372 bool WalkUpFromStmt(Stmt *S) { 373 Builder.foldNode(Builder.getStmtRange(S), 374 new (allocator()) syntax::UnknownStatement); 375 return true; 376 } 377 378 bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) { 379 // We override to traverse range initializer as VarDecl. 380 // RAV traverses it as a statement, we produce invalid node kinds in that 381 // case. 382 // FIXME: should do this in RAV instead? 383 if (S->getInit() && !TraverseStmt(S->getInit())) 384 return false; 385 if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable())) 386 return false; 387 if (S->getRangeInit() && !TraverseStmt(S->getRangeInit())) 388 return false; 389 if (S->getBody() && !TraverseStmt(S->getBody())) 390 return false; 391 return true; 392 } 393 394 bool TraverseStmt(Stmt *S) { 395 if (auto *DS = llvm::dyn_cast_or_null<DeclStmt>(S)) { 396 // We want to consume the semicolon, make sure SimpleDeclaration does not. 397 for (auto *D : DS->decls()) 398 Builder.noticeDeclaratorWithoutSemicolon(D); 399 } else if (auto *E = llvm::dyn_cast_or_null<Expr>(S)) { 400 // (!) do not recurse into subexpressions. 401 // we do not have syntax trees for expressions yet, so we only want to see 402 // the first top-level expression. 403 return WalkUpFromExpr(E->IgnoreImplicit()); 404 } 405 return RecursiveASTVisitor::TraverseStmt(S); 406 } 407 408 // Some expressions are not yet handled by syntax trees. 409 bool WalkUpFromExpr(Expr *E) { 410 assert(!isImplicitExpr(E) && "should be handled by TraverseStmt"); 411 Builder.foldNode(Builder.getExprRange(E), 412 new (allocator()) syntax::UnknownExpression); 413 return true; 414 } 415 416 bool WalkUpFromNamespaceDecl(NamespaceDecl *S) { 417 auto Tokens = Builder.getRange(S); 418 if (Tokens.front().kind() == tok::coloncolon) { 419 // Handle nested namespace definitions. Those start at '::' token, e.g. 420 // namespace a^::b {} 421 // FIXME: build corresponding nodes for the name of this namespace. 422 return true; 423 } 424 Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition); 425 return true; 426 } 427 428 // The code below is very regular, it could even be generated with some 429 // preprocessor magic. We merely assign roles to the corresponding children 430 // and fold resulting nodes. 431 bool WalkUpFromDeclStmt(DeclStmt *S) { 432 Builder.foldNode(Builder.getStmtRange(S), 433 new (allocator()) syntax::DeclarationStatement); 434 return true; 435 } 436 437 bool WalkUpFromNullStmt(NullStmt *S) { 438 Builder.foldNode(Builder.getStmtRange(S), 439 new (allocator()) syntax::EmptyStatement); 440 return true; 441 } 442 443 bool WalkUpFromSwitchStmt(SwitchStmt *S) { 444 Builder.markChildToken(S->getSwitchLoc(), 445 syntax::NodeRole::IntroducerKeyword); 446 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 447 Builder.foldNode(Builder.getStmtRange(S), 448 new (allocator()) syntax::SwitchStatement); 449 return true; 450 } 451 452 bool WalkUpFromCaseStmt(CaseStmt *S) { 453 Builder.markChildToken(S->getKeywordLoc(), 454 syntax::NodeRole::IntroducerKeyword); 455 Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseStatement_value); 456 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 457 Builder.foldNode(Builder.getStmtRange(S), 458 new (allocator()) syntax::CaseStatement); 459 return true; 460 } 461 462 bool WalkUpFromDefaultStmt(DefaultStmt *S) { 463 Builder.markChildToken(S->getKeywordLoc(), 464 syntax::NodeRole::IntroducerKeyword); 465 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 466 Builder.foldNode(Builder.getStmtRange(S), 467 new (allocator()) syntax::DefaultStatement); 468 return true; 469 } 470 471 bool WalkUpFromIfStmt(IfStmt *S) { 472 Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword); 473 Builder.markStmtChild(S->getThen(), 474 syntax::NodeRole::IfStatement_thenStatement); 475 Builder.markChildToken(S->getElseLoc(), 476 syntax::NodeRole::IfStatement_elseKeyword); 477 Builder.markStmtChild(S->getElse(), 478 syntax::NodeRole::IfStatement_elseStatement); 479 Builder.foldNode(Builder.getStmtRange(S), 480 new (allocator()) syntax::IfStatement); 481 return true; 482 } 483 484 bool WalkUpFromForStmt(ForStmt *S) { 485 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 486 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 487 Builder.foldNode(Builder.getStmtRange(S), 488 new (allocator()) syntax::ForStatement); 489 return true; 490 } 491 492 bool WalkUpFromWhileStmt(WhileStmt *S) { 493 Builder.markChildToken(S->getWhileLoc(), 494 syntax::NodeRole::IntroducerKeyword); 495 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 496 Builder.foldNode(Builder.getStmtRange(S), 497 new (allocator()) syntax::WhileStatement); 498 return true; 499 } 500 501 bool WalkUpFromContinueStmt(ContinueStmt *S) { 502 Builder.markChildToken(S->getContinueLoc(), 503 syntax::NodeRole::IntroducerKeyword); 504 Builder.foldNode(Builder.getStmtRange(S), 505 new (allocator()) syntax::ContinueStatement); 506 return true; 507 } 508 509 bool WalkUpFromBreakStmt(BreakStmt *S) { 510 Builder.markChildToken(S->getBreakLoc(), 511 syntax::NodeRole::IntroducerKeyword); 512 Builder.foldNode(Builder.getStmtRange(S), 513 new (allocator()) syntax::BreakStatement); 514 return true; 515 } 516 517 bool WalkUpFromReturnStmt(ReturnStmt *S) { 518 Builder.markChildToken(S->getReturnLoc(), 519 syntax::NodeRole::IntroducerKeyword); 520 Builder.markExprChild(S->getRetValue(), 521 syntax::NodeRole::ReturnStatement_value); 522 Builder.foldNode(Builder.getStmtRange(S), 523 new (allocator()) syntax::ReturnStatement); 524 return true; 525 } 526 527 bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) { 528 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 529 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 530 Builder.foldNode(Builder.getStmtRange(S), 531 new (allocator()) syntax::RangeBasedForStatement); 532 return true; 533 } 534 535 bool WalkUpFromEmptyDecl(EmptyDecl *S) { 536 Builder.foldNode(Builder.getRange(S), 537 new (allocator()) syntax::EmptyDeclaration); 538 return true; 539 } 540 541 bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) { 542 Builder.markExprChild(S->getAssertExpr(), 543 syntax::NodeRole::StaticAssertDeclaration_condition); 544 Builder.markExprChild(S->getMessage(), 545 syntax::NodeRole::StaticAssertDeclaration_message); 546 Builder.foldNode(Builder.getRange(S), 547 new (allocator()) syntax::StaticAssertDeclaration); 548 return true; 549 } 550 551 bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) { 552 Builder.foldNode(Builder.getRange(S), 553 new (allocator()) syntax::LinkageSpecificationDeclaration); 554 return true; 555 } 556 557 bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) { 558 Builder.foldNode(Builder.getRange(S), 559 new (allocator()) syntax::NamespaceAliasDefinition); 560 return true; 561 } 562 563 bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) { 564 Builder.foldNode(Builder.getRange(S), 565 new (allocator()) syntax::UsingNamespaceDirective); 566 return true; 567 } 568 569 bool WalkUpFromUsingDecl(UsingDecl *S) { 570 Builder.foldNode(Builder.getRange(S), 571 new (allocator()) syntax::UsingDeclaration); 572 return true; 573 } 574 575 bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) { 576 Builder.foldNode(Builder.getRange(S), 577 new (allocator()) syntax::UsingDeclaration); 578 return true; 579 } 580 581 bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) { 582 Builder.foldNode(Builder.getRange(S), 583 new (allocator()) syntax::UsingDeclaration); 584 return true; 585 } 586 587 bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) { 588 Builder.foldNode(Builder.getRange(S), 589 new (allocator()) syntax::TypeAliasDeclaration); 590 return true; 591 } 592 593 private: 594 /// A small helper to save some typing. 595 llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); } 596 597 syntax::TreeBuilder &Builder; 598 const LangOptions &LangOpts; 599 }; 600 } // namespace 601 602 void syntax::TreeBuilder::foldNode(llvm::ArrayRef<syntax::Token> Range, 603 syntax::Tree *New) { 604 Pending.foldChildren(Arena, Range, New); 605 } 606 607 void syntax::TreeBuilder::noticeDeclaratorRange( 608 llvm::ArrayRef<syntax::Token> Range) { 609 if (Pending.extendDelayedFold(Range)) 610 return; 611 Pending.foldChildrenDelayed(Range, 612 new (allocator()) syntax::SimpleDeclaration); 613 } 614 615 void syntax::TreeBuilder::noticeDeclaratorWithoutSemicolon(Decl *D) { 616 DeclsWithoutSemicolons.insert(D); 617 } 618 619 void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) { 620 if (Loc.isInvalid()) 621 return; 622 Pending.assignRole(*findToken(Loc), Role); 623 } 624 625 void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) { 626 if (!Child) 627 return; 628 629 auto Range = getStmtRange(Child); 630 // This is an expression in a statement position, consume the trailing 631 // semicolon and form an 'ExpressionStatement' node. 632 if (auto *E = dyn_cast<Expr>(Child)) { 633 Pending.assignRole(getExprRange(E), 634 NodeRole::ExpressionStatement_expression); 635 // (!) 'getRange(Stmt)' ensures this already covers a trailing semicolon. 636 Pending.foldChildren(Arena, Range, 637 new (allocator()) syntax::ExpressionStatement); 638 } 639 Pending.assignRole(Range, Role); 640 } 641 642 void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) { 643 if (!Child) 644 return; 645 646 Pending.assignRole(getExprRange(Child), Role); 647 } 648 649 const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const { 650 auto It = LocationToToken.find(L.getRawEncoding()); 651 assert(It != LocationToToken.end()); 652 return It->second; 653 } 654 655 syntax::TranslationUnit * 656 syntax::buildSyntaxTree(Arena &A, const TranslationUnitDecl &TU) { 657 TreeBuilder Builder(A); 658 BuildTreeVisitor(TU.getASTContext(), Builder).TraverseAST(TU.getASTContext()); 659 return std::move(Builder).finalize(); 660 } 661