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 // FIXME: build the ClassSpecifier node. 347 if (C->isFreeStanding()) { 348 // Class is a declaration specifier and needs a spanning declaration node. 349 Builder.foldNode(Builder.getRange(C), 350 new (allocator()) syntax::SimpleDeclaration); 351 return true; 352 } 353 return true; 354 } 355 356 bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) { 357 // (!) we do not want to call VisitDecl(), the declaration for translation 358 // unit is built by finalize(). 359 return true; 360 } 361 362 bool WalkUpFromCompoundStmt(CompoundStmt *S) { 363 using NodeRole = syntax::NodeRole; 364 365 Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen); 366 for (auto *Child : S->body()) 367 Builder.markStmtChild(Child, NodeRole::CompoundStatement_statement); 368 Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen); 369 370 Builder.foldNode(Builder.getStmtRange(S), 371 new (allocator()) syntax::CompoundStatement); 372 return true; 373 } 374 375 // Some statements are not yet handled by syntax trees. 376 bool WalkUpFromStmt(Stmt *S) { 377 Builder.foldNode(Builder.getStmtRange(S), 378 new (allocator()) syntax::UnknownStatement); 379 return true; 380 } 381 382 bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) { 383 // We override to traverse range initializer as VarDecl. 384 // RAV traverses it as a statement, we produce invalid node kinds in that 385 // case. 386 // FIXME: should do this in RAV instead? 387 if (S->getInit() && !TraverseStmt(S->getInit())) 388 return false; 389 if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable())) 390 return false; 391 if (S->getRangeInit() && !TraverseStmt(S->getRangeInit())) 392 return false; 393 if (S->getBody() && !TraverseStmt(S->getBody())) 394 return false; 395 return true; 396 } 397 398 bool TraverseStmt(Stmt *S) { 399 if (auto *DS = llvm::dyn_cast_or_null<DeclStmt>(S)) { 400 // We want to consume the semicolon, make sure SimpleDeclaration does not. 401 for (auto *D : DS->decls()) 402 Builder.noticeDeclaratorWithoutSemicolon(D); 403 } else if (auto *E = llvm::dyn_cast_or_null<Expr>(S)) { 404 // (!) do not recurse into subexpressions. 405 // we do not have syntax trees for expressions yet, so we only want to see 406 // the first top-level expression. 407 return WalkUpFromExpr(E->IgnoreImplicit()); 408 } 409 return RecursiveASTVisitor::TraverseStmt(S); 410 } 411 412 // Some expressions are not yet handled by syntax trees. 413 bool WalkUpFromExpr(Expr *E) { 414 assert(!isImplicitExpr(E) && "should be handled by TraverseStmt"); 415 Builder.foldNode(Builder.getExprRange(E), 416 new (allocator()) syntax::UnknownExpression); 417 return true; 418 } 419 420 bool WalkUpFromNamespaceDecl(NamespaceDecl *S) { 421 auto Tokens = Builder.getRange(S); 422 if (Tokens.front().kind() == tok::coloncolon) { 423 // Handle nested namespace definitions. Those start at '::' token, e.g. 424 // namespace a^::b {} 425 // FIXME: build corresponding nodes for the name of this namespace. 426 return true; 427 } 428 Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition); 429 return true; 430 } 431 432 // The code below is very regular, it could even be generated with some 433 // preprocessor magic. We merely assign roles to the corresponding children 434 // and fold resulting nodes. 435 bool WalkUpFromDeclStmt(DeclStmt *S) { 436 Builder.foldNode(Builder.getStmtRange(S), 437 new (allocator()) syntax::DeclarationStatement); 438 return true; 439 } 440 441 bool WalkUpFromNullStmt(NullStmt *S) { 442 Builder.foldNode(Builder.getStmtRange(S), 443 new (allocator()) syntax::EmptyStatement); 444 return true; 445 } 446 447 bool WalkUpFromSwitchStmt(SwitchStmt *S) { 448 Builder.markChildToken(S->getSwitchLoc(), 449 syntax::NodeRole::IntroducerKeyword); 450 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 451 Builder.foldNode(Builder.getStmtRange(S), 452 new (allocator()) syntax::SwitchStatement); 453 return true; 454 } 455 456 bool WalkUpFromCaseStmt(CaseStmt *S) { 457 Builder.markChildToken(S->getKeywordLoc(), 458 syntax::NodeRole::IntroducerKeyword); 459 Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseStatement_value); 460 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 461 Builder.foldNode(Builder.getStmtRange(S), 462 new (allocator()) syntax::CaseStatement); 463 return true; 464 } 465 466 bool WalkUpFromDefaultStmt(DefaultStmt *S) { 467 Builder.markChildToken(S->getKeywordLoc(), 468 syntax::NodeRole::IntroducerKeyword); 469 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 470 Builder.foldNode(Builder.getStmtRange(S), 471 new (allocator()) syntax::DefaultStatement); 472 return true; 473 } 474 475 bool WalkUpFromIfStmt(IfStmt *S) { 476 Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword); 477 Builder.markStmtChild(S->getThen(), 478 syntax::NodeRole::IfStatement_thenStatement); 479 Builder.markChildToken(S->getElseLoc(), 480 syntax::NodeRole::IfStatement_elseKeyword); 481 Builder.markStmtChild(S->getElse(), 482 syntax::NodeRole::IfStatement_elseStatement); 483 Builder.foldNode(Builder.getStmtRange(S), 484 new (allocator()) syntax::IfStatement); 485 return true; 486 } 487 488 bool WalkUpFromForStmt(ForStmt *S) { 489 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 490 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 491 Builder.foldNode(Builder.getStmtRange(S), 492 new (allocator()) syntax::ForStatement); 493 return true; 494 } 495 496 bool WalkUpFromWhileStmt(WhileStmt *S) { 497 Builder.markChildToken(S->getWhileLoc(), 498 syntax::NodeRole::IntroducerKeyword); 499 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 500 Builder.foldNode(Builder.getStmtRange(S), 501 new (allocator()) syntax::WhileStatement); 502 return true; 503 } 504 505 bool WalkUpFromContinueStmt(ContinueStmt *S) { 506 Builder.markChildToken(S->getContinueLoc(), 507 syntax::NodeRole::IntroducerKeyword); 508 Builder.foldNode(Builder.getStmtRange(S), 509 new (allocator()) syntax::ContinueStatement); 510 return true; 511 } 512 513 bool WalkUpFromBreakStmt(BreakStmt *S) { 514 Builder.markChildToken(S->getBreakLoc(), 515 syntax::NodeRole::IntroducerKeyword); 516 Builder.foldNode(Builder.getStmtRange(S), 517 new (allocator()) syntax::BreakStatement); 518 return true; 519 } 520 521 bool WalkUpFromReturnStmt(ReturnStmt *S) { 522 Builder.markChildToken(S->getReturnLoc(), 523 syntax::NodeRole::IntroducerKeyword); 524 Builder.markExprChild(S->getRetValue(), 525 syntax::NodeRole::ReturnStatement_value); 526 Builder.foldNode(Builder.getStmtRange(S), 527 new (allocator()) syntax::ReturnStatement); 528 return true; 529 } 530 531 bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) { 532 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 533 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 534 Builder.foldNode(Builder.getStmtRange(S), 535 new (allocator()) syntax::RangeBasedForStatement); 536 return true; 537 } 538 539 bool WalkUpFromEmptyDecl(EmptyDecl *S) { 540 Builder.foldNode(Builder.getRange(S), 541 new (allocator()) syntax::EmptyDeclaration); 542 return true; 543 } 544 545 bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) { 546 Builder.markExprChild(S->getAssertExpr(), 547 syntax::NodeRole::StaticAssertDeclaration_condition); 548 Builder.markExprChild(S->getMessage(), 549 syntax::NodeRole::StaticAssertDeclaration_message); 550 Builder.foldNode(Builder.getRange(S), 551 new (allocator()) syntax::StaticAssertDeclaration); 552 return true; 553 } 554 555 bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) { 556 Builder.foldNode(Builder.getRange(S), 557 new (allocator()) syntax::LinkageSpecificationDeclaration); 558 return true; 559 } 560 561 bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) { 562 Builder.foldNode(Builder.getRange(S), 563 new (allocator()) syntax::NamespaceAliasDefinition); 564 return true; 565 } 566 567 bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) { 568 Builder.foldNode(Builder.getRange(S), 569 new (allocator()) syntax::UsingNamespaceDirective); 570 return true; 571 } 572 573 bool WalkUpFromUsingDecl(UsingDecl *S) { 574 Builder.foldNode(Builder.getRange(S), 575 new (allocator()) syntax::UsingDeclaration); 576 return true; 577 } 578 579 bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) { 580 Builder.foldNode(Builder.getRange(S), 581 new (allocator()) syntax::UsingDeclaration); 582 return true; 583 } 584 585 bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) { 586 Builder.foldNode(Builder.getRange(S), 587 new (allocator()) syntax::UsingDeclaration); 588 return true; 589 } 590 591 bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) { 592 Builder.foldNode(Builder.getRange(S), 593 new (allocator()) syntax::TypeAliasDeclaration); 594 return true; 595 } 596 597 private: 598 /// A small helper to save some typing. 599 llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); } 600 601 syntax::TreeBuilder &Builder; 602 const LangOptions &LangOpts; 603 }; 604 } // namespace 605 606 void syntax::TreeBuilder::foldNode(llvm::ArrayRef<syntax::Token> Range, 607 syntax::Tree *New) { 608 Pending.foldChildren(Arena, Range, New); 609 } 610 611 void syntax::TreeBuilder::noticeDeclaratorRange( 612 llvm::ArrayRef<syntax::Token> Range) { 613 if (Pending.extendDelayedFold(Range)) 614 return; 615 Pending.foldChildrenDelayed(Range, 616 new (allocator()) syntax::SimpleDeclaration); 617 } 618 619 void syntax::TreeBuilder::noticeDeclaratorWithoutSemicolon(Decl *D) { 620 DeclsWithoutSemicolons.insert(D); 621 } 622 623 void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) { 624 if (Loc.isInvalid()) 625 return; 626 Pending.assignRole(*findToken(Loc), Role); 627 } 628 629 void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) { 630 if (!Child) 631 return; 632 633 auto Range = getStmtRange(Child); 634 // This is an expression in a statement position, consume the trailing 635 // semicolon and form an 'ExpressionStatement' node. 636 if (auto *E = dyn_cast<Expr>(Child)) { 637 Pending.assignRole(getExprRange(E), 638 NodeRole::ExpressionStatement_expression); 639 // (!) 'getRange(Stmt)' ensures this already covers a trailing semicolon. 640 Pending.foldChildren(Arena, Range, 641 new (allocator()) syntax::ExpressionStatement); 642 } 643 Pending.assignRole(Range, Role); 644 } 645 646 void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) { 647 if (!Child) 648 return; 649 650 Pending.assignRole(getExprRange(Child), Role); 651 } 652 653 const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const { 654 auto It = LocationToToken.find(L.getRawEncoding()); 655 assert(It != LocationToToken.end()); 656 return It->second; 657 } 658 659 syntax::TranslationUnit * 660 syntax::buildSyntaxTree(Arena &A, const TranslationUnitDecl &TU) { 661 TreeBuilder Builder(A); 662 BuildTreeVisitor(TU.getASTContext(), Builder).TraverseAST(TU.getASTContext()); 663 return std::move(Builder).finalize(); 664 } 665