//===- 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;

  class ParentMap;

private:
  ASTContext &ASTCtx;
  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) DynTypedNode(N);
  }

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

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

  const DynTypedNode *end() const {
    if (!IsSingleNode)
      return reinterpret_cast<const ArrayRef<DynTypedNode> *>(&Storage)->end();
    return reinterpret_cast<const DynTypedNode *>(&Storage) + 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
