1e5dd7070Spatrick //===- BuildTree.cpp ------------------------------------------*- C++ -*-=====// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick #include "clang/Tooling/Syntax/BuildTree.h" 9ec727ea7Spatrick #include "clang/AST/ASTFwd.h" 10e5dd7070Spatrick #include "clang/AST/Decl.h" 11e5dd7070Spatrick #include "clang/AST/DeclBase.h" 12ec727ea7Spatrick #include "clang/AST/DeclCXX.h" 13ec727ea7Spatrick #include "clang/AST/DeclarationName.h" 14ec727ea7Spatrick #include "clang/AST/Expr.h" 15ec727ea7Spatrick #include "clang/AST/ExprCXX.h" 16*a9ac8606Spatrick #include "clang/AST/IgnoreExpr.h" 17*a9ac8606Spatrick #include "clang/AST/OperationKinds.h" 18e5dd7070Spatrick #include "clang/AST/RecursiveASTVisitor.h" 19e5dd7070Spatrick #include "clang/AST/Stmt.h" 20ec727ea7Spatrick #include "clang/AST/TypeLoc.h" 21ec727ea7Spatrick #include "clang/AST/TypeLocVisitor.h" 22e5dd7070Spatrick #include "clang/Basic/LLVM.h" 23e5dd7070Spatrick #include "clang/Basic/SourceLocation.h" 24e5dd7070Spatrick #include "clang/Basic/SourceManager.h" 25ec727ea7Spatrick #include "clang/Basic/Specifiers.h" 26e5dd7070Spatrick #include "clang/Basic/TokenKinds.h" 27e5dd7070Spatrick #include "clang/Lex/Lexer.h" 28ec727ea7Spatrick #include "clang/Lex/LiteralSupport.h" 29e5dd7070Spatrick #include "clang/Tooling/Syntax/Nodes.h" 30e5dd7070Spatrick #include "clang/Tooling/Syntax/Tokens.h" 31e5dd7070Spatrick #include "clang/Tooling/Syntax/Tree.h" 32e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h" 33ec727ea7Spatrick #include "llvm/ADT/DenseMap.h" 34ec727ea7Spatrick #include "llvm/ADT/PointerUnion.h" 35e5dd7070Spatrick #include "llvm/ADT/STLExtras.h" 36ec727ea7Spatrick #include "llvm/ADT/ScopeExit.h" 37e5dd7070Spatrick #include "llvm/ADT/SmallVector.h" 38e5dd7070Spatrick #include "llvm/Support/Allocator.h" 39e5dd7070Spatrick #include "llvm/Support/Casting.h" 40e5dd7070Spatrick #include "llvm/Support/Compiler.h" 41e5dd7070Spatrick #include "llvm/Support/FormatVariadic.h" 42e5dd7070Spatrick #include "llvm/Support/MemoryBuffer.h" 43e5dd7070Spatrick #include "llvm/Support/raw_ostream.h" 44ec727ea7Spatrick #include <cstddef> 45e5dd7070Spatrick #include <map> 46e5dd7070Spatrick 47e5dd7070Spatrick using namespace clang; 48e5dd7070Spatrick 49*a9ac8606Spatrick // Ignores the implicit `CXXConstructExpr` for copy/move constructor calls 50*a9ac8606Spatrick // generated by the compiler, as well as in implicit conversions like the one 51*a9ac8606Spatrick // wrapping `1` in `X x = 1;`. 52*a9ac8606Spatrick static Expr *IgnoreImplicitConstructorSingleStep(Expr *E) { 53*a9ac8606Spatrick if (auto *C = dyn_cast<CXXConstructExpr>(E)) { 54*a9ac8606Spatrick auto NumArgs = C->getNumArgs(); 55*a9ac8606Spatrick if (NumArgs == 1 || (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) { 56*a9ac8606Spatrick Expr *A = C->getArg(0); 57*a9ac8606Spatrick if (C->getParenOrBraceRange().isInvalid()) 58*a9ac8606Spatrick return A; 59*a9ac8606Spatrick } 60*a9ac8606Spatrick } 61*a9ac8606Spatrick return E; 62*a9ac8606Spatrick } 63*a9ac8606Spatrick 64*a9ac8606Spatrick // In: 65*a9ac8606Spatrick // struct X { 66*a9ac8606Spatrick // X(int) 67*a9ac8606Spatrick // }; 68*a9ac8606Spatrick // X x = X(1); 69*a9ac8606Spatrick // Ignores the implicit `CXXFunctionalCastExpr` that wraps 70*a9ac8606Spatrick // `CXXConstructExpr X(1)`. 71*a9ac8606Spatrick static Expr *IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E) { 72*a9ac8606Spatrick if (auto *F = dyn_cast<CXXFunctionalCastExpr>(E)) { 73*a9ac8606Spatrick if (F->getCastKind() == CK_ConstructorConversion) 74*a9ac8606Spatrick return F->getSubExpr(); 75*a9ac8606Spatrick } 76*a9ac8606Spatrick return E; 77*a9ac8606Spatrick } 78*a9ac8606Spatrick 79*a9ac8606Spatrick static Expr *IgnoreImplicit(Expr *E) { 80*a9ac8606Spatrick return IgnoreExprNodes(E, IgnoreImplicitSingleStep, 81*a9ac8606Spatrick IgnoreImplicitConstructorSingleStep, 82*a9ac8606Spatrick IgnoreCXXFunctionalCastExprWrappingConstructor); 83*a9ac8606Spatrick } 84*a9ac8606Spatrick 85e5dd7070Spatrick LLVM_ATTRIBUTE_UNUSED 86*a9ac8606Spatrick static bool isImplicitExpr(Expr *E) { return IgnoreImplicit(E) != E; } 87e5dd7070Spatrick 88ec727ea7Spatrick namespace { 89ec727ea7Spatrick /// Get start location of the Declarator from the TypeLoc. 90ec727ea7Spatrick /// E.g.: 91ec727ea7Spatrick /// loc of `(` in `int (a)` 92ec727ea7Spatrick /// loc of `*` in `int *(a)` 93ec727ea7Spatrick /// loc of the first `(` in `int (*a)(int)` 94ec727ea7Spatrick /// loc of the `*` in `int *(a)(int)` 95ec727ea7Spatrick /// loc of the first `*` in `const int *const *volatile a;` 96ec727ea7Spatrick /// 97ec727ea7Spatrick /// It is non-trivial to get the start location because TypeLocs are stored 98ec727ea7Spatrick /// inside out. In the example above `*volatile` is the TypeLoc returned 99ec727ea7Spatrick /// by `Decl.getTypeSourceInfo()`, and `*const` is what `.getPointeeLoc()` 100ec727ea7Spatrick /// returns. 101ec727ea7Spatrick struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> { 102ec727ea7Spatrick SourceLocation VisitParenTypeLoc(ParenTypeLoc T) { 103ec727ea7Spatrick auto L = Visit(T.getInnerLoc()); 104ec727ea7Spatrick if (L.isValid()) 105ec727ea7Spatrick return L; 106ec727ea7Spatrick return T.getLParenLoc(); 107ec727ea7Spatrick } 108ec727ea7Spatrick 109ec727ea7Spatrick // Types spelled in the prefix part of the declarator. 110ec727ea7Spatrick SourceLocation VisitPointerTypeLoc(PointerTypeLoc T) { 111ec727ea7Spatrick return HandlePointer(T); 112ec727ea7Spatrick } 113ec727ea7Spatrick 114ec727ea7Spatrick SourceLocation VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) { 115ec727ea7Spatrick return HandlePointer(T); 116ec727ea7Spatrick } 117ec727ea7Spatrick 118ec727ea7Spatrick SourceLocation VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) { 119ec727ea7Spatrick return HandlePointer(T); 120ec727ea7Spatrick } 121ec727ea7Spatrick 122ec727ea7Spatrick SourceLocation VisitReferenceTypeLoc(ReferenceTypeLoc T) { 123ec727ea7Spatrick return HandlePointer(T); 124ec727ea7Spatrick } 125ec727ea7Spatrick 126ec727ea7Spatrick SourceLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc T) { 127ec727ea7Spatrick return HandlePointer(T); 128ec727ea7Spatrick } 129ec727ea7Spatrick 130ec727ea7Spatrick // All other cases are not important, as they are either part of declaration 131ec727ea7Spatrick // specifiers (e.g. inheritors of TypeSpecTypeLoc) or introduce modifiers on 132ec727ea7Spatrick // existing declarators (e.g. QualifiedTypeLoc). They cannot start the 133ec727ea7Spatrick // declarator themselves, but their underlying type can. 134ec727ea7Spatrick SourceLocation VisitTypeLoc(TypeLoc T) { 135ec727ea7Spatrick auto N = T.getNextTypeLoc(); 136ec727ea7Spatrick if (!N) 137ec727ea7Spatrick return SourceLocation(); 138ec727ea7Spatrick return Visit(N); 139ec727ea7Spatrick } 140ec727ea7Spatrick 141ec727ea7Spatrick SourceLocation VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc T) { 142ec727ea7Spatrick if (T.getTypePtr()->hasTrailingReturn()) 143ec727ea7Spatrick return SourceLocation(); // avoid recursing into the suffix of declarator. 144ec727ea7Spatrick return VisitTypeLoc(T); 145ec727ea7Spatrick } 146ec727ea7Spatrick 147ec727ea7Spatrick private: 148ec727ea7Spatrick template <class PtrLoc> SourceLocation HandlePointer(PtrLoc T) { 149ec727ea7Spatrick auto L = Visit(T.getPointeeLoc()); 150ec727ea7Spatrick if (L.isValid()) 151ec727ea7Spatrick return L; 152ec727ea7Spatrick return T.getLocalSourceRange().getBegin(); 153ec727ea7Spatrick } 154ec727ea7Spatrick }; 155ec727ea7Spatrick } // namespace 156ec727ea7Spatrick 157*a9ac8606Spatrick static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) { 158*a9ac8606Spatrick auto FirstDefaultArg = std::find_if(Args.begin(), Args.end(), [](auto It) { 159*a9ac8606Spatrick return isa<CXXDefaultArgExpr>(It); 160*a9ac8606Spatrick }); 161*a9ac8606Spatrick return llvm::make_range(Args.begin(), FirstDefaultArg); 162*a9ac8606Spatrick } 163*a9ac8606Spatrick 164ec727ea7Spatrick static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { 165ec727ea7Spatrick switch (E.getOperator()) { 166ec727ea7Spatrick // Comparison 167ec727ea7Spatrick case OO_EqualEqual: 168ec727ea7Spatrick case OO_ExclaimEqual: 169ec727ea7Spatrick case OO_Greater: 170ec727ea7Spatrick case OO_GreaterEqual: 171ec727ea7Spatrick case OO_Less: 172ec727ea7Spatrick case OO_LessEqual: 173ec727ea7Spatrick case OO_Spaceship: 174ec727ea7Spatrick // Assignment 175ec727ea7Spatrick case OO_Equal: 176ec727ea7Spatrick case OO_SlashEqual: 177ec727ea7Spatrick case OO_PercentEqual: 178ec727ea7Spatrick case OO_CaretEqual: 179ec727ea7Spatrick case OO_PipeEqual: 180ec727ea7Spatrick case OO_LessLessEqual: 181ec727ea7Spatrick case OO_GreaterGreaterEqual: 182ec727ea7Spatrick case OO_PlusEqual: 183ec727ea7Spatrick case OO_MinusEqual: 184ec727ea7Spatrick case OO_StarEqual: 185ec727ea7Spatrick case OO_AmpEqual: 186ec727ea7Spatrick // Binary computation 187ec727ea7Spatrick case OO_Slash: 188ec727ea7Spatrick case OO_Percent: 189ec727ea7Spatrick case OO_Caret: 190ec727ea7Spatrick case OO_Pipe: 191ec727ea7Spatrick case OO_LessLess: 192ec727ea7Spatrick case OO_GreaterGreater: 193ec727ea7Spatrick case OO_AmpAmp: 194ec727ea7Spatrick case OO_PipePipe: 195ec727ea7Spatrick case OO_ArrowStar: 196ec727ea7Spatrick case OO_Comma: 197ec727ea7Spatrick return syntax::NodeKind::BinaryOperatorExpression; 198ec727ea7Spatrick case OO_Tilde: 199ec727ea7Spatrick case OO_Exclaim: 200ec727ea7Spatrick return syntax::NodeKind::PrefixUnaryOperatorExpression; 201ec727ea7Spatrick // Prefix/Postfix increment/decrement 202ec727ea7Spatrick case OO_PlusPlus: 203ec727ea7Spatrick case OO_MinusMinus: 204ec727ea7Spatrick switch (E.getNumArgs()) { 205ec727ea7Spatrick case 1: 206ec727ea7Spatrick return syntax::NodeKind::PrefixUnaryOperatorExpression; 207ec727ea7Spatrick case 2: 208ec727ea7Spatrick return syntax::NodeKind::PostfixUnaryOperatorExpression; 209ec727ea7Spatrick default: 210ec727ea7Spatrick llvm_unreachable("Invalid number of arguments for operator"); 211ec727ea7Spatrick } 212ec727ea7Spatrick // Operators that can be unary or binary 213ec727ea7Spatrick case OO_Plus: 214ec727ea7Spatrick case OO_Minus: 215ec727ea7Spatrick case OO_Star: 216ec727ea7Spatrick case OO_Amp: 217ec727ea7Spatrick switch (E.getNumArgs()) { 218ec727ea7Spatrick case 1: 219ec727ea7Spatrick return syntax::NodeKind::PrefixUnaryOperatorExpression; 220ec727ea7Spatrick case 2: 221ec727ea7Spatrick return syntax::NodeKind::BinaryOperatorExpression; 222ec727ea7Spatrick default: 223ec727ea7Spatrick llvm_unreachable("Invalid number of arguments for operator"); 224ec727ea7Spatrick } 225ec727ea7Spatrick return syntax::NodeKind::BinaryOperatorExpression; 226ec727ea7Spatrick // Not yet supported by SyntaxTree 227ec727ea7Spatrick case OO_New: 228ec727ea7Spatrick case OO_Delete: 229ec727ea7Spatrick case OO_Array_New: 230ec727ea7Spatrick case OO_Array_Delete: 231ec727ea7Spatrick case OO_Coawait: 232ec727ea7Spatrick case OO_Subscript: 233ec727ea7Spatrick case OO_Arrow: 234ec727ea7Spatrick return syntax::NodeKind::UnknownExpression; 235*a9ac8606Spatrick case OO_Call: 236*a9ac8606Spatrick return syntax::NodeKind::CallExpression; 237ec727ea7Spatrick case OO_Conditional: // not overloadable 238ec727ea7Spatrick case NUM_OVERLOADED_OPERATORS: 239ec727ea7Spatrick case OO_None: 240ec727ea7Spatrick llvm_unreachable("Not an overloadable operator"); 241ec727ea7Spatrick } 242ec727ea7Spatrick llvm_unreachable("Unknown OverloadedOperatorKind enum"); 243ec727ea7Spatrick } 244ec727ea7Spatrick 245*a9ac8606Spatrick /// Get the start of the qualified name. In the examples below it gives the 246*a9ac8606Spatrick /// location of the `^`: 247*a9ac8606Spatrick /// `int ^a;` 248*a9ac8606Spatrick /// `int *^a;` 249*a9ac8606Spatrick /// `int ^a::S::f(){}` 250*a9ac8606Spatrick static SourceLocation getQualifiedNameStart(NamedDecl *D) { 251*a9ac8606Spatrick assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) && 252*a9ac8606Spatrick "only DeclaratorDecl and TypedefNameDecl are supported."); 253*a9ac8606Spatrick 254*a9ac8606Spatrick auto DN = D->getDeclName(); 255*a9ac8606Spatrick bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo(); 256*a9ac8606Spatrick if (IsAnonymous) 257*a9ac8606Spatrick return SourceLocation(); 258*a9ac8606Spatrick 259*a9ac8606Spatrick if (const auto *DD = dyn_cast<DeclaratorDecl>(D)) { 260*a9ac8606Spatrick if (DD->getQualifierLoc()) { 261*a9ac8606Spatrick return DD->getQualifierLoc().getBeginLoc(); 262*a9ac8606Spatrick } 263*a9ac8606Spatrick } 264*a9ac8606Spatrick 265*a9ac8606Spatrick return D->getLocation(); 266*a9ac8606Spatrick } 267*a9ac8606Spatrick 268*a9ac8606Spatrick /// Gets the range of the initializer inside an init-declarator C++ [dcl.decl]. 269*a9ac8606Spatrick /// `int a;` -> range of ``, 270*a9ac8606Spatrick /// `int *a = nullptr` -> range of `= nullptr`. 271*a9ac8606Spatrick /// `int a{}` -> range of `{}`. 272*a9ac8606Spatrick /// `int a()` -> range of `()`. 273*a9ac8606Spatrick static SourceRange getInitializerRange(Decl *D) { 274*a9ac8606Spatrick if (auto *V = dyn_cast<VarDecl>(D)) { 275*a9ac8606Spatrick auto *I = V->getInit(); 276*a9ac8606Spatrick // Initializers in range-based-for are not part of the declarator 277*a9ac8606Spatrick if (I && !V->isCXXForRangeDecl()) 278*a9ac8606Spatrick return I->getSourceRange(); 279*a9ac8606Spatrick } 280*a9ac8606Spatrick 281*a9ac8606Spatrick return SourceRange(); 282*a9ac8606Spatrick } 283*a9ac8606Spatrick 284ec727ea7Spatrick /// Gets the range of declarator as defined by the C++ grammar. E.g. 285ec727ea7Spatrick /// `int a;` -> range of `a`, 286ec727ea7Spatrick /// `int *a;` -> range of `*a`, 287ec727ea7Spatrick /// `int a[10];` -> range of `a[10]`, 288ec727ea7Spatrick /// `int a[1][2][3];` -> range of `a[1][2][3]`, 289ec727ea7Spatrick /// `int *a = nullptr` -> range of `*a = nullptr`. 290*a9ac8606Spatrick /// `int S::f(){}` -> range of `S::f()`. 291*a9ac8606Spatrick /// FIXME: \p Name must be a source range. 292ec727ea7Spatrick static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, 293ec727ea7Spatrick SourceLocation Name, 294ec727ea7Spatrick SourceRange Initializer) { 295ec727ea7Spatrick SourceLocation Start = GetStartLoc().Visit(T); 296*a9ac8606Spatrick SourceLocation End = T.getEndLoc(); 297ec727ea7Spatrick if (Name.isValid()) { 298ec727ea7Spatrick if (Start.isInvalid()) 299ec727ea7Spatrick Start = Name; 300*a9ac8606Spatrick // End of TypeLoc could be invalid if the type is invalid, fallback to the 301*a9ac8606Spatrick // NameLoc. 302*a9ac8606Spatrick if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name)) 303ec727ea7Spatrick End = Name; 304ec727ea7Spatrick } 305ec727ea7Spatrick if (Initializer.isValid()) { 306ec727ea7Spatrick auto InitializerEnd = Initializer.getEnd(); 307ec727ea7Spatrick assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) || 308ec727ea7Spatrick End == InitializerEnd); 309ec727ea7Spatrick End = InitializerEnd; 310ec727ea7Spatrick } 311ec727ea7Spatrick return SourceRange(Start, End); 312ec727ea7Spatrick } 313ec727ea7Spatrick 314ec727ea7Spatrick namespace { 315ec727ea7Spatrick /// All AST hierarchy roots that can be represented as pointers. 316ec727ea7Spatrick using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>; 317ec727ea7Spatrick /// Maintains a mapping from AST to syntax tree nodes. This class will get more 318ec727ea7Spatrick /// complicated as we support more kinds of AST nodes, e.g. TypeLocs. 319ec727ea7Spatrick /// FIXME: expose this as public API. 320ec727ea7Spatrick class ASTToSyntaxMapping { 321ec727ea7Spatrick public: 322ec727ea7Spatrick void add(ASTPtr From, syntax::Tree *To) { 323ec727ea7Spatrick assert(To != nullptr); 324ec727ea7Spatrick assert(!From.isNull()); 325ec727ea7Spatrick 326ec727ea7Spatrick bool Added = Nodes.insert({From, To}).second; 327ec727ea7Spatrick (void)Added; 328ec727ea7Spatrick assert(Added && "mapping added twice"); 329ec727ea7Spatrick } 330ec727ea7Spatrick 331*a9ac8606Spatrick void add(NestedNameSpecifierLoc From, syntax::Tree *To) { 332*a9ac8606Spatrick assert(To != nullptr); 333*a9ac8606Spatrick assert(From.hasQualifier()); 334*a9ac8606Spatrick 335*a9ac8606Spatrick bool Added = NNSNodes.insert({From, To}).second; 336*a9ac8606Spatrick (void)Added; 337*a9ac8606Spatrick assert(Added && "mapping added twice"); 338*a9ac8606Spatrick } 339*a9ac8606Spatrick 340ec727ea7Spatrick syntax::Tree *find(ASTPtr P) const { return Nodes.lookup(P); } 341ec727ea7Spatrick 342*a9ac8606Spatrick syntax::Tree *find(NestedNameSpecifierLoc P) const { 343*a9ac8606Spatrick return NNSNodes.lookup(P); 344*a9ac8606Spatrick } 345*a9ac8606Spatrick 346ec727ea7Spatrick private: 347ec727ea7Spatrick llvm::DenseMap<ASTPtr, syntax::Tree *> Nodes; 348*a9ac8606Spatrick llvm::DenseMap<NestedNameSpecifierLoc, syntax::Tree *> NNSNodes; 349ec727ea7Spatrick }; 350ec727ea7Spatrick } // namespace 351ec727ea7Spatrick 352e5dd7070Spatrick /// A helper class for constructing the syntax tree while traversing a clang 353e5dd7070Spatrick /// AST. 354e5dd7070Spatrick /// 355e5dd7070Spatrick /// At each point of the traversal we maintain a list of pending nodes. 356e5dd7070Spatrick /// Initially all tokens are added as pending nodes. When processing a clang AST 357e5dd7070Spatrick /// node, the clients need to: 358e5dd7070Spatrick /// - create a corresponding syntax node, 359e5dd7070Spatrick /// - assign roles to all pending child nodes with 'markChild' and 360e5dd7070Spatrick /// 'markChildToken', 361e5dd7070Spatrick /// - replace the child nodes with the new syntax node in the pending list 362e5dd7070Spatrick /// with 'foldNode'. 363e5dd7070Spatrick /// 364e5dd7070Spatrick /// Note that all children are expected to be processed when building a node. 365e5dd7070Spatrick /// 366e5dd7070Spatrick /// Call finalize() to finish building the tree and consume the root node. 367e5dd7070Spatrick class syntax::TreeBuilder { 368e5dd7070Spatrick public: 369e5dd7070Spatrick TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) { 370*a9ac8606Spatrick for (const auto &T : Arena.getTokenBuffer().expandedTokens()) 371*a9ac8606Spatrick LocationToToken.insert({T.location(), &T}); 372e5dd7070Spatrick } 373e5dd7070Spatrick 374*a9ac8606Spatrick llvm::BumpPtrAllocator &allocator() { return Arena.getAllocator(); } 375*a9ac8606Spatrick const SourceManager &sourceManager() const { 376*a9ac8606Spatrick return Arena.getSourceManager(); 377*a9ac8606Spatrick } 378e5dd7070Spatrick 379e5dd7070Spatrick /// Populate children for \p New node, assuming it covers tokens from \p 380e5dd7070Spatrick /// Range. 381*a9ac8606Spatrick void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, ASTPtr From) { 382ec727ea7Spatrick assert(New); 383ec727ea7Spatrick Pending.foldChildren(Arena, Range, New); 384ec727ea7Spatrick if (From) 385ec727ea7Spatrick Mapping.add(From, New); 386ec727ea7Spatrick } 387*a9ac8606Spatrick 388*a9ac8606Spatrick void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, TypeLoc L) { 389ec727ea7Spatrick // FIXME: add mapping for TypeLocs 390ec727ea7Spatrick foldNode(Range, New, nullptr); 391ec727ea7Spatrick } 392e5dd7070Spatrick 393*a9ac8606Spatrick void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New, 394*a9ac8606Spatrick NestedNameSpecifierLoc From) { 395*a9ac8606Spatrick assert(New); 396*a9ac8606Spatrick Pending.foldChildren(Arena, Range, New); 397*a9ac8606Spatrick if (From) 398*a9ac8606Spatrick Mapping.add(From, New); 399*a9ac8606Spatrick } 400*a9ac8606Spatrick 401*a9ac8606Spatrick /// Populate children for \p New list, assuming it covers tokens from a 402*a9ac8606Spatrick /// subrange of \p SuperRange. 403*a9ac8606Spatrick void foldList(ArrayRef<syntax::Token> SuperRange, syntax::List *New, 404*a9ac8606Spatrick ASTPtr From) { 405*a9ac8606Spatrick assert(New); 406*a9ac8606Spatrick auto ListRange = Pending.shrinkToFitList(SuperRange); 407*a9ac8606Spatrick Pending.foldChildren(Arena, ListRange, New); 408*a9ac8606Spatrick if (From) 409*a9ac8606Spatrick Mapping.add(From, New); 410*a9ac8606Spatrick } 411*a9ac8606Spatrick 412e5dd7070Spatrick /// Notifies that we should not consume trailing semicolon when computing 413e5dd7070Spatrick /// token range of \p D. 414ec727ea7Spatrick void noticeDeclWithoutSemicolon(Decl *D); 415e5dd7070Spatrick 416e5dd7070Spatrick /// Mark the \p Child node with a corresponding \p Role. All marked children 417e5dd7070Spatrick /// should be consumed by foldNode. 418ec727ea7Spatrick /// When called on expressions (clang::Expr is derived from clang::Stmt), 419e5dd7070Spatrick /// wraps expressions into expression statement. 420e5dd7070Spatrick void markStmtChild(Stmt *Child, NodeRole Role); 421e5dd7070Spatrick /// Should be called for expressions in non-statement position to avoid 422e5dd7070Spatrick /// wrapping into expression statement. 423e5dd7070Spatrick void markExprChild(Expr *Child, NodeRole Role); 424e5dd7070Spatrick /// Set role for a token starting at \p Loc. 425e5dd7070Spatrick void markChildToken(SourceLocation Loc, NodeRole R); 426ec727ea7Spatrick /// Set role for \p T. 427ec727ea7Spatrick void markChildToken(const syntax::Token *T, NodeRole R); 428ec727ea7Spatrick 429ec727ea7Spatrick /// Set role for \p N. 430ec727ea7Spatrick void markChild(syntax::Node *N, NodeRole R); 431ec727ea7Spatrick /// Set role for the syntax node matching \p N. 432ec727ea7Spatrick void markChild(ASTPtr N, NodeRole R); 433*a9ac8606Spatrick /// Set role for the syntax node matching \p N. 434*a9ac8606Spatrick void markChild(NestedNameSpecifierLoc N, NodeRole R); 435e5dd7070Spatrick 436e5dd7070Spatrick /// Finish building the tree and consume the root node. 437e5dd7070Spatrick syntax::TranslationUnit *finalize() && { 438*a9ac8606Spatrick auto Tokens = Arena.getTokenBuffer().expandedTokens(); 439e5dd7070Spatrick assert(!Tokens.empty()); 440e5dd7070Spatrick assert(Tokens.back().kind() == tok::eof); 441e5dd7070Spatrick 442e5dd7070Spatrick // Build the root of the tree, consuming all the children. 443e5dd7070Spatrick Pending.foldChildren(Arena, Tokens.drop_back(), 444*a9ac8606Spatrick new (Arena.getAllocator()) syntax::TranslationUnit); 445e5dd7070Spatrick 446e5dd7070Spatrick auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).finalize()); 447e5dd7070Spatrick TU->assertInvariantsRecursive(); 448e5dd7070Spatrick return TU; 449e5dd7070Spatrick } 450e5dd7070Spatrick 451ec727ea7Spatrick /// Finds a token starting at \p L. The token must exist if \p L is valid. 452ec727ea7Spatrick const syntax::Token *findToken(SourceLocation L) const; 453ec727ea7Spatrick 454ec727ea7Spatrick /// Finds the syntax tokens corresponding to the \p SourceRange. 455*a9ac8606Spatrick ArrayRef<syntax::Token> getRange(SourceRange Range) const { 456ec727ea7Spatrick assert(Range.isValid()); 457ec727ea7Spatrick return getRange(Range.getBegin(), Range.getEnd()); 458ec727ea7Spatrick } 459ec727ea7Spatrick 460ec727ea7Spatrick /// Finds the syntax tokens corresponding to the passed source locations. 461e5dd7070Spatrick /// \p First is the start position of the first token and \p Last is the start 462e5dd7070Spatrick /// position of the last token. 463*a9ac8606Spatrick ArrayRef<syntax::Token> getRange(SourceLocation First, 464e5dd7070Spatrick SourceLocation Last) const { 465e5dd7070Spatrick assert(First.isValid()); 466e5dd7070Spatrick assert(Last.isValid()); 467e5dd7070Spatrick assert(First == Last || 468*a9ac8606Spatrick Arena.getSourceManager().isBeforeInTranslationUnit(First, Last)); 469e5dd7070Spatrick return llvm::makeArrayRef(findToken(First), std::next(findToken(Last))); 470e5dd7070Spatrick } 471ec727ea7Spatrick 472*a9ac8606Spatrick ArrayRef<syntax::Token> 473ec727ea7Spatrick getTemplateRange(const ClassTemplateSpecializationDecl *D) const { 474ec727ea7Spatrick auto Tokens = getRange(D->getSourceRange()); 475ec727ea7Spatrick return maybeAppendSemicolon(Tokens, D); 476e5dd7070Spatrick } 477ec727ea7Spatrick 478ec727ea7Spatrick /// Returns true if \p D is the last declarator in a chain and is thus 479ec727ea7Spatrick /// reponsible for creating SimpleDeclaration for the whole chain. 480*a9ac8606Spatrick bool isResponsibleForCreatingDeclaration(const Decl *D) const { 481*a9ac8606Spatrick assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) && 482ec727ea7Spatrick "only DeclaratorDecl and TypedefNameDecl are supported."); 483ec727ea7Spatrick 484ec727ea7Spatrick const Decl *Next = D->getNextDeclInContext(); 485ec727ea7Spatrick 486ec727ea7Spatrick // There's no next sibling, this one is responsible. 487ec727ea7Spatrick if (Next == nullptr) { 488ec727ea7Spatrick return true; 489ec727ea7Spatrick } 490ec727ea7Spatrick 491ec727ea7Spatrick // Next sibling is not the same type, this one is responsible. 492*a9ac8606Spatrick if (D->getKind() != Next->getKind()) { 493ec727ea7Spatrick return true; 494ec727ea7Spatrick } 495ec727ea7Spatrick // Next sibling doesn't begin at the same loc, it must be a different 496ec727ea7Spatrick // declaration, so this declarator is responsible. 497*a9ac8606Spatrick if (Next->getBeginLoc() != D->getBeginLoc()) { 498ec727ea7Spatrick return true; 499ec727ea7Spatrick } 500ec727ea7Spatrick 501ec727ea7Spatrick // NextT is a member of the same declaration, and we need the last member to 502ec727ea7Spatrick // create declaration. This one is not responsible. 503ec727ea7Spatrick return false; 504ec727ea7Spatrick } 505ec727ea7Spatrick 506*a9ac8606Spatrick ArrayRef<syntax::Token> getDeclarationRange(Decl *D) { 507*a9ac8606Spatrick ArrayRef<syntax::Token> Tokens; 508ec727ea7Spatrick // We want to drop the template parameters for specializations. 509*a9ac8606Spatrick if (const auto *S = dyn_cast<TagDecl>(D)) 510ec727ea7Spatrick Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc()); 511ec727ea7Spatrick else 512ec727ea7Spatrick Tokens = getRange(D->getSourceRange()); 513ec727ea7Spatrick return maybeAppendSemicolon(Tokens, D); 514ec727ea7Spatrick } 515ec727ea7Spatrick 516*a9ac8606Spatrick ArrayRef<syntax::Token> getExprRange(const Expr *E) const { 517ec727ea7Spatrick return getRange(E->getSourceRange()); 518e5dd7070Spatrick } 519ec727ea7Spatrick 520e5dd7070Spatrick /// Find the adjusted range for the statement, consuming the trailing 521e5dd7070Spatrick /// semicolon when needed. 522*a9ac8606Spatrick ArrayRef<syntax::Token> getStmtRange(const Stmt *S) const { 523ec727ea7Spatrick auto Tokens = getRange(S->getSourceRange()); 524e5dd7070Spatrick if (isa<CompoundStmt>(S)) 525e5dd7070Spatrick return Tokens; 526e5dd7070Spatrick 527e5dd7070Spatrick // Some statements miss a trailing semicolon, e.g. 'return', 'continue' and 528e5dd7070Spatrick // all statements that end with those. Consume this semicolon here. 529e5dd7070Spatrick if (Tokens.back().kind() == tok::semi) 530e5dd7070Spatrick return Tokens; 531e5dd7070Spatrick return withTrailingSemicolon(Tokens); 532e5dd7070Spatrick } 533e5dd7070Spatrick 534e5dd7070Spatrick private: 535*a9ac8606Spatrick ArrayRef<syntax::Token> maybeAppendSemicolon(ArrayRef<syntax::Token> Tokens, 536ec727ea7Spatrick const Decl *D) const { 537*a9ac8606Spatrick if (isa<NamespaceDecl>(D)) 538ec727ea7Spatrick return Tokens; 539ec727ea7Spatrick if (DeclsWithoutSemicolons.count(D)) 540ec727ea7Spatrick return Tokens; 541ec727ea7Spatrick // FIXME: do not consume trailing semicolon on function definitions. 542ec727ea7Spatrick // Most declarations own a semicolon in syntax trees, but not in clang AST. 543ec727ea7Spatrick return withTrailingSemicolon(Tokens); 544ec727ea7Spatrick } 545ec727ea7Spatrick 546*a9ac8606Spatrick ArrayRef<syntax::Token> 547*a9ac8606Spatrick withTrailingSemicolon(ArrayRef<syntax::Token> Tokens) const { 548e5dd7070Spatrick assert(!Tokens.empty()); 549e5dd7070Spatrick assert(Tokens.back().kind() != tok::eof); 550ec727ea7Spatrick // We never consume 'eof', so looking at the next token is ok. 551e5dd7070Spatrick if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi) 552e5dd7070Spatrick return llvm::makeArrayRef(Tokens.begin(), Tokens.end() + 1); 553e5dd7070Spatrick return Tokens; 554e5dd7070Spatrick } 555e5dd7070Spatrick 556ec727ea7Spatrick void setRole(syntax::Node *N, NodeRole R) { 557*a9ac8606Spatrick assert(N->getRole() == NodeRole::Detached); 558ec727ea7Spatrick N->setRole(R); 559ec727ea7Spatrick } 560e5dd7070Spatrick 561e5dd7070Spatrick /// A collection of trees covering the input tokens. 562e5dd7070Spatrick /// When created, each tree corresponds to a single token in the file. 563e5dd7070Spatrick /// Clients call 'foldChildren' to attach one or more subtrees to a parent 564e5dd7070Spatrick /// node and update the list of trees accordingly. 565e5dd7070Spatrick /// 566e5dd7070Spatrick /// Ensures that added nodes properly nest and cover the whole token stream. 567e5dd7070Spatrick struct Forest { 568e5dd7070Spatrick Forest(syntax::Arena &A) { 569*a9ac8606Spatrick assert(!A.getTokenBuffer().expandedTokens().empty()); 570*a9ac8606Spatrick assert(A.getTokenBuffer().expandedTokens().back().kind() == tok::eof); 571e5dd7070Spatrick // Create all leaf nodes. 572e5dd7070Spatrick // Note that we do not have 'eof' in the tree. 573*a9ac8606Spatrick for (const auto &T : A.getTokenBuffer().expandedTokens().drop_back()) { 574*a9ac8606Spatrick auto *L = new (A.getAllocator()) syntax::Leaf(&T); 575e5dd7070Spatrick L->Original = true; 576*a9ac8606Spatrick L->CanModify = A.getTokenBuffer().spelledForExpanded(T).hasValue(); 577ec727ea7Spatrick Trees.insert(Trees.end(), {&T, L}); 578e5dd7070Spatrick } 579e5dd7070Spatrick } 580e5dd7070Spatrick 581*a9ac8606Spatrick void assignRole(ArrayRef<syntax::Token> Range, syntax::NodeRole Role) { 582e5dd7070Spatrick assert(!Range.empty()); 583e5dd7070Spatrick auto It = Trees.lower_bound(Range.begin()); 584e5dd7070Spatrick assert(It != Trees.end() && "no node found"); 585e5dd7070Spatrick assert(It->first == Range.begin() && "no child with the specified range"); 586e5dd7070Spatrick assert((std::next(It) == Trees.end() || 587e5dd7070Spatrick std::next(It)->first == Range.end()) && 588e5dd7070Spatrick "no child with the specified range"); 589*a9ac8606Spatrick assert(It->second->getRole() == NodeRole::Detached && 590ec727ea7Spatrick "re-assigning role for a child"); 591ec727ea7Spatrick It->second->setRole(Role); 592e5dd7070Spatrick } 593e5dd7070Spatrick 594*a9ac8606Spatrick /// Shrink \p Range to a subrange that only contains tokens of a list. 595*a9ac8606Spatrick /// List elements and delimiters should already have correct roles. 596*a9ac8606Spatrick ArrayRef<syntax::Token> shrinkToFitList(ArrayRef<syntax::Token> Range) { 597*a9ac8606Spatrick auto BeginChildren = Trees.lower_bound(Range.begin()); 598*a9ac8606Spatrick assert((BeginChildren == Trees.end() || 599*a9ac8606Spatrick BeginChildren->first == Range.begin()) && 600*a9ac8606Spatrick "Range crosses boundaries of existing subtrees"); 601*a9ac8606Spatrick 602*a9ac8606Spatrick auto EndChildren = Trees.lower_bound(Range.end()); 603*a9ac8606Spatrick assert( 604*a9ac8606Spatrick (EndChildren == Trees.end() || EndChildren->first == Range.end()) && 605*a9ac8606Spatrick "Range crosses boundaries of existing subtrees"); 606*a9ac8606Spatrick 607*a9ac8606Spatrick auto BelongsToList = [](decltype(Trees)::value_type KV) { 608*a9ac8606Spatrick auto Role = KV.second->getRole(); 609*a9ac8606Spatrick return Role == syntax::NodeRole::ListElement || 610*a9ac8606Spatrick Role == syntax::NodeRole::ListDelimiter; 611*a9ac8606Spatrick }; 612*a9ac8606Spatrick 613*a9ac8606Spatrick auto BeginListChildren = 614*a9ac8606Spatrick std::find_if(BeginChildren, EndChildren, BelongsToList); 615*a9ac8606Spatrick 616*a9ac8606Spatrick auto EndListChildren = 617*a9ac8606Spatrick std::find_if_not(BeginListChildren, EndChildren, BelongsToList); 618*a9ac8606Spatrick 619*a9ac8606Spatrick return ArrayRef<syntax::Token>(BeginListChildren->first, 620*a9ac8606Spatrick EndListChildren->first); 621*a9ac8606Spatrick } 622*a9ac8606Spatrick 623e5dd7070Spatrick /// Add \p Node to the forest and attach child nodes based on \p Tokens. 624*a9ac8606Spatrick void foldChildren(const syntax::Arena &A, ArrayRef<syntax::Token> Tokens, 625e5dd7070Spatrick syntax::Tree *Node) { 626e5dd7070Spatrick // Attach children to `Node`. 627*a9ac8606Spatrick assert(Node->getFirstChild() == nullptr && "node already has children"); 628ec727ea7Spatrick 629ec727ea7Spatrick auto *FirstToken = Tokens.begin(); 630ec727ea7Spatrick auto BeginChildren = Trees.lower_bound(FirstToken); 631ec727ea7Spatrick 632ec727ea7Spatrick assert((BeginChildren == Trees.end() || 633ec727ea7Spatrick BeginChildren->first == FirstToken) && 634ec727ea7Spatrick "fold crosses boundaries of existing subtrees"); 635ec727ea7Spatrick auto EndChildren = Trees.lower_bound(Tokens.end()); 636ec727ea7Spatrick assert( 637ec727ea7Spatrick (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) && 638ec727ea7Spatrick "fold crosses boundaries of existing subtrees"); 639ec727ea7Spatrick 640*a9ac8606Spatrick for (auto It = BeginChildren; It != EndChildren; ++It) { 641*a9ac8606Spatrick auto *C = It->second; 642*a9ac8606Spatrick if (C->getRole() == NodeRole::Detached) 643ec727ea7Spatrick C->setRole(NodeRole::Unknown); 644*a9ac8606Spatrick Node->appendChildLowLevel(C); 645e5dd7070Spatrick } 646e5dd7070Spatrick 647ec727ea7Spatrick // Mark that this node came from the AST and is backed by the source code. 648ec727ea7Spatrick Node->Original = true; 649*a9ac8606Spatrick Node->CanModify = 650*a9ac8606Spatrick A.getTokenBuffer().spelledForExpanded(Tokens).hasValue(); 651e5dd7070Spatrick 652ec727ea7Spatrick Trees.erase(BeginChildren, EndChildren); 653ec727ea7Spatrick Trees.insert({FirstToken, Node}); 654e5dd7070Spatrick } 655e5dd7070Spatrick 656e5dd7070Spatrick // EXPECTS: all tokens were consumed and are owned by a single root node. 657e5dd7070Spatrick syntax::Node *finalize() && { 658e5dd7070Spatrick assert(Trees.size() == 1); 659ec727ea7Spatrick auto *Root = Trees.begin()->second; 660e5dd7070Spatrick Trees = {}; 661e5dd7070Spatrick return Root; 662e5dd7070Spatrick } 663e5dd7070Spatrick 664e5dd7070Spatrick std::string str(const syntax::Arena &A) const { 665e5dd7070Spatrick std::string R; 666e5dd7070Spatrick for (auto It = Trees.begin(); It != Trees.end(); ++It) { 667e5dd7070Spatrick unsigned CoveredTokens = 668e5dd7070Spatrick It != Trees.end() 669e5dd7070Spatrick ? (std::next(It)->first - It->first) 670*a9ac8606Spatrick : A.getTokenBuffer().expandedTokens().end() - It->first; 671e5dd7070Spatrick 672*a9ac8606Spatrick R += std::string( 673*a9ac8606Spatrick formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(), 674*a9ac8606Spatrick It->first->text(A.getSourceManager()), CoveredTokens)); 675*a9ac8606Spatrick R += It->second->dump(A.getSourceManager()); 676e5dd7070Spatrick } 677e5dd7070Spatrick return R; 678e5dd7070Spatrick } 679e5dd7070Spatrick 680e5dd7070Spatrick private: 681e5dd7070Spatrick /// Maps from the start token to a subtree starting at that token. 682e5dd7070Spatrick /// Keys in the map are pointers into the array of expanded tokens, so 683e5dd7070Spatrick /// pointer order corresponds to the order of preprocessor tokens. 684ec727ea7Spatrick std::map<const syntax::Token *, syntax::Node *> Trees; 685e5dd7070Spatrick }; 686e5dd7070Spatrick 687e5dd7070Spatrick /// For debugging purposes. 688e5dd7070Spatrick std::string str() { return Pending.str(Arena); } 689e5dd7070Spatrick 690e5dd7070Spatrick syntax::Arena &Arena; 691e5dd7070Spatrick /// To quickly find tokens by their start location. 692*a9ac8606Spatrick llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken; 693e5dd7070Spatrick Forest Pending; 694e5dd7070Spatrick llvm::DenseSet<Decl *> DeclsWithoutSemicolons; 695ec727ea7Spatrick ASTToSyntaxMapping Mapping; 696e5dd7070Spatrick }; 697e5dd7070Spatrick 698e5dd7070Spatrick namespace { 699e5dd7070Spatrick class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> { 700e5dd7070Spatrick public: 701ec727ea7Spatrick explicit BuildTreeVisitor(ASTContext &Context, syntax::TreeBuilder &Builder) 702ec727ea7Spatrick : Builder(Builder), Context(Context) {} 703e5dd7070Spatrick 704e5dd7070Spatrick bool shouldTraversePostOrder() const { return true; } 705e5dd7070Spatrick 706ec727ea7Spatrick bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) { 707ec727ea7Spatrick return processDeclaratorAndDeclaration(DD); 708e5dd7070Spatrick } 709ec727ea7Spatrick 710ec727ea7Spatrick bool WalkUpFromTypedefNameDecl(TypedefNameDecl *TD) { 711ec727ea7Spatrick return processDeclaratorAndDeclaration(TD); 712e5dd7070Spatrick } 713e5dd7070Spatrick 714e5dd7070Spatrick bool VisitDecl(Decl *D) { 715e5dd7070Spatrick assert(!D->isImplicit()); 716ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(D), 717ec727ea7Spatrick new (allocator()) syntax::UnknownDeclaration(), D); 718ec727ea7Spatrick return true; 719ec727ea7Spatrick } 720ec727ea7Spatrick 721ec727ea7Spatrick // RAV does not call WalkUpFrom* on explicit instantiations, so we have to 722ec727ea7Spatrick // override Traverse. 723ec727ea7Spatrick // FIXME: make RAV call WalkUpFrom* instead. 724ec727ea7Spatrick bool 725ec727ea7Spatrick TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) { 726ec727ea7Spatrick if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C)) 727ec727ea7Spatrick return false; 728ec727ea7Spatrick if (C->isExplicitSpecialization()) 729ec727ea7Spatrick return true; // we are only interested in explicit instantiations. 730ec727ea7Spatrick auto *Declaration = 731ec727ea7Spatrick cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C)); 732ec727ea7Spatrick foldExplicitTemplateInstantiation( 733ec727ea7Spatrick Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()), 734ec727ea7Spatrick Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C); 735ec727ea7Spatrick return true; 736ec727ea7Spatrick } 737ec727ea7Spatrick 738ec727ea7Spatrick bool WalkUpFromTemplateDecl(TemplateDecl *S) { 739ec727ea7Spatrick foldTemplateDeclaration( 740ec727ea7Spatrick Builder.getDeclarationRange(S), 741ec727ea7Spatrick Builder.findToken(S->getTemplateParameters()->getTemplateLoc()), 742ec727ea7Spatrick Builder.getDeclarationRange(S->getTemplatedDecl()), S); 743e5dd7070Spatrick return true; 744e5dd7070Spatrick } 745e5dd7070Spatrick 746e5dd7070Spatrick bool WalkUpFromTagDecl(TagDecl *C) { 747e5dd7070Spatrick // FIXME: build the ClassSpecifier node. 748ec727ea7Spatrick if (!C->isFreeStanding()) { 749ec727ea7Spatrick assert(C->getNumTemplateParameterLists() == 0); 750e5dd7070Spatrick return true; 751e5dd7070Spatrick } 752ec727ea7Spatrick handleFreeStandingTagDecl(C); 753e5dd7070Spatrick return true; 754e5dd7070Spatrick } 755e5dd7070Spatrick 756ec727ea7Spatrick syntax::Declaration *handleFreeStandingTagDecl(TagDecl *C) { 757ec727ea7Spatrick assert(C->isFreeStanding()); 758ec727ea7Spatrick // Class is a declaration specifier and needs a spanning declaration node. 759ec727ea7Spatrick auto DeclarationRange = Builder.getDeclarationRange(C); 760ec727ea7Spatrick syntax::Declaration *Result = new (allocator()) syntax::SimpleDeclaration; 761ec727ea7Spatrick Builder.foldNode(DeclarationRange, Result, nullptr); 762ec727ea7Spatrick 763ec727ea7Spatrick // Build TemplateDeclaration nodes if we had template parameters. 764ec727ea7Spatrick auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) { 765ec727ea7Spatrick const auto *TemplateKW = Builder.findToken(L.getTemplateLoc()); 766ec727ea7Spatrick auto R = llvm::makeArrayRef(TemplateKW, DeclarationRange.end()); 767ec727ea7Spatrick Result = 768ec727ea7Spatrick foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr); 769ec727ea7Spatrick DeclarationRange = R; 770ec727ea7Spatrick }; 771*a9ac8606Spatrick if (auto *S = dyn_cast<ClassTemplatePartialSpecializationDecl>(C)) 772ec727ea7Spatrick ConsumeTemplateParameters(*S->getTemplateParameters()); 773ec727ea7Spatrick for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I) 774ec727ea7Spatrick ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1)); 775ec727ea7Spatrick return Result; 776ec727ea7Spatrick } 777ec727ea7Spatrick 778e5dd7070Spatrick bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) { 779ec727ea7Spatrick // We do not want to call VisitDecl(), the declaration for translation 780e5dd7070Spatrick // unit is built by finalize(). 781e5dd7070Spatrick return true; 782e5dd7070Spatrick } 783e5dd7070Spatrick 784e5dd7070Spatrick bool WalkUpFromCompoundStmt(CompoundStmt *S) { 785e5dd7070Spatrick using NodeRole = syntax::NodeRole; 786e5dd7070Spatrick 787e5dd7070Spatrick Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen); 788e5dd7070Spatrick for (auto *Child : S->body()) 789*a9ac8606Spatrick Builder.markStmtChild(Child, NodeRole::Statement); 790e5dd7070Spatrick Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen); 791e5dd7070Spatrick 792e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 793ec727ea7Spatrick new (allocator()) syntax::CompoundStatement, S); 794e5dd7070Spatrick return true; 795e5dd7070Spatrick } 796e5dd7070Spatrick 797e5dd7070Spatrick // Some statements are not yet handled by syntax trees. 798e5dd7070Spatrick bool WalkUpFromStmt(Stmt *S) { 799e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 800ec727ea7Spatrick new (allocator()) syntax::UnknownStatement, S); 801e5dd7070Spatrick return true; 802e5dd7070Spatrick } 803e5dd7070Spatrick 804*a9ac8606Spatrick bool TraverseIfStmt(IfStmt *S) { 805*a9ac8606Spatrick bool Result = [&, this]() { 806*a9ac8606Spatrick if (S->getInit() && !TraverseStmt(S->getInit())) { 807*a9ac8606Spatrick return false; 808*a9ac8606Spatrick } 809*a9ac8606Spatrick // In cases where the condition is an initialized declaration in a 810*a9ac8606Spatrick // statement, we want to preserve the declaration and ignore the 811*a9ac8606Spatrick // implicit condition expression in the syntax tree. 812*a9ac8606Spatrick if (S->hasVarStorage()) { 813*a9ac8606Spatrick if (!TraverseStmt(S->getConditionVariableDeclStmt())) 814*a9ac8606Spatrick return false; 815*a9ac8606Spatrick } else if (S->getCond() && !TraverseStmt(S->getCond())) 816*a9ac8606Spatrick return false; 817*a9ac8606Spatrick 818*a9ac8606Spatrick if (S->getThen() && !TraverseStmt(S->getThen())) 819*a9ac8606Spatrick return false; 820*a9ac8606Spatrick if (S->getElse() && !TraverseStmt(S->getElse())) 821*a9ac8606Spatrick return false; 822*a9ac8606Spatrick return true; 823*a9ac8606Spatrick }(); 824*a9ac8606Spatrick WalkUpFromIfStmt(S); 825*a9ac8606Spatrick return Result; 826*a9ac8606Spatrick } 827*a9ac8606Spatrick 828e5dd7070Spatrick bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) { 829e5dd7070Spatrick // We override to traverse range initializer as VarDecl. 830e5dd7070Spatrick // RAV traverses it as a statement, we produce invalid node kinds in that 831e5dd7070Spatrick // case. 832e5dd7070Spatrick // FIXME: should do this in RAV instead? 833ec727ea7Spatrick bool Result = [&, this]() { 834e5dd7070Spatrick if (S->getInit() && !TraverseStmt(S->getInit())) 835e5dd7070Spatrick return false; 836e5dd7070Spatrick if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable())) 837e5dd7070Spatrick return false; 838e5dd7070Spatrick if (S->getRangeInit() && !TraverseStmt(S->getRangeInit())) 839e5dd7070Spatrick return false; 840e5dd7070Spatrick if (S->getBody() && !TraverseStmt(S->getBody())) 841e5dd7070Spatrick return false; 842e5dd7070Spatrick return true; 843ec727ea7Spatrick }(); 844ec727ea7Spatrick WalkUpFromCXXForRangeStmt(S); 845ec727ea7Spatrick return Result; 846e5dd7070Spatrick } 847e5dd7070Spatrick 848e5dd7070Spatrick bool TraverseStmt(Stmt *S) { 849*a9ac8606Spatrick if (auto *DS = dyn_cast_or_null<DeclStmt>(S)) { 850e5dd7070Spatrick // We want to consume the semicolon, make sure SimpleDeclaration does not. 851e5dd7070Spatrick for (auto *D : DS->decls()) 852ec727ea7Spatrick Builder.noticeDeclWithoutSemicolon(D); 853*a9ac8606Spatrick } else if (auto *E = dyn_cast_or_null<Expr>(S)) { 854*a9ac8606Spatrick return RecursiveASTVisitor::TraverseStmt(IgnoreImplicit(E)); 855e5dd7070Spatrick } 856e5dd7070Spatrick return RecursiveASTVisitor::TraverseStmt(S); 857e5dd7070Spatrick } 858e5dd7070Spatrick 859*a9ac8606Spatrick bool TraverseOpaqueValueExpr(OpaqueValueExpr *VE) { 860*a9ac8606Spatrick // OpaqueValue doesn't correspond to concrete syntax, ignore it. 861*a9ac8606Spatrick return true; 862*a9ac8606Spatrick } 863*a9ac8606Spatrick 864e5dd7070Spatrick // Some expressions are not yet handled by syntax trees. 865e5dd7070Spatrick bool WalkUpFromExpr(Expr *E) { 866e5dd7070Spatrick assert(!isImplicitExpr(E) && "should be handled by TraverseStmt"); 867e5dd7070Spatrick Builder.foldNode(Builder.getExprRange(E), 868ec727ea7Spatrick new (allocator()) syntax::UnknownExpression, E); 869e5dd7070Spatrick return true; 870e5dd7070Spatrick } 871e5dd7070Spatrick 872ec727ea7Spatrick bool TraverseUserDefinedLiteral(UserDefinedLiteral *S) { 873ec727ea7Spatrick // The semantic AST node `UserDefinedLiteral` (UDL) may have one child node 874ec727ea7Spatrick // referencing the location of the UDL suffix (`_w` in `1.2_w`). The 875ec727ea7Spatrick // UDL suffix location does not point to the beginning of a token, so we 876ec727ea7Spatrick // can't represent the UDL suffix as a separate syntax tree node. 877ec727ea7Spatrick 878ec727ea7Spatrick return WalkUpFromUserDefinedLiteral(S); 879ec727ea7Spatrick } 880ec727ea7Spatrick 881ec727ea7Spatrick syntax::UserDefinedLiteralExpression * 882ec727ea7Spatrick buildUserDefinedLiteral(UserDefinedLiteral *S) { 883ec727ea7Spatrick switch (S->getLiteralOperatorKind()) { 884*a9ac8606Spatrick case UserDefinedLiteral::LOK_Integer: 885ec727ea7Spatrick return new (allocator()) syntax::IntegerUserDefinedLiteralExpression; 886*a9ac8606Spatrick case UserDefinedLiteral::LOK_Floating: 887ec727ea7Spatrick return new (allocator()) syntax::FloatUserDefinedLiteralExpression; 888*a9ac8606Spatrick case UserDefinedLiteral::LOK_Character: 889ec727ea7Spatrick return new (allocator()) syntax::CharUserDefinedLiteralExpression; 890*a9ac8606Spatrick case UserDefinedLiteral::LOK_String: 891ec727ea7Spatrick return new (allocator()) syntax::StringUserDefinedLiteralExpression; 892*a9ac8606Spatrick case UserDefinedLiteral::LOK_Raw: 893*a9ac8606Spatrick case UserDefinedLiteral::LOK_Template: 894ec727ea7Spatrick // For raw literal operator and numeric literal operator template we 895ec727ea7Spatrick // cannot get the type of the operand in the semantic AST. We get this 896ec727ea7Spatrick // information from the token. As integer and floating point have the same 897ec727ea7Spatrick // token kind, we run `NumericLiteralParser` again to distinguish them. 898ec727ea7Spatrick auto TokLoc = S->getBeginLoc(); 899ec727ea7Spatrick auto TokSpelling = 900ec727ea7Spatrick Builder.findToken(TokLoc)->text(Context.getSourceManager()); 901ec727ea7Spatrick auto Literal = 902ec727ea7Spatrick NumericLiteralParser(TokSpelling, TokLoc, Context.getSourceManager(), 903ec727ea7Spatrick Context.getLangOpts(), Context.getTargetInfo(), 904ec727ea7Spatrick Context.getDiagnostics()); 905ec727ea7Spatrick if (Literal.isIntegerLiteral()) 906ec727ea7Spatrick return new (allocator()) syntax::IntegerUserDefinedLiteralExpression; 907ec727ea7Spatrick else { 908ec727ea7Spatrick assert(Literal.isFloatingLiteral()); 909ec727ea7Spatrick return new (allocator()) syntax::FloatUserDefinedLiteralExpression; 910ec727ea7Spatrick } 911ec727ea7Spatrick } 912ec727ea7Spatrick llvm_unreachable("Unknown literal operator kind."); 913ec727ea7Spatrick } 914ec727ea7Spatrick 915ec727ea7Spatrick bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) { 916ec727ea7Spatrick Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken); 917ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), buildUserDefinedLiteral(S), S); 918ec727ea7Spatrick return true; 919ec727ea7Spatrick } 920ec727ea7Spatrick 921*a9ac8606Spatrick // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the 922*a9ac8606Spatrick // `DependentTemplateSpecializationType` case. 923*a9ac8606Spatrick /// Given a nested-name-specifier return the range for the last name 924*a9ac8606Spatrick /// specifier. 925*a9ac8606Spatrick /// 926*a9ac8606Spatrick /// e.g. `std::T::template X<U>::` => `template X<U>::` 927*a9ac8606Spatrick SourceRange getLocalSourceRange(const NestedNameSpecifierLoc &NNSLoc) { 928*a9ac8606Spatrick auto SR = NNSLoc.getLocalSourceRange(); 929ec727ea7Spatrick 930*a9ac8606Spatrick // The method `NestedNameSpecifierLoc::getLocalSourceRange` *should* 931*a9ac8606Spatrick // return the desired `SourceRange`, but there is a corner case. For a 932*a9ac8606Spatrick // `DependentTemplateSpecializationType` this method returns its 933*a9ac8606Spatrick // qualifiers as well, in other words in the example above this method 934*a9ac8606Spatrick // returns `T::template X<U>::` instead of only `template X<U>::` 935*a9ac8606Spatrick if (auto TL = NNSLoc.getTypeLoc()) { 936*a9ac8606Spatrick if (auto DependentTL = 937*a9ac8606Spatrick TL.getAs<DependentTemplateSpecializationTypeLoc>()) { 938*a9ac8606Spatrick // The 'template' keyword is always present in dependent template 939*a9ac8606Spatrick // specializations. Except in the case of incorrect code 940*a9ac8606Spatrick // TODO: Treat the case of incorrect code. 941*a9ac8606Spatrick SR.setBegin(DependentTL.getTemplateKeywordLoc()); 942ec727ea7Spatrick } 943*a9ac8606Spatrick } 944*a9ac8606Spatrick 945*a9ac8606Spatrick return SR; 946*a9ac8606Spatrick } 947*a9ac8606Spatrick 948*a9ac8606Spatrick syntax::NodeKind getNameSpecifierKind(const NestedNameSpecifier &NNS) { 949*a9ac8606Spatrick switch (NNS.getKind()) { 950*a9ac8606Spatrick case NestedNameSpecifier::Global: 951*a9ac8606Spatrick return syntax::NodeKind::GlobalNameSpecifier; 952*a9ac8606Spatrick case NestedNameSpecifier::Namespace: 953*a9ac8606Spatrick case NestedNameSpecifier::NamespaceAlias: 954*a9ac8606Spatrick case NestedNameSpecifier::Identifier: 955*a9ac8606Spatrick return syntax::NodeKind::IdentifierNameSpecifier; 956*a9ac8606Spatrick case NestedNameSpecifier::TypeSpecWithTemplate: 957*a9ac8606Spatrick return syntax::NodeKind::SimpleTemplateNameSpecifier; 958*a9ac8606Spatrick case NestedNameSpecifier::TypeSpec: { 959*a9ac8606Spatrick const auto *NNSType = NNS.getAsType(); 960*a9ac8606Spatrick assert(NNSType); 961*a9ac8606Spatrick if (isa<DecltypeType>(NNSType)) 962*a9ac8606Spatrick return syntax::NodeKind::DecltypeNameSpecifier; 963*a9ac8606Spatrick if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>( 964*a9ac8606Spatrick NNSType)) 965*a9ac8606Spatrick return syntax::NodeKind::SimpleTemplateNameSpecifier; 966*a9ac8606Spatrick return syntax::NodeKind::IdentifierNameSpecifier; 967*a9ac8606Spatrick } 968*a9ac8606Spatrick default: 969*a9ac8606Spatrick // FIXME: Support Microsoft's __super 970*a9ac8606Spatrick llvm::report_fatal_error("We don't yet support the __super specifier", 971*a9ac8606Spatrick true); 972*a9ac8606Spatrick } 973*a9ac8606Spatrick } 974*a9ac8606Spatrick 975*a9ac8606Spatrick syntax::NameSpecifier * 976*a9ac8606Spatrick buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) { 977*a9ac8606Spatrick assert(NNSLoc.hasQualifier()); 978*a9ac8606Spatrick auto NameSpecifierTokens = 979*a9ac8606Spatrick Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back(); 980*a9ac8606Spatrick switch (getNameSpecifierKind(*NNSLoc.getNestedNameSpecifier())) { 981*a9ac8606Spatrick case syntax::NodeKind::GlobalNameSpecifier: 982*a9ac8606Spatrick return new (allocator()) syntax::GlobalNameSpecifier; 983*a9ac8606Spatrick case syntax::NodeKind::IdentifierNameSpecifier: { 984*a9ac8606Spatrick assert(NameSpecifierTokens.size() == 1); 985*a9ac8606Spatrick Builder.markChildToken(NameSpecifierTokens.begin(), 986*a9ac8606Spatrick syntax::NodeRole::Unknown); 987*a9ac8606Spatrick auto *NS = new (allocator()) syntax::IdentifierNameSpecifier; 988*a9ac8606Spatrick Builder.foldNode(NameSpecifierTokens, NS, nullptr); 989*a9ac8606Spatrick return NS; 990*a9ac8606Spatrick } 991*a9ac8606Spatrick case syntax::NodeKind::SimpleTemplateNameSpecifier: { 992*a9ac8606Spatrick // TODO: Build `SimpleTemplateNameSpecifier` children and implement 993*a9ac8606Spatrick // accessors to them. 994*a9ac8606Spatrick // Be aware, we cannot do that simply by calling `TraverseTypeLoc`, 995*a9ac8606Spatrick // some `TypeLoc`s have inside them the previous name specifier and 996*a9ac8606Spatrick // we want to treat them independently. 997*a9ac8606Spatrick auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier; 998*a9ac8606Spatrick Builder.foldNode(NameSpecifierTokens, NS, nullptr); 999*a9ac8606Spatrick return NS; 1000*a9ac8606Spatrick } 1001*a9ac8606Spatrick case syntax::NodeKind::DecltypeNameSpecifier: { 1002*a9ac8606Spatrick const auto TL = NNSLoc.getTypeLoc().castAs<DecltypeTypeLoc>(); 1003*a9ac8606Spatrick if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL)) 1004*a9ac8606Spatrick return nullptr; 1005*a9ac8606Spatrick auto *NS = new (allocator()) syntax::DecltypeNameSpecifier; 1006*a9ac8606Spatrick // TODO: Implement accessor to `DecltypeNameSpecifier` inner 1007*a9ac8606Spatrick // `DecltypeTypeLoc`. 1008*a9ac8606Spatrick // For that add mapping from `TypeLoc` to `syntax::Node*` then: 1009*a9ac8606Spatrick // Builder.markChild(TypeLoc, syntax::NodeRole); 1010*a9ac8606Spatrick Builder.foldNode(NameSpecifierTokens, NS, nullptr); 1011*a9ac8606Spatrick return NS; 1012*a9ac8606Spatrick } 1013*a9ac8606Spatrick default: 1014*a9ac8606Spatrick llvm_unreachable("getChildKind() does not return this value"); 1015*a9ac8606Spatrick } 1016*a9ac8606Spatrick } 1017*a9ac8606Spatrick 1018*a9ac8606Spatrick // To build syntax tree nodes for NestedNameSpecifierLoc we override 1019*a9ac8606Spatrick // Traverse instead of WalkUpFrom because we want to traverse the children 1020*a9ac8606Spatrick // ourselves and build a list instead of a nested tree of name specifier 1021*a9ac8606Spatrick // prefixes. 1022*a9ac8606Spatrick bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) { 1023*a9ac8606Spatrick if (!QualifierLoc) 1024*a9ac8606Spatrick return true; 1025*a9ac8606Spatrick for (auto It = QualifierLoc; It; It = It.getPrefix()) { 1026*a9ac8606Spatrick auto *NS = buildNameSpecifier(It); 1027*a9ac8606Spatrick if (!NS) 1028*a9ac8606Spatrick return false; 1029*a9ac8606Spatrick Builder.markChild(NS, syntax::NodeRole::ListElement); 1030*a9ac8606Spatrick Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter); 1031*a9ac8606Spatrick } 1032*a9ac8606Spatrick Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), 1033*a9ac8606Spatrick new (allocator()) syntax::NestedNameSpecifier, 1034*a9ac8606Spatrick QualifierLoc); 1035*a9ac8606Spatrick return true; 1036*a9ac8606Spatrick } 1037*a9ac8606Spatrick 1038*a9ac8606Spatrick syntax::IdExpression *buildIdExpression(NestedNameSpecifierLoc QualifierLoc, 1039*a9ac8606Spatrick SourceLocation TemplateKeywordLoc, 1040*a9ac8606Spatrick SourceRange UnqualifiedIdLoc, 1041*a9ac8606Spatrick ASTPtr From) { 1042*a9ac8606Spatrick if (QualifierLoc) { 1043*a9ac8606Spatrick Builder.markChild(QualifierLoc, syntax::NodeRole::Qualifier); 1044*a9ac8606Spatrick if (TemplateKeywordLoc.isValid()) 1045*a9ac8606Spatrick Builder.markChildToken(TemplateKeywordLoc, 1046*a9ac8606Spatrick syntax::NodeRole::TemplateKeyword); 1047*a9ac8606Spatrick } 1048*a9ac8606Spatrick 1049*a9ac8606Spatrick auto *TheUnqualifiedId = new (allocator()) syntax::UnqualifiedId; 1050*a9ac8606Spatrick Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId, 1051*a9ac8606Spatrick nullptr); 1052*a9ac8606Spatrick Builder.markChild(TheUnqualifiedId, syntax::NodeRole::UnqualifiedId); 1053*a9ac8606Spatrick 1054*a9ac8606Spatrick auto IdExpressionBeginLoc = 1055*a9ac8606Spatrick QualifierLoc ? QualifierLoc.getBeginLoc() : UnqualifiedIdLoc.getBegin(); 1056*a9ac8606Spatrick 1057*a9ac8606Spatrick auto *TheIdExpression = new (allocator()) syntax::IdExpression; 1058*a9ac8606Spatrick Builder.foldNode( 1059*a9ac8606Spatrick Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.getEnd()), 1060*a9ac8606Spatrick TheIdExpression, From); 1061*a9ac8606Spatrick 1062*a9ac8606Spatrick return TheIdExpression; 1063*a9ac8606Spatrick } 1064*a9ac8606Spatrick 1065*a9ac8606Spatrick bool WalkUpFromMemberExpr(MemberExpr *S) { 1066*a9ac8606Spatrick // For `MemberExpr` with implicit `this->` we generate a simple 1067*a9ac8606Spatrick // `id-expression` syntax node, beacuse an implicit `member-expression` is 1068*a9ac8606Spatrick // syntactically undistinguishable from an `id-expression` 1069*a9ac8606Spatrick if (S->isImplicitAccess()) { 1070*a9ac8606Spatrick buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(), 1071*a9ac8606Spatrick SourceRange(S->getMemberLoc(), S->getEndLoc()), S); 1072*a9ac8606Spatrick return true; 1073*a9ac8606Spatrick } 1074*a9ac8606Spatrick 1075*a9ac8606Spatrick auto *TheIdExpression = buildIdExpression( 1076*a9ac8606Spatrick S->getQualifierLoc(), S->getTemplateKeywordLoc(), 1077*a9ac8606Spatrick SourceRange(S->getMemberLoc(), S->getEndLoc()), nullptr); 1078*a9ac8606Spatrick 1079*a9ac8606Spatrick Builder.markChild(TheIdExpression, syntax::NodeRole::Member); 1080*a9ac8606Spatrick 1081*a9ac8606Spatrick Builder.markExprChild(S->getBase(), syntax::NodeRole::Object); 1082*a9ac8606Spatrick Builder.markChildToken(S->getOperatorLoc(), syntax::NodeRole::AccessToken); 1083ec727ea7Spatrick 1084ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1085*a9ac8606Spatrick new (allocator()) syntax::MemberExpression, S); 1086*a9ac8606Spatrick return true; 1087*a9ac8606Spatrick } 1088*a9ac8606Spatrick 1089*a9ac8606Spatrick bool WalkUpFromDeclRefExpr(DeclRefExpr *S) { 1090*a9ac8606Spatrick buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(), 1091*a9ac8606Spatrick SourceRange(S->getLocation(), S->getEndLoc()), S); 1092*a9ac8606Spatrick 1093*a9ac8606Spatrick return true; 1094*a9ac8606Spatrick } 1095*a9ac8606Spatrick 1096*a9ac8606Spatrick // Same logic as DeclRefExpr. 1097*a9ac8606Spatrick bool WalkUpFromDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) { 1098*a9ac8606Spatrick buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(), 1099*a9ac8606Spatrick SourceRange(S->getLocation(), S->getEndLoc()), S); 1100*a9ac8606Spatrick 1101*a9ac8606Spatrick return true; 1102*a9ac8606Spatrick } 1103*a9ac8606Spatrick 1104*a9ac8606Spatrick bool WalkUpFromCXXThisExpr(CXXThisExpr *S) { 1105*a9ac8606Spatrick if (!S->isImplicit()) { 1106*a9ac8606Spatrick Builder.markChildToken(S->getLocation(), 1107*a9ac8606Spatrick syntax::NodeRole::IntroducerKeyword); 1108*a9ac8606Spatrick Builder.foldNode(Builder.getExprRange(S), 1109*a9ac8606Spatrick new (allocator()) syntax::ThisExpression, S); 1110*a9ac8606Spatrick } 1111ec727ea7Spatrick return true; 1112ec727ea7Spatrick } 1113ec727ea7Spatrick 1114ec727ea7Spatrick bool WalkUpFromParenExpr(ParenExpr *S) { 1115ec727ea7Spatrick Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen); 1116*a9ac8606Spatrick Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::SubExpression); 1117ec727ea7Spatrick Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen); 1118ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1119ec727ea7Spatrick new (allocator()) syntax::ParenExpression, S); 1120ec727ea7Spatrick return true; 1121ec727ea7Spatrick } 1122ec727ea7Spatrick 1123ec727ea7Spatrick bool WalkUpFromIntegerLiteral(IntegerLiteral *S) { 1124ec727ea7Spatrick Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); 1125ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1126ec727ea7Spatrick new (allocator()) syntax::IntegerLiteralExpression, S); 1127ec727ea7Spatrick return true; 1128ec727ea7Spatrick } 1129ec727ea7Spatrick 1130ec727ea7Spatrick bool WalkUpFromCharacterLiteral(CharacterLiteral *S) { 1131ec727ea7Spatrick Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); 1132ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1133ec727ea7Spatrick new (allocator()) syntax::CharacterLiteralExpression, S); 1134ec727ea7Spatrick return true; 1135ec727ea7Spatrick } 1136ec727ea7Spatrick 1137ec727ea7Spatrick bool WalkUpFromFloatingLiteral(FloatingLiteral *S) { 1138ec727ea7Spatrick Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); 1139ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1140ec727ea7Spatrick new (allocator()) syntax::FloatingLiteralExpression, S); 1141ec727ea7Spatrick return true; 1142ec727ea7Spatrick } 1143ec727ea7Spatrick 1144ec727ea7Spatrick bool WalkUpFromStringLiteral(StringLiteral *S) { 1145ec727ea7Spatrick Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken); 1146ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1147ec727ea7Spatrick new (allocator()) syntax::StringLiteralExpression, S); 1148ec727ea7Spatrick return true; 1149ec727ea7Spatrick } 1150ec727ea7Spatrick 1151ec727ea7Spatrick bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) { 1152ec727ea7Spatrick Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); 1153ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1154ec727ea7Spatrick new (allocator()) syntax::BoolLiteralExpression, S); 1155ec727ea7Spatrick return true; 1156ec727ea7Spatrick } 1157ec727ea7Spatrick 1158ec727ea7Spatrick bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) { 1159ec727ea7Spatrick Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); 1160ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1161ec727ea7Spatrick new (allocator()) syntax::CxxNullPtrExpression, S); 1162ec727ea7Spatrick return true; 1163ec727ea7Spatrick } 1164ec727ea7Spatrick 1165ec727ea7Spatrick bool WalkUpFromUnaryOperator(UnaryOperator *S) { 1166ec727ea7Spatrick Builder.markChildToken(S->getOperatorLoc(), 1167*a9ac8606Spatrick syntax::NodeRole::OperatorToken); 1168*a9ac8606Spatrick Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::Operand); 1169ec727ea7Spatrick 1170ec727ea7Spatrick if (S->isPostfix()) 1171ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1172ec727ea7Spatrick new (allocator()) syntax::PostfixUnaryOperatorExpression, 1173ec727ea7Spatrick S); 1174ec727ea7Spatrick else 1175ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1176ec727ea7Spatrick new (allocator()) syntax::PrefixUnaryOperatorExpression, 1177ec727ea7Spatrick S); 1178ec727ea7Spatrick 1179ec727ea7Spatrick return true; 1180ec727ea7Spatrick } 1181ec727ea7Spatrick 1182ec727ea7Spatrick bool WalkUpFromBinaryOperator(BinaryOperator *S) { 1183*a9ac8606Spatrick Builder.markExprChild(S->getLHS(), syntax::NodeRole::LeftHandSide); 1184ec727ea7Spatrick Builder.markChildToken(S->getOperatorLoc(), 1185*a9ac8606Spatrick syntax::NodeRole::OperatorToken); 1186*a9ac8606Spatrick Builder.markExprChild(S->getRHS(), syntax::NodeRole::RightHandSide); 1187ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1188ec727ea7Spatrick new (allocator()) syntax::BinaryOperatorExpression, S); 1189ec727ea7Spatrick return true; 1190ec727ea7Spatrick } 1191ec727ea7Spatrick 1192*a9ac8606Spatrick /// Builds `CallArguments` syntax node from arguments that appear in source 1193*a9ac8606Spatrick /// code, i.e. not default arguments. 1194*a9ac8606Spatrick syntax::CallArguments * 1195*a9ac8606Spatrick buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs) { 1196*a9ac8606Spatrick auto Args = dropDefaultArgs(ArgsAndDefaultArgs); 1197*a9ac8606Spatrick for (auto *Arg : Args) { 1198*a9ac8606Spatrick Builder.markExprChild(Arg, syntax::NodeRole::ListElement); 1199*a9ac8606Spatrick const auto *DelimiterToken = 1200*a9ac8606Spatrick std::next(Builder.findToken(Arg->getEndLoc())); 1201*a9ac8606Spatrick if (DelimiterToken->kind() == clang::tok::TokenKind::comma) 1202*a9ac8606Spatrick Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter); 1203*a9ac8606Spatrick } 1204*a9ac8606Spatrick 1205*a9ac8606Spatrick auto *Arguments = new (allocator()) syntax::CallArguments; 1206*a9ac8606Spatrick if (!Args.empty()) 1207*a9ac8606Spatrick Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(), 1208*a9ac8606Spatrick (*(Args.end() - 1))->getEndLoc()), 1209*a9ac8606Spatrick Arguments, nullptr); 1210*a9ac8606Spatrick 1211*a9ac8606Spatrick return Arguments; 1212*a9ac8606Spatrick } 1213*a9ac8606Spatrick 1214*a9ac8606Spatrick bool WalkUpFromCallExpr(CallExpr *S) { 1215*a9ac8606Spatrick Builder.markExprChild(S->getCallee(), syntax::NodeRole::Callee); 1216*a9ac8606Spatrick 1217*a9ac8606Spatrick const auto *LParenToken = 1218*a9ac8606Spatrick std::next(Builder.findToken(S->getCallee()->getEndLoc())); 1219*a9ac8606Spatrick // FIXME: Assert that `LParenToken` is indeed a `l_paren` once we have fixed 1220*a9ac8606Spatrick // the test on decltype desctructors. 1221*a9ac8606Spatrick if (LParenToken->kind() == clang::tok::l_paren) 1222*a9ac8606Spatrick Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen); 1223*a9ac8606Spatrick 1224*a9ac8606Spatrick Builder.markChild(buildCallArguments(S->arguments()), 1225*a9ac8606Spatrick syntax::NodeRole::Arguments); 1226*a9ac8606Spatrick 1227*a9ac8606Spatrick Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen); 1228*a9ac8606Spatrick 1229*a9ac8606Spatrick Builder.foldNode(Builder.getRange(S->getSourceRange()), 1230*a9ac8606Spatrick new (allocator()) syntax::CallExpression, S); 1231*a9ac8606Spatrick return true; 1232*a9ac8606Spatrick } 1233*a9ac8606Spatrick 1234*a9ac8606Spatrick bool WalkUpFromCXXConstructExpr(CXXConstructExpr *S) { 1235*a9ac8606Spatrick // Ignore the implicit calls to default constructors. 1236*a9ac8606Spatrick if ((S->getNumArgs() == 0 || isa<CXXDefaultArgExpr>(S->getArg(0))) && 1237*a9ac8606Spatrick S->getParenOrBraceRange().isInvalid()) 1238*a9ac8606Spatrick return true; 1239*a9ac8606Spatrick return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S); 1240*a9ac8606Spatrick } 1241*a9ac8606Spatrick 1242ec727ea7Spatrick bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { 1243*a9ac8606Spatrick // To construct a syntax tree of the same shape for calls to built-in and 1244*a9ac8606Spatrick // user-defined operators, ignore the `DeclRefExpr` that refers to the 1245*a9ac8606Spatrick // operator and treat it as a simple token. Do that by traversing 1246*a9ac8606Spatrick // arguments instead of children. 1247*a9ac8606Spatrick for (auto *child : S->arguments()) { 1248ec727ea7Spatrick // A postfix unary operator is declared as taking two operands. The 1249ec727ea7Spatrick // second operand is used to distinguish from its prefix counterpart. In 1250ec727ea7Spatrick // the semantic AST this "phantom" operand is represented as a 1251ec727ea7Spatrick // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this 1252ec727ea7Spatrick // operand because it does not correspond to anything written in source 1253*a9ac8606Spatrick // code. 1254*a9ac8606Spatrick if (child->getSourceRange().isInvalid()) { 1255*a9ac8606Spatrick assert(getOperatorNodeKind(*S) == 1256*a9ac8606Spatrick syntax::NodeKind::PostfixUnaryOperatorExpression); 1257ec727ea7Spatrick continue; 1258*a9ac8606Spatrick } 1259ec727ea7Spatrick if (!TraverseStmt(child)) 1260ec727ea7Spatrick return false; 1261ec727ea7Spatrick } 1262ec727ea7Spatrick return WalkUpFromCXXOperatorCallExpr(S); 1263ec727ea7Spatrick } 1264ec727ea7Spatrick 1265ec727ea7Spatrick bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) { 1266ec727ea7Spatrick switch (getOperatorNodeKind(*S)) { 1267ec727ea7Spatrick case syntax::NodeKind::BinaryOperatorExpression: 1268*a9ac8606Spatrick Builder.markExprChild(S->getArg(0), syntax::NodeRole::LeftHandSide); 1269*a9ac8606Spatrick Builder.markChildToken(S->getOperatorLoc(), 1270*a9ac8606Spatrick syntax::NodeRole::OperatorToken); 1271*a9ac8606Spatrick Builder.markExprChild(S->getArg(1), syntax::NodeRole::RightHandSide); 1272ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1273ec727ea7Spatrick new (allocator()) syntax::BinaryOperatorExpression, S); 1274ec727ea7Spatrick return true; 1275ec727ea7Spatrick case syntax::NodeKind::PrefixUnaryOperatorExpression: 1276*a9ac8606Spatrick Builder.markChildToken(S->getOperatorLoc(), 1277*a9ac8606Spatrick syntax::NodeRole::OperatorToken); 1278*a9ac8606Spatrick Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand); 1279ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1280ec727ea7Spatrick new (allocator()) syntax::PrefixUnaryOperatorExpression, 1281ec727ea7Spatrick S); 1282ec727ea7Spatrick return true; 1283ec727ea7Spatrick case syntax::NodeKind::PostfixUnaryOperatorExpression: 1284*a9ac8606Spatrick Builder.markChildToken(S->getOperatorLoc(), 1285*a9ac8606Spatrick syntax::NodeRole::OperatorToken); 1286*a9ac8606Spatrick Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand); 1287ec727ea7Spatrick Builder.foldNode(Builder.getExprRange(S), 1288ec727ea7Spatrick new (allocator()) syntax::PostfixUnaryOperatorExpression, 1289ec727ea7Spatrick S); 1290ec727ea7Spatrick return true; 1291*a9ac8606Spatrick case syntax::NodeKind::CallExpression: { 1292*a9ac8606Spatrick Builder.markExprChild(S->getArg(0), syntax::NodeRole::Callee); 1293*a9ac8606Spatrick 1294*a9ac8606Spatrick const auto *LParenToken = 1295*a9ac8606Spatrick std::next(Builder.findToken(S->getArg(0)->getEndLoc())); 1296*a9ac8606Spatrick // FIXME: Assert that `LParenToken` is indeed a `l_paren` once we have 1297*a9ac8606Spatrick // fixed the test on decltype desctructors. 1298*a9ac8606Spatrick if (LParenToken->kind() == clang::tok::l_paren) 1299*a9ac8606Spatrick Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen); 1300*a9ac8606Spatrick 1301*a9ac8606Spatrick Builder.markChild(buildCallArguments(CallExpr::arg_range( 1302*a9ac8606Spatrick S->arg_begin() + 1, S->arg_end())), 1303*a9ac8606Spatrick syntax::NodeRole::Arguments); 1304*a9ac8606Spatrick 1305*a9ac8606Spatrick Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen); 1306*a9ac8606Spatrick 1307*a9ac8606Spatrick Builder.foldNode(Builder.getRange(S->getSourceRange()), 1308*a9ac8606Spatrick new (allocator()) syntax::CallExpression, S); 1309*a9ac8606Spatrick return true; 1310*a9ac8606Spatrick } 1311ec727ea7Spatrick case syntax::NodeKind::UnknownExpression: 1312*a9ac8606Spatrick return WalkUpFromExpr(S); 1313ec727ea7Spatrick default: 1314ec727ea7Spatrick llvm_unreachable("getOperatorNodeKind() does not return this value"); 1315ec727ea7Spatrick } 1316ec727ea7Spatrick } 1317ec727ea7Spatrick 1318*a9ac8606Spatrick bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; } 1319*a9ac8606Spatrick 1320e5dd7070Spatrick bool WalkUpFromNamespaceDecl(NamespaceDecl *S) { 1321ec727ea7Spatrick auto Tokens = Builder.getDeclarationRange(S); 1322e5dd7070Spatrick if (Tokens.front().kind() == tok::coloncolon) { 1323e5dd7070Spatrick // Handle nested namespace definitions. Those start at '::' token, e.g. 1324e5dd7070Spatrick // namespace a^::b {} 1325e5dd7070Spatrick // FIXME: build corresponding nodes for the name of this namespace. 1326e5dd7070Spatrick return true; 1327e5dd7070Spatrick } 1328ec727ea7Spatrick Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition, S); 1329ec727ea7Spatrick return true; 1330ec727ea7Spatrick } 1331ec727ea7Spatrick 1332*a9ac8606Spatrick // FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test 1333*a9ac8606Spatrick // results. Find test coverage or remove it. 1334ec727ea7Spatrick bool TraverseParenTypeLoc(ParenTypeLoc L) { 1335ec727ea7Spatrick // We reverse order of traversal to get the proper syntax structure. 1336ec727ea7Spatrick if (!WalkUpFromParenTypeLoc(L)) 1337ec727ea7Spatrick return false; 1338ec727ea7Spatrick return TraverseTypeLoc(L.getInnerLoc()); 1339ec727ea7Spatrick } 1340ec727ea7Spatrick 1341ec727ea7Spatrick bool WalkUpFromParenTypeLoc(ParenTypeLoc L) { 1342ec727ea7Spatrick Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen); 1343ec727ea7Spatrick Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen); 1344ec727ea7Spatrick Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getRParenLoc()), 1345ec727ea7Spatrick new (allocator()) syntax::ParenDeclarator, L); 1346ec727ea7Spatrick return true; 1347ec727ea7Spatrick } 1348ec727ea7Spatrick 1349ec727ea7Spatrick // Declarator chunks, they are produced by type locs and some clang::Decls. 1350ec727ea7Spatrick bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L) { 1351ec727ea7Spatrick Builder.markChildToken(L.getLBracketLoc(), syntax::NodeRole::OpenParen); 1352*a9ac8606Spatrick Builder.markExprChild(L.getSizeExpr(), syntax::NodeRole::Size); 1353ec727ea7Spatrick Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen); 1354ec727ea7Spatrick Builder.foldNode(Builder.getRange(L.getLBracketLoc(), L.getRBracketLoc()), 1355ec727ea7Spatrick new (allocator()) syntax::ArraySubscript, L); 1356ec727ea7Spatrick return true; 1357ec727ea7Spatrick } 1358ec727ea7Spatrick 1359*a9ac8606Spatrick syntax::ParameterDeclarationList * 1360*a9ac8606Spatrick buildParameterDeclarationList(ArrayRef<ParmVarDecl *> Params) { 1361*a9ac8606Spatrick for (auto *P : Params) { 1362*a9ac8606Spatrick Builder.markChild(P, syntax::NodeRole::ListElement); 1363*a9ac8606Spatrick const auto *DelimiterToken = std::next(Builder.findToken(P->getEndLoc())); 1364*a9ac8606Spatrick if (DelimiterToken->kind() == clang::tok::TokenKind::comma) 1365*a9ac8606Spatrick Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter); 1366*a9ac8606Spatrick } 1367*a9ac8606Spatrick auto *Parameters = new (allocator()) syntax::ParameterDeclarationList; 1368*a9ac8606Spatrick if (!Params.empty()) 1369*a9ac8606Spatrick Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(), 1370*a9ac8606Spatrick Params.back()->getEndLoc()), 1371*a9ac8606Spatrick Parameters, nullptr); 1372*a9ac8606Spatrick return Parameters; 1373*a9ac8606Spatrick } 1374*a9ac8606Spatrick 1375ec727ea7Spatrick bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L) { 1376ec727ea7Spatrick Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen); 1377*a9ac8606Spatrick 1378*a9ac8606Spatrick Builder.markChild(buildParameterDeclarationList(L.getParams()), 1379*a9ac8606Spatrick syntax::NodeRole::Parameters); 1380*a9ac8606Spatrick 1381ec727ea7Spatrick Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen); 1382ec727ea7Spatrick Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()), 1383ec727ea7Spatrick new (allocator()) syntax::ParametersAndQualifiers, L); 1384ec727ea7Spatrick return true; 1385ec727ea7Spatrick } 1386ec727ea7Spatrick 1387ec727ea7Spatrick bool WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L) { 1388ec727ea7Spatrick if (!L.getTypePtr()->hasTrailingReturn()) 1389ec727ea7Spatrick return WalkUpFromFunctionTypeLoc(L); 1390ec727ea7Spatrick 1391*a9ac8606Spatrick auto *TrailingReturnTokens = buildTrailingReturn(L); 1392ec727ea7Spatrick // Finish building the node for parameters. 1393*a9ac8606Spatrick Builder.markChild(TrailingReturnTokens, syntax::NodeRole::TrailingReturn); 1394ec727ea7Spatrick return WalkUpFromFunctionTypeLoc(L); 1395ec727ea7Spatrick } 1396ec727ea7Spatrick 1397*a9ac8606Spatrick bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) { 1398*a9ac8606Spatrick // In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds 1399*a9ac8606Spatrick // to "Y::*" but it points to a `ParenTypeLoc` that corresponds to 1400*a9ac8606Spatrick // "(Y::*mp)" We thus reverse the order of traversal to get the proper 1401*a9ac8606Spatrick // syntax structure. 1402*a9ac8606Spatrick if (!WalkUpFromMemberPointerTypeLoc(L)) 1403*a9ac8606Spatrick return false; 1404*a9ac8606Spatrick return TraverseTypeLoc(L.getPointeeLoc()); 1405*a9ac8606Spatrick } 1406*a9ac8606Spatrick 1407ec727ea7Spatrick bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) { 1408ec727ea7Spatrick auto SR = L.getLocalSourceRange(); 1409ec727ea7Spatrick Builder.foldNode(Builder.getRange(SR), 1410ec727ea7Spatrick new (allocator()) syntax::MemberPointer, L); 1411e5dd7070Spatrick return true; 1412e5dd7070Spatrick } 1413e5dd7070Spatrick 1414e5dd7070Spatrick // The code below is very regular, it could even be generated with some 1415e5dd7070Spatrick // preprocessor magic. We merely assign roles to the corresponding children 1416e5dd7070Spatrick // and fold resulting nodes. 1417e5dd7070Spatrick bool WalkUpFromDeclStmt(DeclStmt *S) { 1418e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1419ec727ea7Spatrick new (allocator()) syntax::DeclarationStatement, S); 1420e5dd7070Spatrick return true; 1421e5dd7070Spatrick } 1422e5dd7070Spatrick 1423e5dd7070Spatrick bool WalkUpFromNullStmt(NullStmt *S) { 1424e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1425ec727ea7Spatrick new (allocator()) syntax::EmptyStatement, S); 1426e5dd7070Spatrick return true; 1427e5dd7070Spatrick } 1428e5dd7070Spatrick 1429e5dd7070Spatrick bool WalkUpFromSwitchStmt(SwitchStmt *S) { 1430e5dd7070Spatrick Builder.markChildToken(S->getSwitchLoc(), 1431e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1432e5dd7070Spatrick Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 1433e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1434ec727ea7Spatrick new (allocator()) syntax::SwitchStatement, S); 1435e5dd7070Spatrick return true; 1436e5dd7070Spatrick } 1437e5dd7070Spatrick 1438e5dd7070Spatrick bool WalkUpFromCaseStmt(CaseStmt *S) { 1439e5dd7070Spatrick Builder.markChildToken(S->getKeywordLoc(), 1440e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1441*a9ac8606Spatrick Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseValue); 1442e5dd7070Spatrick Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 1443e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1444ec727ea7Spatrick new (allocator()) syntax::CaseStatement, S); 1445e5dd7070Spatrick return true; 1446e5dd7070Spatrick } 1447e5dd7070Spatrick 1448e5dd7070Spatrick bool WalkUpFromDefaultStmt(DefaultStmt *S) { 1449e5dd7070Spatrick Builder.markChildToken(S->getKeywordLoc(), 1450e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1451e5dd7070Spatrick Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement); 1452e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1453ec727ea7Spatrick new (allocator()) syntax::DefaultStatement, S); 1454e5dd7070Spatrick return true; 1455e5dd7070Spatrick } 1456e5dd7070Spatrick 1457e5dd7070Spatrick bool WalkUpFromIfStmt(IfStmt *S) { 1458e5dd7070Spatrick Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword); 1459*a9ac8606Spatrick Stmt *ConditionStatement = S->getCond(); 1460*a9ac8606Spatrick if (S->hasVarStorage()) 1461*a9ac8606Spatrick ConditionStatement = S->getConditionVariableDeclStmt(); 1462*a9ac8606Spatrick Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition); 1463*a9ac8606Spatrick Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement); 1464*a9ac8606Spatrick Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword); 1465*a9ac8606Spatrick Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement); 1466e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1467ec727ea7Spatrick new (allocator()) syntax::IfStatement, S); 1468e5dd7070Spatrick return true; 1469e5dd7070Spatrick } 1470e5dd7070Spatrick 1471e5dd7070Spatrick bool WalkUpFromForStmt(ForStmt *S) { 1472e5dd7070Spatrick Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 1473e5dd7070Spatrick Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 1474e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1475ec727ea7Spatrick new (allocator()) syntax::ForStatement, S); 1476e5dd7070Spatrick return true; 1477e5dd7070Spatrick } 1478e5dd7070Spatrick 1479e5dd7070Spatrick bool WalkUpFromWhileStmt(WhileStmt *S) { 1480e5dd7070Spatrick Builder.markChildToken(S->getWhileLoc(), 1481e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1482e5dd7070Spatrick Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 1483e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1484ec727ea7Spatrick new (allocator()) syntax::WhileStatement, S); 1485e5dd7070Spatrick return true; 1486e5dd7070Spatrick } 1487e5dd7070Spatrick 1488e5dd7070Spatrick bool WalkUpFromContinueStmt(ContinueStmt *S) { 1489e5dd7070Spatrick Builder.markChildToken(S->getContinueLoc(), 1490e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1491e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1492ec727ea7Spatrick new (allocator()) syntax::ContinueStatement, S); 1493e5dd7070Spatrick return true; 1494e5dd7070Spatrick } 1495e5dd7070Spatrick 1496e5dd7070Spatrick bool WalkUpFromBreakStmt(BreakStmt *S) { 1497e5dd7070Spatrick Builder.markChildToken(S->getBreakLoc(), 1498e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1499e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1500ec727ea7Spatrick new (allocator()) syntax::BreakStatement, S); 1501e5dd7070Spatrick return true; 1502e5dd7070Spatrick } 1503e5dd7070Spatrick 1504e5dd7070Spatrick bool WalkUpFromReturnStmt(ReturnStmt *S) { 1505e5dd7070Spatrick Builder.markChildToken(S->getReturnLoc(), 1506e5dd7070Spatrick syntax::NodeRole::IntroducerKeyword); 1507*a9ac8606Spatrick Builder.markExprChild(S->getRetValue(), syntax::NodeRole::ReturnValue); 1508e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1509ec727ea7Spatrick new (allocator()) syntax::ReturnStatement, S); 1510e5dd7070Spatrick return true; 1511e5dd7070Spatrick } 1512e5dd7070Spatrick 1513e5dd7070Spatrick bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) { 1514e5dd7070Spatrick Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword); 1515e5dd7070Spatrick Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement); 1516e5dd7070Spatrick Builder.foldNode(Builder.getStmtRange(S), 1517ec727ea7Spatrick new (allocator()) syntax::RangeBasedForStatement, S); 1518e5dd7070Spatrick return true; 1519e5dd7070Spatrick } 1520e5dd7070Spatrick 1521e5dd7070Spatrick bool WalkUpFromEmptyDecl(EmptyDecl *S) { 1522ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1523ec727ea7Spatrick new (allocator()) syntax::EmptyDeclaration, S); 1524e5dd7070Spatrick return true; 1525e5dd7070Spatrick } 1526e5dd7070Spatrick 1527e5dd7070Spatrick bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) { 1528*a9ac8606Spatrick Builder.markExprChild(S->getAssertExpr(), syntax::NodeRole::Condition); 1529*a9ac8606Spatrick Builder.markExprChild(S->getMessage(), syntax::NodeRole::Message); 1530ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1531ec727ea7Spatrick new (allocator()) syntax::StaticAssertDeclaration, S); 1532e5dd7070Spatrick return true; 1533e5dd7070Spatrick } 1534e5dd7070Spatrick 1535e5dd7070Spatrick bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) { 1536ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1537ec727ea7Spatrick new (allocator()) syntax::LinkageSpecificationDeclaration, 1538ec727ea7Spatrick S); 1539e5dd7070Spatrick return true; 1540e5dd7070Spatrick } 1541e5dd7070Spatrick 1542e5dd7070Spatrick bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) { 1543ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1544ec727ea7Spatrick new (allocator()) syntax::NamespaceAliasDefinition, S); 1545e5dd7070Spatrick return true; 1546e5dd7070Spatrick } 1547e5dd7070Spatrick 1548e5dd7070Spatrick bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) { 1549ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1550ec727ea7Spatrick new (allocator()) syntax::UsingNamespaceDirective, S); 1551e5dd7070Spatrick return true; 1552e5dd7070Spatrick } 1553e5dd7070Spatrick 1554e5dd7070Spatrick bool WalkUpFromUsingDecl(UsingDecl *S) { 1555ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1556ec727ea7Spatrick new (allocator()) syntax::UsingDeclaration, S); 1557e5dd7070Spatrick return true; 1558e5dd7070Spatrick } 1559e5dd7070Spatrick 1560e5dd7070Spatrick bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) { 1561ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1562ec727ea7Spatrick new (allocator()) syntax::UsingDeclaration, S); 1563e5dd7070Spatrick return true; 1564e5dd7070Spatrick } 1565e5dd7070Spatrick 1566e5dd7070Spatrick bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) { 1567ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1568ec727ea7Spatrick new (allocator()) syntax::UsingDeclaration, S); 1569e5dd7070Spatrick return true; 1570e5dd7070Spatrick } 1571e5dd7070Spatrick 1572e5dd7070Spatrick bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) { 1573ec727ea7Spatrick Builder.foldNode(Builder.getDeclarationRange(S), 1574ec727ea7Spatrick new (allocator()) syntax::TypeAliasDeclaration, S); 1575e5dd7070Spatrick return true; 1576e5dd7070Spatrick } 1577e5dd7070Spatrick 1578e5dd7070Spatrick private: 1579ec727ea7Spatrick /// Folds SimpleDeclarator node (if present) and in case this is the last 1580ec727ea7Spatrick /// declarator in the chain it also folds SimpleDeclaration node. 1581ec727ea7Spatrick template <class T> bool processDeclaratorAndDeclaration(T *D) { 1582*a9ac8606Spatrick auto Range = getDeclaratorRange( 1583*a9ac8606Spatrick Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(), 1584*a9ac8606Spatrick getQualifiedNameStart(D), getInitializerRange(D)); 1585ec727ea7Spatrick 1586ec727ea7Spatrick // There doesn't have to be a declarator (e.g. `void foo(int)` only has 1587ec727ea7Spatrick // declaration, but no declarator). 1588*a9ac8606Spatrick if (!Range.getBegin().isValid()) { 1589*a9ac8606Spatrick Builder.markChild(new (allocator()) syntax::DeclaratorList, 1590*a9ac8606Spatrick syntax::NodeRole::Declarators); 1591*a9ac8606Spatrick Builder.foldNode(Builder.getDeclarationRange(D), 1592*a9ac8606Spatrick new (allocator()) syntax::SimpleDeclaration, D); 1593*a9ac8606Spatrick return true; 1594ec727ea7Spatrick } 1595ec727ea7Spatrick 1596*a9ac8606Spatrick auto *N = new (allocator()) syntax::SimpleDeclarator; 1597*a9ac8606Spatrick Builder.foldNode(Builder.getRange(Range), N, nullptr); 1598*a9ac8606Spatrick Builder.markChild(N, syntax::NodeRole::ListElement); 1599*a9ac8606Spatrick 1600*a9ac8606Spatrick if (!Builder.isResponsibleForCreatingDeclaration(D)) { 1601*a9ac8606Spatrick // If this is not the last declarator in the declaration we expect a 1602*a9ac8606Spatrick // delimiter after it. 1603*a9ac8606Spatrick const auto *DelimiterToken = std::next(Builder.findToken(Range.getEnd())); 1604*a9ac8606Spatrick if (DelimiterToken->kind() == clang::tok::TokenKind::comma) 1605*a9ac8606Spatrick Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter); 1606*a9ac8606Spatrick } else { 1607*a9ac8606Spatrick auto *DL = new (allocator()) syntax::DeclaratorList; 1608*a9ac8606Spatrick auto DeclarationRange = Builder.getDeclarationRange(D); 1609*a9ac8606Spatrick Builder.foldList(DeclarationRange, DL, nullptr); 1610*a9ac8606Spatrick 1611*a9ac8606Spatrick Builder.markChild(DL, syntax::NodeRole::Declarators); 1612*a9ac8606Spatrick Builder.foldNode(DeclarationRange, 1613ec727ea7Spatrick new (allocator()) syntax::SimpleDeclaration, D); 1614ec727ea7Spatrick } 1615ec727ea7Spatrick return true; 1616ec727ea7Spatrick } 1617ec727ea7Spatrick 1618ec727ea7Spatrick /// Returns the range of the built node. 1619*a9ac8606Spatrick syntax::TrailingReturnType *buildTrailingReturn(FunctionProtoTypeLoc L) { 1620ec727ea7Spatrick assert(L.getTypePtr()->hasTrailingReturn()); 1621ec727ea7Spatrick 1622ec727ea7Spatrick auto ReturnedType = L.getReturnLoc(); 1623ec727ea7Spatrick // Build node for the declarator, if any. 1624*a9ac8606Spatrick auto ReturnDeclaratorRange = SourceRange(GetStartLoc().Visit(ReturnedType), 1625*a9ac8606Spatrick ReturnedType.getEndLoc()); 1626ec727ea7Spatrick syntax::SimpleDeclarator *ReturnDeclarator = nullptr; 1627ec727ea7Spatrick if (ReturnDeclaratorRange.isValid()) { 1628ec727ea7Spatrick ReturnDeclarator = new (allocator()) syntax::SimpleDeclarator; 1629ec727ea7Spatrick Builder.foldNode(Builder.getRange(ReturnDeclaratorRange), 1630ec727ea7Spatrick ReturnDeclarator, nullptr); 1631ec727ea7Spatrick } 1632ec727ea7Spatrick 1633ec727ea7Spatrick // Build node for trailing return type. 1634ec727ea7Spatrick auto Return = Builder.getRange(ReturnedType.getSourceRange()); 1635ec727ea7Spatrick const auto *Arrow = Return.begin() - 1; 1636ec727ea7Spatrick assert(Arrow->kind() == tok::arrow); 1637ec727ea7Spatrick auto Tokens = llvm::makeArrayRef(Arrow, Return.end()); 1638ec727ea7Spatrick Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken); 1639ec727ea7Spatrick if (ReturnDeclarator) 1640*a9ac8606Spatrick Builder.markChild(ReturnDeclarator, syntax::NodeRole::Declarator); 1641ec727ea7Spatrick auto *R = new (allocator()) syntax::TrailingReturnType; 1642ec727ea7Spatrick Builder.foldNode(Tokens, R, L); 1643ec727ea7Spatrick return R; 1644ec727ea7Spatrick } 1645ec727ea7Spatrick 1646ec727ea7Spatrick void foldExplicitTemplateInstantiation( 1647ec727ea7Spatrick ArrayRef<syntax::Token> Range, const syntax::Token *ExternKW, 1648ec727ea7Spatrick const syntax::Token *TemplateKW, 1649ec727ea7Spatrick syntax::SimpleDeclaration *InnerDeclaration, Decl *From) { 1650ec727ea7Spatrick assert(!ExternKW || ExternKW->kind() == tok::kw_extern); 1651ec727ea7Spatrick assert(TemplateKW && TemplateKW->kind() == tok::kw_template); 1652ec727ea7Spatrick Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword); 1653ec727ea7Spatrick Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword); 1654*a9ac8606Spatrick Builder.markChild(InnerDeclaration, syntax::NodeRole::Declaration); 1655ec727ea7Spatrick Builder.foldNode( 1656ec727ea7Spatrick Range, new (allocator()) syntax::ExplicitTemplateInstantiation, From); 1657ec727ea7Spatrick } 1658ec727ea7Spatrick 1659ec727ea7Spatrick syntax::TemplateDeclaration *foldTemplateDeclaration( 1660ec727ea7Spatrick ArrayRef<syntax::Token> Range, const syntax::Token *TemplateKW, 1661ec727ea7Spatrick ArrayRef<syntax::Token> TemplatedDeclaration, Decl *From) { 1662ec727ea7Spatrick assert(TemplateKW && TemplateKW->kind() == tok::kw_template); 1663ec727ea7Spatrick Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword); 1664ec727ea7Spatrick 1665ec727ea7Spatrick auto *N = new (allocator()) syntax::TemplateDeclaration; 1666ec727ea7Spatrick Builder.foldNode(Range, N, From); 1667*a9ac8606Spatrick Builder.markChild(N, syntax::NodeRole::Declaration); 1668ec727ea7Spatrick return N; 1669ec727ea7Spatrick } 1670ec727ea7Spatrick 1671e5dd7070Spatrick /// A small helper to save some typing. 1672e5dd7070Spatrick llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); } 1673e5dd7070Spatrick 1674e5dd7070Spatrick syntax::TreeBuilder &Builder; 1675ec727ea7Spatrick const ASTContext &Context; 1676e5dd7070Spatrick }; 1677e5dd7070Spatrick } // namespace 1678e5dd7070Spatrick 1679ec727ea7Spatrick void syntax::TreeBuilder::noticeDeclWithoutSemicolon(Decl *D) { 1680e5dd7070Spatrick DeclsWithoutSemicolons.insert(D); 1681e5dd7070Spatrick } 1682e5dd7070Spatrick 1683e5dd7070Spatrick void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) { 1684e5dd7070Spatrick if (Loc.isInvalid()) 1685e5dd7070Spatrick return; 1686e5dd7070Spatrick Pending.assignRole(*findToken(Loc), Role); 1687e5dd7070Spatrick } 1688e5dd7070Spatrick 1689ec727ea7Spatrick void syntax::TreeBuilder::markChildToken(const syntax::Token *T, NodeRole R) { 1690ec727ea7Spatrick if (!T) 1691ec727ea7Spatrick return; 1692ec727ea7Spatrick Pending.assignRole(*T, R); 1693ec727ea7Spatrick } 1694ec727ea7Spatrick 1695ec727ea7Spatrick void syntax::TreeBuilder::markChild(syntax::Node *N, NodeRole R) { 1696ec727ea7Spatrick assert(N); 1697ec727ea7Spatrick setRole(N, R); 1698ec727ea7Spatrick } 1699ec727ea7Spatrick 1700ec727ea7Spatrick void syntax::TreeBuilder::markChild(ASTPtr N, NodeRole R) { 1701ec727ea7Spatrick auto *SN = Mapping.find(N); 1702ec727ea7Spatrick assert(SN != nullptr); 1703ec727ea7Spatrick setRole(SN, R); 1704ec727ea7Spatrick } 1705*a9ac8606Spatrick void syntax::TreeBuilder::markChild(NestedNameSpecifierLoc NNSLoc, NodeRole R) { 1706*a9ac8606Spatrick auto *SN = Mapping.find(NNSLoc); 1707*a9ac8606Spatrick assert(SN != nullptr); 1708*a9ac8606Spatrick setRole(SN, R); 1709*a9ac8606Spatrick } 1710ec727ea7Spatrick 1711e5dd7070Spatrick void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) { 1712e5dd7070Spatrick if (!Child) 1713e5dd7070Spatrick return; 1714e5dd7070Spatrick 1715ec727ea7Spatrick syntax::Tree *ChildNode; 1716ec727ea7Spatrick if (Expr *ChildExpr = dyn_cast<Expr>(Child)) { 1717e5dd7070Spatrick // This is an expression in a statement position, consume the trailing 1718e5dd7070Spatrick // semicolon and form an 'ExpressionStatement' node. 1719*a9ac8606Spatrick markExprChild(ChildExpr, NodeRole::Expression); 1720ec727ea7Spatrick ChildNode = new (allocator()) syntax::ExpressionStatement; 1721ec727ea7Spatrick // (!) 'getStmtRange()' ensures this covers a trailing semicolon. 1722ec727ea7Spatrick Pending.foldChildren(Arena, getStmtRange(Child), ChildNode); 1723ec727ea7Spatrick } else { 1724ec727ea7Spatrick ChildNode = Mapping.find(Child); 1725e5dd7070Spatrick } 1726ec727ea7Spatrick assert(ChildNode != nullptr); 1727ec727ea7Spatrick setRole(ChildNode, Role); 1728e5dd7070Spatrick } 1729e5dd7070Spatrick 1730e5dd7070Spatrick void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) { 1731e5dd7070Spatrick if (!Child) 1732e5dd7070Spatrick return; 1733*a9ac8606Spatrick Child = IgnoreImplicit(Child); 1734e5dd7070Spatrick 1735ec727ea7Spatrick syntax::Tree *ChildNode = Mapping.find(Child); 1736ec727ea7Spatrick assert(ChildNode != nullptr); 1737ec727ea7Spatrick setRole(ChildNode, Role); 1738e5dd7070Spatrick } 1739e5dd7070Spatrick 1740e5dd7070Spatrick const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const { 1741ec727ea7Spatrick if (L.isInvalid()) 1742ec727ea7Spatrick return nullptr; 1743*a9ac8606Spatrick auto It = LocationToToken.find(L); 1744e5dd7070Spatrick assert(It != LocationToToken.end()); 1745e5dd7070Spatrick return It->second; 1746e5dd7070Spatrick } 1747e5dd7070Spatrick 1748*a9ac8606Spatrick syntax::TranslationUnit *syntax::buildSyntaxTree(Arena &A, 1749*a9ac8606Spatrick ASTContext &Context) { 1750e5dd7070Spatrick TreeBuilder Builder(A); 1751*a9ac8606Spatrick BuildTreeVisitor(Context, Builder).TraverseAST(Context); 1752e5dd7070Spatrick return std::move(Builder).finalize(); 1753e5dd7070Spatrick } 1754