//===-- HelperDeclRefGraph.cpp - AST-based call graph for helper decls ----===//
//
// 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 "HelperDeclRefGraph.h"
#include "Move.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/Debug.h"
#include <vector>

#define DEBUG_TYPE "clang-move"

namespace clang {
namespace move {

void HelperDeclRefGraph::print(raw_ostream &OS) const {
  OS << " --- Call graph Dump --- \n";
  for (auto I = DeclMap.begin(); I != DeclMap.end(); ++I) {
    const CallGraphNode *N = (I->second).get();

    OS << "  Declarations: ";
    N->print(OS);
    OS << " (" << N << ") ";
    OS << " calls: ";
    for (auto CI = N->begin(), CE = N->end(); CI != CE; ++CI) {
      CI->Callee->print(OS);
      OS << " (" << CI << ") ";
    }
    OS << '\n';
  }
  OS.flush();
}

void HelperDeclRefGraph::addEdge(const Decl *Caller, const Decl *Callee) {
  assert(Caller);
  assert(Callee);

  // Ignore the case where Caller equals Callee. This happens in the static
  // class member definitions in global namespace like "int CLASS::static_var =
  // 1;", its DC is a VarDel whose outmost enclosing declaration is the "CLASS"
  // CXXRecordDecl.
  if (Caller == Callee) return;

  // Allocate a new node, mark it as root, and process it's calls.
  CallGraphNode *CallerNode = getOrInsertNode(const_cast<Decl *>(Caller));
  CallGraphNode *CalleeNode = getOrInsertNode(const_cast<Decl *>(Callee));
  CallerNode->addCallee({CalleeNode, /*CallExpr=*/nullptr});
}

void HelperDeclRefGraph::dump() const { print(llvm::errs()); }

CallGraphNode *HelperDeclRefGraph::getOrInsertNode(Decl *F) {
  F = F->getCanonicalDecl();
  std::unique_ptr<CallGraphNode> &Node = DeclMap[F];
  if (Node)
    return Node.get();

  Node = std::make_unique<CallGraphNode>(F);
  return Node.get();
}

CallGraphNode *HelperDeclRefGraph::getNode(const Decl *D) const {
  auto I = DeclMap.find(D->getCanonicalDecl());
  return I == DeclMap.end() ? nullptr : I->second.get();
}

llvm::DenseSet<const CallGraphNode *>
HelperDeclRefGraph::getReachableNodes(const Decl *Root) const {
  const auto *RootNode = getNode(Root);
  if (!RootNode)
    return {};
  llvm::DenseSet<const CallGraphNode *> ConnectedNodes;
  std::function<void(const CallGraphNode *)> VisitNode =
      [&](const CallGraphNode *Node) {
        if (ConnectedNodes.count(Node))
          return;
        ConnectedNodes.insert(Node);
        for (auto It = Node->begin(), End = Node->end(); It != End; ++It)
          VisitNode(*It);
      };

  VisitNode(RootNode);
  return ConnectedNodes;
}

const Decl *HelperDeclRGBuilder::getOutmostClassOrFunDecl(const Decl *D) {
  const auto *DC = D->getDeclContext();
  const auto *Result = D;
  while (DC) {
    if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
      Result = RD;
    else if (const auto *FD = dyn_cast<FunctionDecl>(DC))
      Result = FD;
    DC = DC->getParent();
  }
  return Result;
}

void HelperDeclRGBuilder::run(
    const ast_matchers::MatchFinder::MatchResult &Result) {
  // Construct the graph by adding a directed edge from caller to callee.
  //
  // "dc" is the closest ancestor declaration of "func_ref" or "used_class", it
  // might be not the targetted Caller Decl, we always use the outmost enclosing
  // FunctionDecl/CXXRecordDecl of "dc". For example,
  //
  //   int MoveClass::F() { int a = helper(); return a; }
  //
  // The matched "dc" of "helper" DeclRefExpr is a VarDecl, we traverse up AST
  // to find the outmost "MoveClass" CXXRecordDecl and use it as Caller.
  if (const auto *FuncRef = Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
    const auto *DC = Result.Nodes.getNodeAs<Decl>("dc");
    assert(DC);
    LLVM_DEBUG(llvm::dbgs() << "Find helper function usage: "
                            << FuncRef->getDecl()->getDeclName() << " ("
                            << FuncRef->getDecl() << ")\n");
    RG->addEdge(
        getOutmostClassOrFunDecl(DC->getCanonicalDecl()),
        getOutmostClassOrFunDecl(FuncRef->getDecl()->getCanonicalDecl()));
  } else if (const auto *UsedClass =
                 Result.Nodes.getNodeAs<CXXRecordDecl>("used_class")) {
    const auto *DC = Result.Nodes.getNodeAs<Decl>("dc");
    assert(DC);
    LLVM_DEBUG(llvm::dbgs()
               << "Find helper class usage: " << UsedClass->getDeclName()
               << " (" << UsedClass << ")\n");
    RG->addEdge(getOutmostClassOrFunDecl(DC->getCanonicalDecl()), UsedClass);
  }
}

} // namespace move
} // namespace clang
