//===- BuildTree.cpp ------------------------------------------*- C++ -*-=====//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Syntax/BuildTree.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/IgnoreExpr.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Tooling/Syntax/Nodes.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "clang/Tooling/Syntax/Tree.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstddef>
#include <map>

using namespace clang;

// Ignores the implicit `CXXConstructExpr` for copy/move constructor calls
// generated by the compiler, as well as in implicit conversions like the one
// wrapping `1` in `X x = 1;`.
static Expr *IgnoreImplicitConstructorSingleStep(Expr *E) {
  if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
    auto NumArgs = C->getNumArgs();
    if (NumArgs == 1 || (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
      Expr *A = C->getArg(0);
      if (C->getParenOrBraceRange().isInvalid())
        return A;
    }
  }
  return E;
}

// In:
// struct X {
//   X(int)
// };
// X x = X(1);
// Ignores the implicit `CXXFunctionalCastExpr` that wraps
// `CXXConstructExpr X(1)`.
static Expr *IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E) {
  if (auto *F = dyn_cast<CXXFunctionalCastExpr>(E)) {
    if (F->getCastKind() == CK_ConstructorConversion)
      return F->getSubExpr();
  }
  return E;
}

static Expr *IgnoreImplicit(Expr *E) {
  return IgnoreExprNodes(E, IgnoreImplicitSingleStep,
                         IgnoreImplicitConstructorSingleStep,
                         IgnoreCXXFunctionalCastExprWrappingConstructor);
}

LLVM_ATTRIBUTE_UNUSED
static bool isImplicitExpr(Expr *E) { return IgnoreImplicit(E) != E; }

namespace {
/// Get start location of the Declarator from the TypeLoc.
/// E.g.:
///   loc of `(` in `int (a)`
///   loc of `*` in `int *(a)`
///   loc of the first `(` in `int (*a)(int)`
///   loc of the `*` in `int *(a)(int)`
///   loc of the first `*` in `const int *const *volatile a;`
///
/// It is non-trivial to get the start location because TypeLocs are stored
/// inside out. In the example above `*volatile` is the TypeLoc returned
/// by `Decl.getTypeSourceInfo()`, and `*const` is what `.getPointeeLoc()`
/// returns.
struct GetStartLoc : TypeLocVisitor<GetStartLoc, SourceLocation> {
  SourceLocation VisitParenTypeLoc(ParenTypeLoc T) {
    auto L = Visit(T.getInnerLoc());
    if (L.isValid())
      return L;
    return T.getLParenLoc();
  }

  // Types spelled in the prefix part of the declarator.
  SourceLocation VisitPointerTypeLoc(PointerTypeLoc T) {
    return HandlePointer(T);
  }

  SourceLocation VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
    return HandlePointer(T);
  }

  SourceLocation VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
    return HandlePointer(T);
  }

  SourceLocation VisitReferenceTypeLoc(ReferenceTypeLoc T) {
    return HandlePointer(T);
  }

  SourceLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc T) {
    return HandlePointer(T);
  }

  // All other cases are not important, as they are either part of declaration
  // specifiers (e.g. inheritors of TypeSpecTypeLoc) or introduce modifiers on
  // existing declarators (e.g. QualifiedTypeLoc). They cannot start the
  // declarator themselves, but their underlying type can.
  SourceLocation VisitTypeLoc(TypeLoc T) {
    auto N = T.getNextTypeLoc();
    if (!N)
      return SourceLocation();
    return Visit(N);
  }

  SourceLocation VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc T) {
    if (T.getTypePtr()->hasTrailingReturn())
      return SourceLocation(); // avoid recursing into the suffix of declarator.
    return VisitTypeLoc(T);
  }

private:
  template <class PtrLoc> SourceLocation HandlePointer(PtrLoc T) {
    auto L = Visit(T.getPointeeLoc());
    if (L.isValid())
      return L;
    return T.getLocalSourceRange().getBegin();
  }
};
} // namespace

static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) {
  auto FirstDefaultArg =
      llvm::find_if(Args, [](auto It) { return isa<CXXDefaultArgExpr>(It); });
  return llvm::make_range(Args.begin(), FirstDefaultArg);
}

static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) {
  switch (E.getOperator()) {
  // Comparison
  case OO_EqualEqual:
  case OO_ExclaimEqual:
  case OO_Greater:
  case OO_GreaterEqual:
  case OO_Less:
  case OO_LessEqual:
  case OO_Spaceship:
  // Assignment
  case OO_Equal:
  case OO_SlashEqual:
  case OO_PercentEqual:
  case OO_CaretEqual:
  case OO_PipeEqual:
  case OO_LessLessEqual:
  case OO_GreaterGreaterEqual:
  case OO_PlusEqual:
  case OO_MinusEqual:
  case OO_StarEqual:
  case OO_AmpEqual:
  // Binary computation
  case OO_Slash:
  case OO_Percent:
  case OO_Caret:
  case OO_Pipe:
  case OO_LessLess:
  case OO_GreaterGreater:
  case OO_AmpAmp:
  case OO_PipePipe:
  case OO_ArrowStar:
  case OO_Comma:
    return syntax::NodeKind::BinaryOperatorExpression;
  case OO_Tilde:
  case OO_Exclaim:
    return syntax::NodeKind::PrefixUnaryOperatorExpression;
  // Prefix/Postfix increment/decrement
  case OO_PlusPlus:
  case OO_MinusMinus:
    switch (E.getNumArgs()) {
    case 1:
      return syntax::NodeKind::PrefixUnaryOperatorExpression;
    case 2:
      return syntax::NodeKind::PostfixUnaryOperatorExpression;
    default:
      llvm_unreachable("Invalid number of arguments for operator");
    }
  // Operators that can be unary or binary
  case OO_Plus:
  case OO_Minus:
  case OO_Star:
  case OO_Amp:
    switch (E.getNumArgs()) {
    case 1:
      return syntax::NodeKind::PrefixUnaryOperatorExpression;
    case 2:
      return syntax::NodeKind::BinaryOperatorExpression;
    default:
      llvm_unreachable("Invalid number of arguments for operator");
    }
    return syntax::NodeKind::BinaryOperatorExpression;
  // Not yet supported by SyntaxTree
  case OO_New:
  case OO_Delete:
  case OO_Array_New:
  case OO_Array_Delete:
  case OO_Coawait:
  case OO_Subscript:
  case OO_Arrow:
    return syntax::NodeKind::UnknownExpression;
  case OO_Call:
    return syntax::NodeKind::CallExpression;
  case OO_Conditional: // not overloadable
  case NUM_OVERLOADED_OPERATORS:
  case OO_None:
    llvm_unreachable("Not an overloadable operator");
  }
  llvm_unreachable("Unknown OverloadedOperatorKind enum");
}

/// Get the start of the qualified name. In the examples below it gives the
/// location of the `^`:
///     `int ^a;`
///     `int *^a;`
///     `int ^a::S::f(){}`
static SourceLocation getQualifiedNameStart(NamedDecl *D) {
  assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) &&
         "only DeclaratorDecl and TypedefNameDecl are supported.");

  auto DN = D->getDeclName();
  bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo();
  if (IsAnonymous)
    return SourceLocation();

  if (const auto *DD = dyn_cast<DeclaratorDecl>(D)) {
    if (DD->getQualifierLoc()) {
      return DD->getQualifierLoc().getBeginLoc();
    }
  }

  return D->getLocation();
}

/// Gets the range of the initializer inside an init-declarator C++ [dcl.decl].
///     `int a;` -> range of ``,
///     `int *a = nullptr` -> range of `= nullptr`.
///     `int a{}` -> range of `{}`.
///     `int a()` -> range of `()`.
static SourceRange getInitializerRange(Decl *D) {
  if (auto *V = dyn_cast<VarDecl>(D)) {
    auto *I = V->getInit();
    // Initializers in range-based-for are not part of the declarator
    if (I && !V->isCXXForRangeDecl())
      return I->getSourceRange();
  }

  return SourceRange();
}

/// Gets the range of declarator as defined by the C++ grammar. E.g.
///     `int a;` -> range of `a`,
///     `int *a;` -> range of `*a`,
///     `int a[10];` -> range of `a[10]`,
///     `int a[1][2][3];` -> range of `a[1][2][3]`,
///     `int *a = nullptr` -> range of `*a = nullptr`.
///     `int S::f(){}` -> range of `S::f()`.
/// FIXME: \p Name must be a source range.
static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T,
                                      SourceLocation Name,
                                      SourceRange Initializer) {
  SourceLocation Start = GetStartLoc().Visit(T);
  SourceLocation End = T.getEndLoc();
  if (Name.isValid()) {
    if (Start.isInvalid())
      Start = Name;
    // End of TypeLoc could be invalid if the type is invalid, fallback to the
    // NameLoc.
    if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name))
      End = Name;
  }
  if (Initializer.isValid()) {
    auto InitializerEnd = Initializer.getEnd();
    assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) ||
           End == InitializerEnd);
    End = InitializerEnd;
  }
  return SourceRange(Start, End);
}

namespace {
/// All AST hierarchy roots that can be represented as pointers.
using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;
/// Maintains a mapping from AST to syntax tree nodes. This class will get more
/// complicated as we support more kinds of AST nodes, e.g. TypeLocs.
/// FIXME: expose this as public API.
class ASTToSyntaxMapping {
public:
  void add(ASTPtr From, syntax::Tree *To) {
    assert(To != nullptr);
    assert(!From.isNull());

    bool Added = Nodes.insert({From, To}).second;
    (void)Added;
    assert(Added && "mapping added twice");
  }

  void add(NestedNameSpecifierLoc From, syntax::Tree *To) {
    assert(To != nullptr);
    assert(From.hasQualifier());

    bool Added = NNSNodes.insert({From, To}).second;
    (void)Added;
    assert(Added && "mapping added twice");
  }

  syntax::Tree *find(ASTPtr P) const { return Nodes.lookup(P); }

  syntax::Tree *find(NestedNameSpecifierLoc P) const {
    return NNSNodes.lookup(P);
  }

private:
  llvm::DenseMap<ASTPtr, syntax::Tree *> Nodes;
  llvm::DenseMap<NestedNameSpecifierLoc, syntax::Tree *> NNSNodes;
};
} // namespace

/// A helper class for constructing the syntax tree while traversing a clang
/// AST.
///
/// At each point of the traversal we maintain a list of pending nodes.
/// Initially all tokens are added as pending nodes. When processing a clang AST
/// node, the clients need to:
///   - create a corresponding syntax node,
///   - assign roles to all pending child nodes with 'markChild' and
///     'markChildToken',
///   - replace the child nodes with the new syntax node in the pending list
///     with 'foldNode'.
///
/// Note that all children are expected to be processed when building a node.
///
/// Call finalize() to finish building the tree and consume the root node.
class syntax::TreeBuilder {
public:
  TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) {
    for (const auto &T : Arena.getTokenBuffer().expandedTokens())
      LocationToToken.insert({T.location(), &T});
  }

  llvm::BumpPtrAllocator &allocator() { return Arena.getAllocator(); }
  const SourceManager &sourceManager() const {
    return Arena.getSourceManager();
  }

  /// Populate children for \p New node, assuming it covers tokens from \p
  /// Range.
  void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, ASTPtr From) {
    assert(New);
    Pending.foldChildren(Arena, Range, New);
    if (From)
      Mapping.add(From, New);
  }

  void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, TypeLoc L) {
    // FIXME: add mapping for TypeLocs
    foldNode(Range, New, nullptr);
  }

  void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
                NestedNameSpecifierLoc From) {
    assert(New);
    Pending.foldChildren(Arena, Range, New);
    if (From)
      Mapping.add(From, New);
  }

  /// Populate children for \p New list, assuming it covers tokens from a
  /// subrange of \p SuperRange.
  void foldList(ArrayRef<syntax::Token> SuperRange, syntax::List *New,
                ASTPtr From) {
    assert(New);
    auto ListRange = Pending.shrinkToFitList(SuperRange);
    Pending.foldChildren(Arena, ListRange, New);
    if (From)
      Mapping.add(From, New);
  }

  /// Notifies that we should not consume trailing semicolon when computing
  /// token range of \p D.
  void noticeDeclWithoutSemicolon(Decl *D);

  /// Mark the \p Child node with a corresponding \p Role. All marked children
  /// should be consumed by foldNode.
  /// When called on expressions (clang::Expr is derived from clang::Stmt),
  /// wraps expressions into expression statement.
  void markStmtChild(Stmt *Child, NodeRole Role);
  /// Should be called for expressions in non-statement position to avoid
  /// wrapping into expression statement.
  void markExprChild(Expr *Child, NodeRole Role);
  /// Set role for a token starting at \p Loc.
  void markChildToken(SourceLocation Loc, NodeRole R);
  /// Set role for \p T.
  void markChildToken(const syntax::Token *T, NodeRole R);

  /// Set role for \p N.
  void markChild(syntax::Node *N, NodeRole R);
  /// Set role for the syntax node matching \p N.
  void markChild(ASTPtr N, NodeRole R);
  /// Set role for the syntax node matching \p N.
  void markChild(NestedNameSpecifierLoc N, NodeRole R);

  /// Finish building the tree and consume the root node.
  syntax::TranslationUnit *finalize() && {
    auto Tokens = Arena.getTokenBuffer().expandedTokens();
    assert(!Tokens.empty());
    assert(Tokens.back().kind() == tok::eof);

    // Build the root of the tree, consuming all the children.
    Pending.foldChildren(Arena, Tokens.drop_back(),
                         new (Arena.getAllocator()) syntax::TranslationUnit);

    auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).finalize());
    TU->assertInvariantsRecursive();
    return TU;
  }

  /// Finds a token starting at \p L. The token must exist if \p L is valid.
  const syntax::Token *findToken(SourceLocation L) const;

  /// Finds the syntax tokens corresponding to the \p SourceRange.
  ArrayRef<syntax::Token> getRange(SourceRange Range) const {
    assert(Range.isValid());
    return getRange(Range.getBegin(), Range.getEnd());
  }

  /// Finds the syntax tokens corresponding to the passed source locations.
  /// \p First is the start position of the first token and \p Last is the start
  /// position of the last token.
  ArrayRef<syntax::Token> getRange(SourceLocation First,
                                   SourceLocation Last) const {
    assert(First.isValid());
    assert(Last.isValid());
    assert(First == Last ||
           Arena.getSourceManager().isBeforeInTranslationUnit(First, Last));
    return llvm::makeArrayRef(findToken(First), std::next(findToken(Last)));
  }

  ArrayRef<syntax::Token>
  getTemplateRange(const ClassTemplateSpecializationDecl *D) const {
    auto Tokens = getRange(D->getSourceRange());
    return maybeAppendSemicolon(Tokens, D);
  }

  /// Returns true if \p D is the last declarator in a chain and is thus
  /// reponsible for creating SimpleDeclaration for the whole chain.
  bool isResponsibleForCreatingDeclaration(const Decl *D) const {
    assert((isa<DeclaratorDecl, TypedefNameDecl>(D)) &&
           "only DeclaratorDecl and TypedefNameDecl are supported.");

    const Decl *Next = D->getNextDeclInContext();

    // There's no next sibling, this one is responsible.
    if (Next == nullptr) {
      return true;
    }

    // Next sibling is not the same type, this one is responsible.
    if (D->getKind() != Next->getKind()) {
      return true;
    }
    // Next sibling doesn't begin at the same loc, it must be a different
    // declaration, so this declarator is responsible.
    if (Next->getBeginLoc() != D->getBeginLoc()) {
      return true;
    }

    // NextT is a member of the same declaration, and we need the last member to
    // create declaration. This one is not responsible.
    return false;
  }

  ArrayRef<syntax::Token> getDeclarationRange(Decl *D) {
    ArrayRef<syntax::Token> Tokens;
    // We want to drop the template parameters for specializations.
    if (const auto *S = dyn_cast<TagDecl>(D))
      Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());
    else
      Tokens = getRange(D->getSourceRange());
    return maybeAppendSemicolon(Tokens, D);
  }

  ArrayRef<syntax::Token> getExprRange(const Expr *E) const {
    return getRange(E->getSourceRange());
  }

  /// Find the adjusted range for the statement, consuming the trailing
  /// semicolon when needed.
  ArrayRef<syntax::Token> getStmtRange(const Stmt *S) const {
    auto Tokens = getRange(S->getSourceRange());
    if (isa<CompoundStmt>(S))
      return Tokens;

    // Some statements miss a trailing semicolon, e.g. 'return', 'continue' and
    // all statements that end with those. Consume this semicolon here.
    if (Tokens.back().kind() == tok::semi)
      return Tokens;
    return withTrailingSemicolon(Tokens);
  }

private:
  ArrayRef<syntax::Token> maybeAppendSemicolon(ArrayRef<syntax::Token> Tokens,
                                               const Decl *D) const {
    if (isa<NamespaceDecl>(D))
      return Tokens;
    if (DeclsWithoutSemicolons.count(D))
      return Tokens;
    // FIXME: do not consume trailing semicolon on function definitions.
    // Most declarations own a semicolon in syntax trees, but not in clang AST.
    return withTrailingSemicolon(Tokens);
  }

  ArrayRef<syntax::Token>
  withTrailingSemicolon(ArrayRef<syntax::Token> Tokens) const {
    assert(!Tokens.empty());
    assert(Tokens.back().kind() != tok::eof);
    // We never consume 'eof', so looking at the next token is ok.
    if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi)
      return llvm::makeArrayRef(Tokens.begin(), Tokens.end() + 1);
    return Tokens;
  }

  void setRole(syntax::Node *N, NodeRole R) {
    assert(N->getRole() == NodeRole::Detached);
    N->setRole(R);
  }

  /// A collection of trees covering the input tokens.
  /// When created, each tree corresponds to a single token in the file.
  /// Clients call 'foldChildren' to attach one or more subtrees to a parent
  /// node and update the list of trees accordingly.
  ///
  /// Ensures that added nodes properly nest and cover the whole token stream.
  struct Forest {
    Forest(syntax::Arena &A) {
      assert(!A.getTokenBuffer().expandedTokens().empty());
      assert(A.getTokenBuffer().expandedTokens().back().kind() == tok::eof);
      // Create all leaf nodes.
      // Note that we do not have 'eof' in the tree.
      for (const auto &T : A.getTokenBuffer().expandedTokens().drop_back()) {
        auto *L = new (A.getAllocator()) syntax::Leaf(&T);
        L->Original = true;
        L->CanModify = A.getTokenBuffer().spelledForExpanded(T).hasValue();
        Trees.insert(Trees.end(), {&T, L});
      }
    }

    void assignRole(ArrayRef<syntax::Token> Range, syntax::NodeRole Role) {
      assert(!Range.empty());
      auto It = Trees.lower_bound(Range.begin());
      assert(It != Trees.end() && "no node found");
      assert(It->first == Range.begin() && "no child with the specified range");
      assert((std::next(It) == Trees.end() ||
              std::next(It)->first == Range.end()) &&
             "no child with the specified range");
      assert(It->second->getRole() == NodeRole::Detached &&
             "re-assigning role for a child");
      It->second->setRole(Role);
    }

    /// Shrink \p Range to a subrange that only contains tokens of a list.
    /// List elements and delimiters should already have correct roles.
    ArrayRef<syntax::Token> shrinkToFitList(ArrayRef<syntax::Token> Range) {
      auto BeginChildren = Trees.lower_bound(Range.begin());
      assert((BeginChildren == Trees.end() ||
              BeginChildren->first == Range.begin()) &&
             "Range crosses boundaries of existing subtrees");

      auto EndChildren = Trees.lower_bound(Range.end());
      assert(
          (EndChildren == Trees.end() || EndChildren->first == Range.end()) &&
          "Range crosses boundaries of existing subtrees");

      auto BelongsToList = [](decltype(Trees)::value_type KV) {
        auto Role = KV.second->getRole();
        return Role == syntax::NodeRole::ListElement ||
               Role == syntax::NodeRole::ListDelimiter;
      };

      auto BeginListChildren =
          std::find_if(BeginChildren, EndChildren, BelongsToList);

      auto EndListChildren =
          std::find_if_not(BeginListChildren, EndChildren, BelongsToList);

      return ArrayRef<syntax::Token>(BeginListChildren->first,
                                     EndListChildren->first);
    }

    /// Add \p Node to the forest and attach child nodes based on \p Tokens.
    void foldChildren(const syntax::Arena &A, ArrayRef<syntax::Token> Tokens,
                      syntax::Tree *Node) {
      // Attach children to `Node`.
      assert(Node->getFirstChild() == nullptr && "node already has children");

      auto *FirstToken = Tokens.begin();
      auto BeginChildren = Trees.lower_bound(FirstToken);

      assert((BeginChildren == Trees.end() ||
              BeginChildren->first == FirstToken) &&
             "fold crosses boundaries of existing subtrees");
      auto EndChildren = Trees.lower_bound(Tokens.end());
      assert(
          (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) &&
          "fold crosses boundaries of existing subtrees");

      for (auto It = BeginChildren; It != EndChildren; ++It) {
        auto *C = It->second;
        if (C->getRole() == NodeRole::Detached)
          C->setRole(NodeRole::Unknown);
        Node->appendChildLowLevel(C);
      }

      // Mark that this node came from the AST and is backed by the source code.
      Node->Original = true;
      Node->CanModify =
          A.getTokenBuffer().spelledForExpanded(Tokens).hasValue();

      Trees.erase(BeginChildren, EndChildren);
      Trees.insert({FirstToken, Node});
    }

    // EXPECTS: all tokens were consumed and are owned by a single root node.
    syntax::Node *finalize() && {
      assert(Trees.size() == 1);
      auto *Root = Trees.begin()->second;
      Trees = {};
      return Root;
    }

    std::string str(const syntax::Arena &A) const {
      std::string R;
      for (auto It = Trees.begin(); It != Trees.end(); ++It) {
        unsigned CoveredTokens =
            It != Trees.end()
                ? (std::next(It)->first - It->first)
                : A.getTokenBuffer().expandedTokens().end() - It->first;

        R += std::string(
            formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(),
                    It->first->text(A.getSourceManager()), CoveredTokens));
        R += It->second->dump(A.getSourceManager());
      }
      return R;
    }

  private:
    /// Maps from the start token to a subtree starting at that token.
    /// Keys in the map are pointers into the array of expanded tokens, so
    /// pointer order corresponds to the order of preprocessor tokens.
    std::map<const syntax::Token *, syntax::Node *> Trees;
  };

  /// For debugging purposes.
  std::string str() { return Pending.str(Arena); }

  syntax::Arena &Arena;
  /// To quickly find tokens by their start location.
  llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken;
  Forest Pending;
  llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
  ASTToSyntaxMapping Mapping;
};

namespace {
class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
public:
  explicit BuildTreeVisitor(ASTContext &Context, syntax::TreeBuilder &Builder)
      : Builder(Builder), Context(Context) {}

  bool shouldTraversePostOrder() const { return true; }

  bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) {
    return processDeclaratorAndDeclaration(DD);
  }

  bool WalkUpFromTypedefNameDecl(TypedefNameDecl *TD) {
    return processDeclaratorAndDeclaration(TD);
  }

  bool VisitDecl(Decl *D) {
    assert(!D->isImplicit());
    Builder.foldNode(Builder.getDeclarationRange(D),
                     new (allocator()) syntax::UnknownDeclaration(), D);
    return true;
  }

  // RAV does not call WalkUpFrom* on explicit instantiations, so we have to
  // override Traverse.
  // FIXME: make RAV call WalkUpFrom* instead.
  bool
  TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) {
    if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))
      return false;
    if (C->isExplicitSpecialization())
      return true; // we are only interested in explicit instantiations.
    auto *Declaration =
        cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C));
    foldExplicitTemplateInstantiation(
        Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()),
        Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
    return true;
  }

  bool WalkUpFromTemplateDecl(TemplateDecl *S) {
    foldTemplateDeclaration(
        Builder.getDeclarationRange(S),
        Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),
        Builder.getDeclarationRange(S->getTemplatedDecl()), S);
    return true;
  }

  bool WalkUpFromTagDecl(TagDecl *C) {
    // FIXME: build the ClassSpecifier node.
    if (!C->isFreeStanding()) {
      assert(C->getNumTemplateParameterLists() == 0);
      return true;
    }
    handleFreeStandingTagDecl(C);
    return true;
  }

  syntax::Declaration *handleFreeStandingTagDecl(TagDecl *C) {
    assert(C->isFreeStanding());
    // Class is a declaration specifier and needs a spanning declaration node.
    auto DeclarationRange = Builder.getDeclarationRange(C);
    syntax::Declaration *Result = new (allocator()) syntax::SimpleDeclaration;
    Builder.foldNode(DeclarationRange, Result, nullptr);

    // Build TemplateDeclaration nodes if we had template parameters.
    auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) {
      const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
      auto R = llvm::makeArrayRef(TemplateKW, DeclarationRange.end());
      Result =
          foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);
      DeclarationRange = R;
    };
    if (auto *S = dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
      ConsumeTemplateParameters(*S->getTemplateParameters());
    for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
      ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
    return Result;
  }

  bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) {
    // We do not want to call VisitDecl(), the declaration for translation
    // unit is built by finalize().
    return true;
  }

  bool WalkUpFromCompoundStmt(CompoundStmt *S) {
    using NodeRole = syntax::NodeRole;

    Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen);
    for (auto *Child : S->body())
      Builder.markStmtChild(Child, NodeRole::Statement);
    Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);

    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::CompoundStatement, S);
    return true;
  }

  // Some statements are not yet handled by syntax trees.
  bool WalkUpFromStmt(Stmt *S) {
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::UnknownStatement, S);
    return true;
  }

  bool TraverseIfStmt(IfStmt *S) {
    bool Result = [&, this]() {
      if (S->getInit() && !TraverseStmt(S->getInit())) {
        return false;
      }
      // In cases where the condition is an initialized declaration in a
      // statement, we want to preserve the declaration and ignore the
      // implicit condition expression in the syntax tree.
      if (S->hasVarStorage()) {
        if (!TraverseStmt(S->getConditionVariableDeclStmt()))
          return false;
      } else if (S->getCond() && !TraverseStmt(S->getCond()))
        return false;

      if (S->getThen() && !TraverseStmt(S->getThen()))
        return false;
      if (S->getElse() && !TraverseStmt(S->getElse()))
        return false;
      return true;
    }();
    WalkUpFromIfStmt(S);
    return Result;
  }

  bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) {
    // We override to traverse range initializer as VarDecl.
    // RAV traverses it as a statement, we produce invalid node kinds in that
    // case.
    // FIXME: should do this in RAV instead?
    bool Result = [&, this]() {
      if (S->getInit() && !TraverseStmt(S->getInit()))
        return false;
      if (S->getLoopVariable() && !TraverseDecl(S->getLoopVariable()))
        return false;
      if (S->getRangeInit() && !TraverseStmt(S->getRangeInit()))
        return false;
      if (S->getBody() && !TraverseStmt(S->getBody()))
        return false;
      return true;
    }();
    WalkUpFromCXXForRangeStmt(S);
    return Result;
  }

  bool TraverseStmt(Stmt *S) {
    if (auto *DS = dyn_cast_or_null<DeclStmt>(S)) {
      // We want to consume the semicolon, make sure SimpleDeclaration does not.
      for (auto *D : DS->decls())
        Builder.noticeDeclWithoutSemicolon(D);
    } else if (auto *E = dyn_cast_or_null<Expr>(S)) {
      return RecursiveASTVisitor::TraverseStmt(IgnoreImplicit(E));
    }
    return RecursiveASTVisitor::TraverseStmt(S);
  }

  bool TraverseOpaqueValueExpr(OpaqueValueExpr *VE) {
    // OpaqueValue doesn't correspond to concrete syntax, ignore it.
    return true;
  }

  // Some expressions are not yet handled by syntax trees.
  bool WalkUpFromExpr(Expr *E) {
    assert(!isImplicitExpr(E) && "should be handled by TraverseStmt");
    Builder.foldNode(Builder.getExprRange(E),
                     new (allocator()) syntax::UnknownExpression, E);
    return true;
  }

  bool TraverseUserDefinedLiteral(UserDefinedLiteral *S) {
    // The semantic AST node `UserDefinedLiteral` (UDL) may have one child node
    // referencing the location of the UDL suffix (`_w` in `1.2_w`). The
    // UDL suffix location does not point to the beginning of a token, so we
    // can't represent the UDL suffix as a separate syntax tree node.

    return WalkUpFromUserDefinedLiteral(S);
  }

  syntax::UserDefinedLiteralExpression *
  buildUserDefinedLiteral(UserDefinedLiteral *S) {
    switch (S->getLiteralOperatorKind()) {
    case UserDefinedLiteral::LOK_Integer:
      return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
    case UserDefinedLiteral::LOK_Floating:
      return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
    case UserDefinedLiteral::LOK_Character:
      return new (allocator()) syntax::CharUserDefinedLiteralExpression;
    case UserDefinedLiteral::LOK_String:
      return new (allocator()) syntax::StringUserDefinedLiteralExpression;
    case UserDefinedLiteral::LOK_Raw:
    case UserDefinedLiteral::LOK_Template:
      // For raw literal operator and numeric literal operator template we
      // cannot get the type of the operand in the semantic AST. We get this
      // information from the token. As integer and floating point have the same
      // token kind, we run `NumericLiteralParser` again to distinguish them.
      auto TokLoc = S->getBeginLoc();
      auto TokSpelling =
          Builder.findToken(TokLoc)->text(Context.getSourceManager());
      auto Literal =
          NumericLiteralParser(TokSpelling, TokLoc, Context.getSourceManager(),
                               Context.getLangOpts(), Context.getTargetInfo(),
                               Context.getDiagnostics());
      if (Literal.isIntegerLiteral())
        return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
      else {
        assert(Literal.isFloatingLiteral());
        return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
      }
    }
    llvm_unreachable("Unknown literal operator kind.");
  }

  bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) {
    Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S), buildUserDefinedLiteral(S), S);
    return true;
  }

  // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the
  // `DependentTemplateSpecializationType` case.
  /// Given a nested-name-specifier return the range for the last name
  /// specifier.
  ///
  /// e.g. `std::T::template X<U>::` => `template X<U>::`
  SourceRange getLocalSourceRange(const NestedNameSpecifierLoc &NNSLoc) {
    auto SR = NNSLoc.getLocalSourceRange();

    // The method `NestedNameSpecifierLoc::getLocalSourceRange` *should*
    // return the desired `SourceRange`, but there is a corner case. For a
    // `DependentTemplateSpecializationType` this method returns its
    // qualifiers as well, in other words in the example above this method
    // returns `T::template X<U>::` instead of only `template X<U>::`
    if (auto TL = NNSLoc.getTypeLoc()) {
      if (auto DependentTL =
              TL.getAs<DependentTemplateSpecializationTypeLoc>()) {
        // The 'template' keyword is always present in dependent template
        // specializations. Except in the case of incorrect code
        // TODO: Treat the case of incorrect code.
        SR.setBegin(DependentTL.getTemplateKeywordLoc());
      }
    }

    return SR;
  }

  syntax::NodeKind getNameSpecifierKind(const NestedNameSpecifier &NNS) {
    switch (NNS.getKind()) {
    case NestedNameSpecifier::Global:
      return syntax::NodeKind::GlobalNameSpecifier;
    case NestedNameSpecifier::Namespace:
    case NestedNameSpecifier::NamespaceAlias:
    case NestedNameSpecifier::Identifier:
      return syntax::NodeKind::IdentifierNameSpecifier;
    case NestedNameSpecifier::TypeSpecWithTemplate:
      return syntax::NodeKind::SimpleTemplateNameSpecifier;
    case NestedNameSpecifier::TypeSpec: {
      const auto *NNSType = NNS.getAsType();
      assert(NNSType);
      if (isa<DecltypeType>(NNSType))
        return syntax::NodeKind::DecltypeNameSpecifier;
      if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(
              NNSType))
        return syntax::NodeKind::SimpleTemplateNameSpecifier;
      return syntax::NodeKind::IdentifierNameSpecifier;
    }
    default:
      // FIXME: Support Microsoft's __super
      llvm::report_fatal_error("We don't yet support the __super specifier",
                               true);
    }
  }

  syntax::NameSpecifier *
  buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) {
    assert(NNSLoc.hasQualifier());
    auto NameSpecifierTokens =
        Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back();
    switch (getNameSpecifierKind(*NNSLoc.getNestedNameSpecifier())) {
    case syntax::NodeKind::GlobalNameSpecifier:
      return new (allocator()) syntax::GlobalNameSpecifier;
    case syntax::NodeKind::IdentifierNameSpecifier: {
      assert(NameSpecifierTokens.size() == 1);
      Builder.markChildToken(NameSpecifierTokens.begin(),
                             syntax::NodeRole::Unknown);
      auto *NS = new (allocator()) syntax::IdentifierNameSpecifier;
      Builder.foldNode(NameSpecifierTokens, NS, nullptr);
      return NS;
    }
    case syntax::NodeKind::SimpleTemplateNameSpecifier: {
      // TODO: Build `SimpleTemplateNameSpecifier` children and implement
      // accessors to them.
      // Be aware, we cannot do that simply by calling `TraverseTypeLoc`,
      // some `TypeLoc`s have inside them the previous name specifier and
      // we want to treat them independently.
      auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier;
      Builder.foldNode(NameSpecifierTokens, NS, nullptr);
      return NS;
    }
    case syntax::NodeKind::DecltypeNameSpecifier: {
      const auto TL = NNSLoc.getTypeLoc().castAs<DecltypeTypeLoc>();
      if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL))
        return nullptr;
      auto *NS = new (allocator()) syntax::DecltypeNameSpecifier;
      // TODO: Implement accessor to `DecltypeNameSpecifier` inner
      // `DecltypeTypeLoc`.
      // For that add mapping from `TypeLoc` to `syntax::Node*` then:
      // Builder.markChild(TypeLoc, syntax::NodeRole);
      Builder.foldNode(NameSpecifierTokens, NS, nullptr);
      return NS;
    }
    default:
      llvm_unreachable("getChildKind() does not return this value");
    }
  }

  // To build syntax tree nodes for NestedNameSpecifierLoc we override
  // Traverse instead of WalkUpFrom because we want to traverse the children
  // ourselves and build a list instead of a nested tree of name specifier
  // prefixes.
  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) {
    if (!QualifierLoc)
      return true;
    for (auto It = QualifierLoc; It; It = It.getPrefix()) {
      auto *NS = buildNameSpecifier(It);
      if (!NS)
        return false;
      Builder.markChild(NS, syntax::NodeRole::ListElement);
      Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter);
    }
    Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()),
                     new (allocator()) syntax::NestedNameSpecifier,
                     QualifierLoc);
    return true;
  }

  syntax::IdExpression *buildIdExpression(NestedNameSpecifierLoc QualifierLoc,
                                          SourceLocation TemplateKeywordLoc,
                                          SourceRange UnqualifiedIdLoc,
                                          ASTPtr From) {
    if (QualifierLoc) {
      Builder.markChild(QualifierLoc, syntax::NodeRole::Qualifier);
      if (TemplateKeywordLoc.isValid())
        Builder.markChildToken(TemplateKeywordLoc,
                               syntax::NodeRole::TemplateKeyword);
    }

    auto *TheUnqualifiedId = new (allocator()) syntax::UnqualifiedId;
    Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId,
                     nullptr);
    Builder.markChild(TheUnqualifiedId, syntax::NodeRole::UnqualifiedId);

    auto IdExpressionBeginLoc =
        QualifierLoc ? QualifierLoc.getBeginLoc() : UnqualifiedIdLoc.getBegin();

    auto *TheIdExpression = new (allocator()) syntax::IdExpression;
    Builder.foldNode(
        Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.getEnd()),
        TheIdExpression, From);

    return TheIdExpression;
  }

  bool WalkUpFromMemberExpr(MemberExpr *S) {
    // For `MemberExpr` with implicit `this->` we generate a simple
    // `id-expression` syntax node, beacuse an implicit `member-expression` is
    // syntactically undistinguishable from an `id-expression`
    if (S->isImplicitAccess()) {
      buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
                        SourceRange(S->getMemberLoc(), S->getEndLoc()), S);
      return true;
    }

    auto *TheIdExpression = buildIdExpression(
        S->getQualifierLoc(), S->getTemplateKeywordLoc(),
        SourceRange(S->getMemberLoc(), S->getEndLoc()), nullptr);

    Builder.markChild(TheIdExpression, syntax::NodeRole::Member);

    Builder.markExprChild(S->getBase(), syntax::NodeRole::Object);
    Builder.markChildToken(S->getOperatorLoc(), syntax::NodeRole::AccessToken);

    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::MemberExpression, S);
    return true;
  }

  bool WalkUpFromDeclRefExpr(DeclRefExpr *S) {
    buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
                      SourceRange(S->getLocation(), S->getEndLoc()), S);

    return true;
  }

  // Same logic as DeclRefExpr.
  bool WalkUpFromDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
    buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
                      SourceRange(S->getLocation(), S->getEndLoc()), S);

    return true;
  }

  bool WalkUpFromCXXThisExpr(CXXThisExpr *S) {
    if (!S->isImplicit()) {
      Builder.markChildToken(S->getLocation(),
                             syntax::NodeRole::IntroducerKeyword);
      Builder.foldNode(Builder.getExprRange(S),
                       new (allocator()) syntax::ThisExpression, S);
    }
    return true;
  }

  bool WalkUpFromParenExpr(ParenExpr *S) {
    Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen);
    Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::SubExpression);
    Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::ParenExpression, S);
    return true;
  }

  bool WalkUpFromIntegerLiteral(IntegerLiteral *S) {
    Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::IntegerLiteralExpression, S);
    return true;
  }

  bool WalkUpFromCharacterLiteral(CharacterLiteral *S) {
    Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::CharacterLiteralExpression, S);
    return true;
  }

  bool WalkUpFromFloatingLiteral(FloatingLiteral *S) {
    Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::FloatingLiteralExpression, S);
    return true;
  }

  bool WalkUpFromStringLiteral(StringLiteral *S) {
    Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::StringLiteralExpression, S);
    return true;
  }

  bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) {
    Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::BoolLiteralExpression, S);
    return true;
  }

  bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) {
    Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::CxxNullPtrExpression, S);
    return true;
  }

  bool WalkUpFromUnaryOperator(UnaryOperator *S) {
    Builder.markChildToken(S->getOperatorLoc(),
                           syntax::NodeRole::OperatorToken);
    Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::Operand);

    if (S->isPostfix())
      Builder.foldNode(Builder.getExprRange(S),
                       new (allocator()) syntax::PostfixUnaryOperatorExpression,
                       S);
    else
      Builder.foldNode(Builder.getExprRange(S),
                       new (allocator()) syntax::PrefixUnaryOperatorExpression,
                       S);

    return true;
  }

  bool WalkUpFromBinaryOperator(BinaryOperator *S) {
    Builder.markExprChild(S->getLHS(), syntax::NodeRole::LeftHandSide);
    Builder.markChildToken(S->getOperatorLoc(),
                           syntax::NodeRole::OperatorToken);
    Builder.markExprChild(S->getRHS(), syntax::NodeRole::RightHandSide);
    Builder.foldNode(Builder.getExprRange(S),
                     new (allocator()) syntax::BinaryOperatorExpression, S);
    return true;
  }

  /// Builds `CallArguments` syntax node from arguments that appear in source
  /// code, i.e. not default arguments.
  syntax::CallArguments *
  buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs) {
    auto Args = dropDefaultArgs(ArgsAndDefaultArgs);
    for (auto *Arg : Args) {
      Builder.markExprChild(Arg, syntax::NodeRole::ListElement);
      const auto *DelimiterToken =
          std::next(Builder.findToken(Arg->getEndLoc()));
      if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
        Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
    }

    auto *Arguments = new (allocator()) syntax::CallArguments;
    if (!Args.empty())
      Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(),
                                        (*(Args.end() - 1))->getEndLoc()),
                       Arguments, nullptr);

    return Arguments;
  }

  bool WalkUpFromCallExpr(CallExpr *S) {
    Builder.markExprChild(S->getCallee(), syntax::NodeRole::Callee);

    const auto *LParenToken =
        std::next(Builder.findToken(S->getCallee()->getEndLoc()));
    // FIXME: Assert that `LParenToken` is indeed a `l_paren` once we have fixed
    // the test on decltype desctructors.
    if (LParenToken->kind() == clang::tok::l_paren)
      Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);

    Builder.markChild(buildCallArguments(S->arguments()),
                      syntax::NodeRole::Arguments);

    Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);

    Builder.foldNode(Builder.getRange(S->getSourceRange()),
                     new (allocator()) syntax::CallExpression, S);
    return true;
  }

  bool WalkUpFromCXXConstructExpr(CXXConstructExpr *S) {
    // Ignore the implicit calls to default constructors.
    if ((S->getNumArgs() == 0 || isa<CXXDefaultArgExpr>(S->getArg(0))) &&
        S->getParenOrBraceRange().isInvalid())
      return true;
    return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S);
  }

  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
    // To construct a syntax tree of the same shape for calls to built-in and
    // user-defined operators, ignore the `DeclRefExpr` that refers to the
    // operator and treat it as a simple token. Do that by traversing
    // arguments instead of children.
    for (auto *child : S->arguments()) {
      // A postfix unary operator is declared as taking two operands. The
      // second operand is used to distinguish from its prefix counterpart. In
      // the semantic AST this "phantom" operand is represented as a
      // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this
      // operand because it does not correspond to anything written in source
      // code.
      if (child->getSourceRange().isInvalid()) {
        assert(getOperatorNodeKind(*S) ==
               syntax::NodeKind::PostfixUnaryOperatorExpression);
        continue;
      }
      if (!TraverseStmt(child))
        return false;
    }
    return WalkUpFromCXXOperatorCallExpr(S);
  }

  bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
    switch (getOperatorNodeKind(*S)) {
    case syntax::NodeKind::BinaryOperatorExpression:
      Builder.markExprChild(S->getArg(0), syntax::NodeRole::LeftHandSide);
      Builder.markChildToken(S->getOperatorLoc(),
                             syntax::NodeRole::OperatorToken);
      Builder.markExprChild(S->getArg(1), syntax::NodeRole::RightHandSide);
      Builder.foldNode(Builder.getExprRange(S),
                       new (allocator()) syntax::BinaryOperatorExpression, S);
      return true;
    case syntax::NodeKind::PrefixUnaryOperatorExpression:
      Builder.markChildToken(S->getOperatorLoc(),
                             syntax::NodeRole::OperatorToken);
      Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);
      Builder.foldNode(Builder.getExprRange(S),
                       new (allocator()) syntax::PrefixUnaryOperatorExpression,
                       S);
      return true;
    case syntax::NodeKind::PostfixUnaryOperatorExpression:
      Builder.markChildToken(S->getOperatorLoc(),
                             syntax::NodeRole::OperatorToken);
      Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);
      Builder.foldNode(Builder.getExprRange(S),
                       new (allocator()) syntax::PostfixUnaryOperatorExpression,
                       S);
      return true;
    case syntax::NodeKind::CallExpression: {
      Builder.markExprChild(S->getArg(0), syntax::NodeRole::Callee);

      const auto *LParenToken =
          std::next(Builder.findToken(S->getArg(0)->getEndLoc()));
      // FIXME: Assert that `LParenToken` is indeed a `l_paren` once we have
      // fixed the test on decltype desctructors.
      if (LParenToken->kind() == clang::tok::l_paren)
        Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);

      Builder.markChild(buildCallArguments(CallExpr::arg_range(
                            S->arg_begin() + 1, S->arg_end())),
                        syntax::NodeRole::Arguments);

      Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);

      Builder.foldNode(Builder.getRange(S->getSourceRange()),
                       new (allocator()) syntax::CallExpression, S);
      return true;
    }
    case syntax::NodeKind::UnknownExpression:
      return WalkUpFromExpr(S);
    default:
      llvm_unreachable("getOperatorNodeKind() does not return this value");
    }
  }

  bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; }

  bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {
    auto Tokens = Builder.getDeclarationRange(S);
    if (Tokens.front().kind() == tok::coloncolon) {
      // Handle nested namespace definitions. Those start at '::' token, e.g.
      // namespace a^::b {}
      // FIXME: build corresponding nodes for the name of this namespace.
      return true;
    }
    Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition, S);
    return true;
  }

  // FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test
  // results. Find test coverage or remove it.
  bool TraverseParenTypeLoc(ParenTypeLoc L) {
    // We reverse order of traversal to get the proper syntax structure.
    if (!WalkUpFromParenTypeLoc(L))
      return false;
    return TraverseTypeLoc(L.getInnerLoc());
  }

  bool WalkUpFromParenTypeLoc(ParenTypeLoc L) {
    Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
    Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
    Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getRParenLoc()),
                     new (allocator()) syntax::ParenDeclarator, L);
    return true;
  }

  // Declarator chunks, they are produced by type locs and some clang::Decls.
  bool WalkUpFromArrayTypeLoc(ArrayTypeLoc L) {
    Builder.markChildToken(L.getLBracketLoc(), syntax::NodeRole::OpenParen);
    Builder.markExprChild(L.getSizeExpr(), syntax::NodeRole::Size);
    Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen);
    Builder.foldNode(Builder.getRange(L.getLBracketLoc(), L.getRBracketLoc()),
                     new (allocator()) syntax::ArraySubscript, L);
    return true;
  }

  syntax::ParameterDeclarationList *
  buildParameterDeclarationList(ArrayRef<ParmVarDecl *> Params) {
    for (auto *P : Params) {
      Builder.markChild(P, syntax::NodeRole::ListElement);
      const auto *DelimiterToken = std::next(Builder.findToken(P->getEndLoc()));
      if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
        Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
    }
    auto *Parameters = new (allocator()) syntax::ParameterDeclarationList;
    if (!Params.empty())
      Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(),
                                        Params.back()->getEndLoc()),
                       Parameters, nullptr);
    return Parameters;
  }

  bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L) {
    Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);

    Builder.markChild(buildParameterDeclarationList(L.getParams()),
                      syntax::NodeRole::Parameters);

    Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
    Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()),
                     new (allocator()) syntax::ParametersAndQualifiers, L);
    return true;
  }

  bool WalkUpFromFunctionProtoTypeLoc(FunctionProtoTypeLoc L) {
    if (!L.getTypePtr()->hasTrailingReturn())
      return WalkUpFromFunctionTypeLoc(L);

    auto *TrailingReturnTokens = buildTrailingReturn(L);
    // Finish building the node for parameters.
    Builder.markChild(TrailingReturnTokens, syntax::NodeRole::TrailingReturn);
    return WalkUpFromFunctionTypeLoc(L);
  }

  bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) {
    // In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds
    // to "Y::*" but it points to a `ParenTypeLoc` that corresponds to
    // "(Y::*mp)" We thus reverse the order of traversal to get the proper
    // syntax structure.
    if (!WalkUpFromMemberPointerTypeLoc(L))
      return false;
    return TraverseTypeLoc(L.getPointeeLoc());
  }

  bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) {
    auto SR = L.getLocalSourceRange();
    Builder.foldNode(Builder.getRange(SR),
                     new (allocator()) syntax::MemberPointer, L);
    return true;
  }

  // The code below is very regular, it could even be generated with some
  // preprocessor magic. We merely assign roles to the corresponding children
  // and fold resulting nodes.
  bool WalkUpFromDeclStmt(DeclStmt *S) {
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::DeclarationStatement, S);
    return true;
  }

  bool WalkUpFromNullStmt(NullStmt *S) {
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::EmptyStatement, S);
    return true;
  }

  bool WalkUpFromSwitchStmt(SwitchStmt *S) {
    Builder.markChildToken(S->getSwitchLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::SwitchStatement, S);
    return true;
  }

  bool WalkUpFromCaseStmt(CaseStmt *S) {
    Builder.markChildToken(S->getKeywordLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseValue);
    Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::CaseStatement, S);
    return true;
  }

  bool WalkUpFromDefaultStmt(DefaultStmt *S) {
    Builder.markChildToken(S->getKeywordLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::DefaultStatement, S);
    return true;
  }

  bool WalkUpFromIfStmt(IfStmt *S) {
    Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword);
    Stmt *ConditionStatement = S->getCond();
    if (S->hasVarStorage())
      ConditionStatement = S->getConditionVariableDeclStmt();
    Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition);
    Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement);
    Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword);
    Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::IfStatement, S);
    return true;
  }

  bool WalkUpFromForStmt(ForStmt *S) {
    Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
    Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::ForStatement, S);
    return true;
  }

  bool WalkUpFromWhileStmt(WhileStmt *S) {
    Builder.markChildToken(S->getWhileLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::WhileStatement, S);
    return true;
  }

  bool WalkUpFromContinueStmt(ContinueStmt *S) {
    Builder.markChildToken(S->getContinueLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::ContinueStatement, S);
    return true;
  }

  bool WalkUpFromBreakStmt(BreakStmt *S) {
    Builder.markChildToken(S->getBreakLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::BreakStatement, S);
    return true;
  }

  bool WalkUpFromReturnStmt(ReturnStmt *S) {
    Builder.markChildToken(S->getReturnLoc(),
                           syntax::NodeRole::IntroducerKeyword);
    Builder.markExprChild(S->getRetValue(), syntax::NodeRole::ReturnValue);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::ReturnStatement, S);
    return true;
  }

  bool WalkUpFromCXXForRangeStmt(CXXForRangeStmt *S) {
    Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
    Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
    Builder.foldNode(Builder.getStmtRange(S),
                     new (allocator()) syntax::RangeBasedForStatement, S);
    return true;
  }

  bool WalkUpFromEmptyDecl(EmptyDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::EmptyDeclaration, S);
    return true;
  }

  bool WalkUpFromStaticAssertDecl(StaticAssertDecl *S) {
    Builder.markExprChild(S->getAssertExpr(), syntax::NodeRole::Condition);
    Builder.markExprChild(S->getMessage(), syntax::NodeRole::Message);
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::StaticAssertDeclaration, S);
    return true;
  }

  bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::LinkageSpecificationDeclaration,
                     S);
    return true;
  }

  bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::NamespaceAliasDefinition, S);
    return true;
  }

  bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::UsingNamespaceDirective, S);
    return true;
  }

  bool WalkUpFromUsingDecl(UsingDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::UsingDeclaration, S);
    return true;
  }

  bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::UsingDeclaration, S);
    return true;
  }

  bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::UsingDeclaration, S);
    return true;
  }

  bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) {
    Builder.foldNode(Builder.getDeclarationRange(S),
                     new (allocator()) syntax::TypeAliasDeclaration, S);
    return true;
  }

private:
  /// Folds SimpleDeclarator node (if present) and in case this is the last
  /// declarator in the chain it also folds SimpleDeclaration node.
  template <class T> bool processDeclaratorAndDeclaration(T *D) {
    auto Range = getDeclaratorRange(
        Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(),
        getQualifiedNameStart(D), getInitializerRange(D));

    // There doesn't have to be a declarator (e.g. `void foo(int)` only has
    // declaration, but no declarator).
    if (!Range.getBegin().isValid()) {
      Builder.markChild(new (allocator()) syntax::DeclaratorList,
                        syntax::NodeRole::Declarators);
      Builder.foldNode(Builder.getDeclarationRange(D),
                       new (allocator()) syntax::SimpleDeclaration, D);
      return true;
    }

    auto *N = new (allocator()) syntax::SimpleDeclarator;
    Builder.foldNode(Builder.getRange(Range), N, nullptr);
    Builder.markChild(N, syntax::NodeRole::ListElement);

    if (!Builder.isResponsibleForCreatingDeclaration(D)) {
      // If this is not the last declarator in the declaration we expect a
      // delimiter after it.
      const auto *DelimiterToken = std::next(Builder.findToken(Range.getEnd()));
      if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
        Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
    } else {
      auto *DL = new (allocator()) syntax::DeclaratorList;
      auto DeclarationRange = Builder.getDeclarationRange(D);
      Builder.foldList(DeclarationRange, DL, nullptr);

      Builder.markChild(DL, syntax::NodeRole::Declarators);
      Builder.foldNode(DeclarationRange,
                       new (allocator()) syntax::SimpleDeclaration, D);
    }
    return true;
  }

  /// Returns the range of the built node.
  syntax::TrailingReturnType *buildTrailingReturn(FunctionProtoTypeLoc L) {
    assert(L.getTypePtr()->hasTrailingReturn());

    auto ReturnedType = L.getReturnLoc();
    // Build node for the declarator, if any.
    auto ReturnDeclaratorRange = SourceRange(GetStartLoc().Visit(ReturnedType),
                                             ReturnedType.getEndLoc());
    syntax::SimpleDeclarator *ReturnDeclarator = nullptr;
    if (ReturnDeclaratorRange.isValid()) {
      ReturnDeclarator = new (allocator()) syntax::SimpleDeclarator;
      Builder.foldNode(Builder.getRange(ReturnDeclaratorRange),
                       ReturnDeclarator, nullptr);
    }

    // Build node for trailing return type.
    auto Return = Builder.getRange(ReturnedType.getSourceRange());
    const auto *Arrow = Return.begin() - 1;
    assert(Arrow->kind() == tok::arrow);
    auto Tokens = llvm::makeArrayRef(Arrow, Return.end());
    Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken);
    if (ReturnDeclarator)
      Builder.markChild(ReturnDeclarator, syntax::NodeRole::Declarator);
    auto *R = new (allocator()) syntax::TrailingReturnType;
    Builder.foldNode(Tokens, R, L);
    return R;
  }

  void foldExplicitTemplateInstantiation(
      ArrayRef<syntax::Token> Range, const syntax::Token *ExternKW,
      const syntax::Token *TemplateKW,
      syntax::SimpleDeclaration *InnerDeclaration, Decl *From) {
    assert(!ExternKW || ExternKW->kind() == tok::kw_extern);
    assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
    Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword);
    Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
    Builder.markChild(InnerDeclaration, syntax::NodeRole::Declaration);
    Builder.foldNode(
        Range, new (allocator()) syntax::ExplicitTemplateInstantiation, From);
  }

  syntax::TemplateDeclaration *foldTemplateDeclaration(
      ArrayRef<syntax::Token> Range, const syntax::Token *TemplateKW,
      ArrayRef<syntax::Token> TemplatedDeclaration, Decl *From) {
    assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
    Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);

    auto *N = new (allocator()) syntax::TemplateDeclaration;
    Builder.foldNode(Range, N, From);
    Builder.markChild(N, syntax::NodeRole::Declaration);
    return N;
  }

  /// A small helper to save some typing.
  llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); }

  syntax::TreeBuilder &Builder;
  const ASTContext &Context;
};
} // namespace

void syntax::TreeBuilder::noticeDeclWithoutSemicolon(Decl *D) {
  DeclsWithoutSemicolons.insert(D);
}

void syntax::TreeBuilder::markChildToken(SourceLocation Loc, NodeRole Role) {
  if (Loc.isInvalid())
    return;
  Pending.assignRole(*findToken(Loc), Role);
}

void syntax::TreeBuilder::markChildToken(const syntax::Token *T, NodeRole R) {
  if (!T)
    return;
  Pending.assignRole(*T, R);
}

void syntax::TreeBuilder::markChild(syntax::Node *N, NodeRole R) {
  assert(N);
  setRole(N, R);
}

void syntax::TreeBuilder::markChild(ASTPtr N, NodeRole R) {
  auto *SN = Mapping.find(N);
  assert(SN != nullptr);
  setRole(SN, R);
}
void syntax::TreeBuilder::markChild(NestedNameSpecifierLoc NNSLoc, NodeRole R) {
  auto *SN = Mapping.find(NNSLoc);
  assert(SN != nullptr);
  setRole(SN, R);
}

void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
  if (!Child)
    return;

  syntax::Tree *ChildNode;
  if (Expr *ChildExpr = dyn_cast<Expr>(Child)) {
    // This is an expression in a statement position, consume the trailing
    // semicolon and form an 'ExpressionStatement' node.
    markExprChild(ChildExpr, NodeRole::Expression);
    ChildNode = new (allocator()) syntax::ExpressionStatement;
    // (!) 'getStmtRange()' ensures this covers a trailing semicolon.
    Pending.foldChildren(Arena, getStmtRange(Child), ChildNode);
  } else {
    ChildNode = Mapping.find(Child);
  }
  assert(ChildNode != nullptr);
  setRole(ChildNode, Role);
}

void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
  if (!Child)
    return;
  Child = IgnoreImplicit(Child);

  syntax::Tree *ChildNode = Mapping.find(Child);
  assert(ChildNode != nullptr);
  setRole(ChildNode, Role);
}

const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
  if (L.isInvalid())
    return nullptr;
  auto It = LocationToToken.find(L);
  assert(It != LocationToToken.end());
  return It->second;
}

syntax::TranslationUnit *syntax::buildSyntaxTree(Arena &A,
                                                 ASTContext &Context) {
  TreeBuilder Builder(A);
  BuildTreeVisitor(Context, Builder).TraverseAST(Context);
  return std::move(Builder).finalize();
}
