//===- ParentMapContext.h - Map of parents using DynTypedNode -------*- 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
//
//===----------------------------------------------------------------------===//
//
// Similar to ParentMap.h, but generalizes to non-Stmt nodes, which can have
// multiple parents.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_PARENTMAPCONTEXT_H
#define LLVM_CLANG_AST_PARENTMAPCONTEXT_H

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"

namespace clang {
class DynTypedNodeList;

class ParentMapContext {
public:
  ParentMapContext(ASTContext &Ctx);

  ~ParentMapContext();

  /// Returns the parents of the given node (within the traversal scope).
  ///
  /// Note that this will lazily compute the parents of all nodes
  /// and store them for later retrieval. Thus, the first call is O(n)
  /// in the number of AST nodes.
  ///
  /// Caveats and FIXMEs:
  /// Calculating the parent map over all AST nodes will need to load the
  /// full AST. This can be undesirable in the case where the full AST is
  /// expensive to create (for example, when using precompiled header
  /// preambles). Thus, there are good opportunities for optimization here.
  /// One idea is to walk the given node downwards, looking for references
  /// to declaration contexts - once a declaration context is found, compute
  /// the parent map for the declaration context; if that can satisfy the
  /// request, loading the whole AST can be avoided. Note that this is made
  /// more complex by statements in templates having multiple parents - those
  /// problems can be solved by building closure over the templated parts of
  /// the AST, which also avoids touching large parts of the AST.
  /// Additionally, we will want to add an interface to already give a hint
  /// where to search for the parents, for example when looking at a statement
  /// inside a certain function.
  ///
  /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
  /// NestedNameSpecifier or NestedNameSpecifierLoc.
  template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node);

  DynTypedNodeList getParents(const DynTypedNode &Node);

  /// Clear parent maps.
  void clear();

  TraversalKind getTraversalKind() const { return Traversal; }
  void setTraversalKind(TraversalKind TK) { Traversal = TK; }

  const Expr *traverseIgnored(const Expr *E) const;
  Expr *traverseIgnored(Expr *E) const;
  DynTypedNode traverseIgnored(const DynTypedNode &N) const;

private:
  ASTContext &ASTCtx;
  class ParentMap;
  TraversalKind Traversal = TK_AsIs;
  std::unique_ptr<ParentMap> Parents;
};

class TraversalKindScope {
  ParentMapContext &Ctx;
  TraversalKind TK = TK_AsIs;

public:
  TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK)
      : Ctx(ASTCtx.getParentMapContext()) {
    TK = Ctx.getTraversalKind();
    if (ScopeTK)
      Ctx.setTraversalKind(*ScopeTK);
  }

  ~TraversalKindScope() { Ctx.setTraversalKind(TK); }
};

/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
  llvm::AlignedCharArrayUnion<DynTypedNode, ArrayRef<DynTypedNode>> Storage;
  bool IsSingleNode;

public:
  DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
    new (Storage.buffer) DynTypedNode(N);
  }

  DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
    new (Storage.buffer) ArrayRef<DynTypedNode>(A);
  }

  const DynTypedNode *begin() const {
    if (!IsSingleNode)
      return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
          ->begin();
    return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
  }

  const DynTypedNode *end() const {
    if (!IsSingleNode)
      return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
          ->end();
    return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
  }

  size_t size() const { return end() - begin(); }
  bool empty() const { return begin() == end(); }

  const DynTypedNode &operator[](size_t N) const {
    assert(N < size() && "Out of bounds!");
    return *(begin() + N);
  }
};

template <typename NodeT>
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
  return getParents(DynTypedNode::create(Node));
}

template <typename NodeT>
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
  return getParentMapContext().getParents(Node);
}

template <>
inline DynTypedNodeList ASTContext::getParents(const DynTypedNode &Node) {
  return getParentMapContext().getParents(Node);
}

} // namespace clang

#endif
