//===--- AST.cpp - Utility AST functions  -----------------------*- 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 "AST.h"

#include "SourceCode.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <iterator>
#include <optional>
#include <string>
#include <vector>

namespace clang {
namespace clangd {

namespace {
std::optional<llvm::ArrayRef<TemplateArgumentLoc>>
getTemplateSpecializationArgLocs(const NamedDecl &ND) {
  if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) {
    if (const ASTTemplateArgumentListInfo *Args =
            Func->getTemplateSpecializationArgsAsWritten())
      return Args->arguments();
  } else if (auto *Cls =
                 llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
    if (auto *Args = Cls->getTemplateArgsAsWritten())
      return Args->arguments();
  } else if (auto *Var =
                 llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) {
    if (auto *Args = Var->getTemplateArgsAsWritten())
      return Args->arguments();
  } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) {
    if (auto *Args = Var->getTemplateArgsInfo())
      return Args->arguments();
  }
  // We return std::nullopt for ClassTemplateSpecializationDecls because it does
  // not contain TemplateArgumentLoc information.
  return std::nullopt;
}

template <class T>
bool isTemplateSpecializationKind(const NamedDecl *D,
                                  TemplateSpecializationKind Kind) {
  if (const auto *TD = dyn_cast<T>(D))
    return TD->getTemplateSpecializationKind() == Kind;
  return false;
}

bool isTemplateSpecializationKind(const NamedDecl *D,
                                  TemplateSpecializationKind Kind) {
  return isTemplateSpecializationKind<FunctionDecl>(D, Kind) ||
         isTemplateSpecializationKind<CXXRecordDecl>(D, Kind) ||
         isTemplateSpecializationKind<VarDecl>(D, Kind);
}

// Store all UsingDirectiveDecls in parent contexts of DestContext, that were
// introduced before InsertionPoint.
llvm::DenseSet<const NamespaceDecl *>
getUsingNamespaceDirectives(const DeclContext *DestContext,
                            SourceLocation Until) {
  const auto &SM = DestContext->getParentASTContext().getSourceManager();
  llvm::DenseSet<const NamespaceDecl *> VisibleNamespaceDecls;
  for (const auto *DC = DestContext; DC; DC = DC->getLookupParent()) {
    for (const auto *D : DC->decls()) {
      if (!SM.isWrittenInSameFile(D->getLocation(), Until) ||
          !SM.isBeforeInTranslationUnit(D->getLocation(), Until))
        continue;
      if (auto *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D))
        VisibleNamespaceDecls.insert(
            UDD->getNominatedNamespace()->getCanonicalDecl());
    }
  }
  return VisibleNamespaceDecls;
}

// Goes over all parents of SourceContext until we find a common ancestor for
// DestContext and SourceContext. Any qualifier including and above common
// ancestor is redundant, therefore we stop at lowest common ancestor.
// In addition to that stops early whenever IsVisible returns true. This can be
// used to implement support for "using namespace" decls.
std::string
getQualification(ASTContext &Context, const DeclContext *DestContext,
                 const DeclContext *SourceContext,
                 llvm::function_ref<bool(NestedNameSpecifier *)> IsVisible) {
  std::vector<const NestedNameSpecifier *> Parents;
  bool ReachedNS = false;
  for (const DeclContext *CurContext = SourceContext; CurContext;
       CurContext = CurContext->getLookupParent()) {
    // Stop once we reach a common ancestor.
    if (CurContext->Encloses(DestContext))
      break;

    NestedNameSpecifier *NNS = nullptr;
    if (auto *TD = llvm::dyn_cast<TagDecl>(CurContext)) {
      // There can't be any more tag parents after hitting a namespace.
      assert(!ReachedNS);
      (void)ReachedNS;
      NNS = NestedNameSpecifier::Create(Context, nullptr, false,
                                        TD->getTypeForDecl());
    } else if (auto *NSD = llvm::dyn_cast<NamespaceDecl>(CurContext)) {
      ReachedNS = true;
      NNS = NestedNameSpecifier::Create(Context, nullptr, NSD);
      // Anonymous and inline namespace names are not spelled while qualifying
      // a name, so skip those.
      if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace())
        continue;
    } else {
      // Other types of contexts cannot be spelled in code, just skip over
      // them.
      continue;
    }
    // Stop if this namespace is already visible at DestContext.
    if (IsVisible(NNS))
      break;

    Parents.push_back(NNS);
  }

  // Go over name-specifiers in reverse order to create necessary qualification,
  // since we stored inner-most parent first.
  std::string Result;
  llvm::raw_string_ostream OS(Result);
  for (const auto *Parent : llvm::reverse(Parents))
    Parent->print(OS, Context.getPrintingPolicy());
  return OS.str();
}

} // namespace

bool isImplicitTemplateInstantiation(const NamedDecl *D) {
  return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation);
}

bool isExplicitTemplateSpecialization(const NamedDecl *D) {
  return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization);
}

bool isImplementationDetail(const Decl *D) {
  return !isSpelledInSource(D->getLocation(),
                            D->getASTContext().getSourceManager());
}

SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM) {
  auto L = D.getLocation();
  // For `- (void)foo` we want `foo` not the `-`.
  if (const auto *MD = dyn_cast<ObjCMethodDecl>(&D))
    L = MD->getSelectorStartLoc();
  if (isSpelledInSource(L, SM))
    return SM.getSpellingLoc(L);
  return SM.getExpansionLoc(L);
}

std::string printQualifiedName(const NamedDecl &ND) {
  std::string QName;
  llvm::raw_string_ostream OS(QName);
  PrintingPolicy Policy(ND.getASTContext().getLangOpts());
  // Note that inline namespaces are treated as transparent scopes. This
  // reflects the way they're most commonly used for lookup. Ideally we'd
  // include them, but at query time it's hard to find all the inline
  // namespaces to query: the preamble doesn't have a dedicated list.
  Policy.SuppressUnwrittenScope = true;
  // (unnamed struct), not (unnamed struct at /path/to/foo.cc:42:1).
  // In clangd, context is usually available and paths are mostly noise.
  Policy.AnonymousTagLocations = false;
  ND.printQualifiedName(OS, Policy);
  OS.flush();
  assert(!StringRef(QName).starts_with("::"));
  return QName;
}

static bool isAnonymous(const DeclarationName &N) {
  return N.isIdentifier() && !N.getAsIdentifierInfo();
}

NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND) {
  if (auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND))
    return V->getQualifierLoc();
  if (auto *T = llvm::dyn_cast<TagDecl>(&ND))
    return T->getQualifierLoc();
  return NestedNameSpecifierLoc();
}

std::string printUsingNamespaceName(const ASTContext &Ctx,
                                    const UsingDirectiveDecl &D) {
  PrintingPolicy PP(Ctx.getLangOpts());
  std::string Name;
  llvm::raw_string_ostream Out(Name);

  if (auto *Qual = D.getQualifier())
    Qual->print(Out, PP);
  D.getNominatedNamespaceAsWritten()->printName(Out);
  return Out.str();
}

std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
  std::string Name;
  llvm::raw_string_ostream Out(Name);
  PrintingPolicy PP(Ctx.getLangOpts());
  // We don't consider a class template's args part of the constructor name.
  PP.SuppressTemplateArgsInCXXConstructors = true;

  // Handle 'using namespace'. They all have the same name - <using-directive>.
  if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) {
    Out << "using namespace ";
    if (auto *Qual = UD->getQualifier())
      Qual->print(Out, PP);
    UD->getNominatedNamespaceAsWritten()->printName(Out);
    return Out.str();
  }

  if (isAnonymous(ND.getDeclName())) {
    // Come up with a presentation for an anonymous entity.
    if (isa<NamespaceDecl>(ND))
      return "(anonymous namespace)";
    if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) {
      if (Cls->isLambda())
        return "(lambda)";
      return ("(anonymous " + Cls->getKindName() + ")").str();
    }
    if (isa<EnumDecl>(ND))
      return "(anonymous enum)";
    return "(anonymous)";
  }

  // Print nested name qualifier if it was written in the source code.
  if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier())
    Qualifier->print(Out, PP);
  // Print the name itself.
  ND.getDeclName().print(Out, PP);
  // Print template arguments.
  Out << printTemplateSpecializationArgs(ND);

  return Out.str();
}

std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
  std::string TemplateArgs;
  llvm::raw_string_ostream OS(TemplateArgs);
  PrintingPolicy Policy(ND.getASTContext().getLangOpts());
  if (std::optional<llvm::ArrayRef<TemplateArgumentLoc>> Args =
          getTemplateSpecializationArgLocs(ND)) {
    printTemplateArgumentList(OS, *Args, Policy);
  } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
    if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) {
      // ClassTemplateSpecializationDecls do not contain
      // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we
      // create a new argument location list from TypeSourceInfo.
      auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
      llvm::SmallVector<TemplateArgumentLoc> ArgLocs;
      ArgLocs.reserve(STL.getNumArgs());
      for (unsigned I = 0; I < STL.getNumArgs(); ++I)
        ArgLocs.push_back(STL.getArgLoc(I));
      printTemplateArgumentList(OS, ArgLocs, Policy);
    } else {
      // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
      // e.g. friend decls. Currently we fallback to Template Arguments without
      // location information.
      printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
    }
  }
  OS.flush();
  return TemplateArgs;
}

std::string printNamespaceScope(const DeclContext &DC) {
  for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent())
    if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx))
      if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace())
        return printQualifiedName(*NS) + "::";
  return "";
}

static llvm::StringRef
getNameOrErrForObjCInterface(const ObjCInterfaceDecl *ID) {
  return ID ? ID->getName() : "<<error-type>>";
}

std::string printObjCMethod(const ObjCMethodDecl &Method) {
  std::string Name;
  llvm::raw_string_ostream OS(Name);

  OS << (Method.isInstanceMethod() ? '-' : '+') << '[';

  // Should always be true.
  if (const ObjCContainerDecl *C =
          dyn_cast<ObjCContainerDecl>(Method.getDeclContext()))
    OS << printObjCContainer(*C);

  Method.getSelector().print(OS << ' ');
  if (Method.isVariadic())
    OS << ", ...";

  OS << ']';
  OS.flush();
  return Name;
}

std::string printObjCContainer(const ObjCContainerDecl &C) {
  if (const ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(&C)) {
    std::string Name;
    llvm::raw_string_ostream OS(Name);
    const ObjCInterfaceDecl *Class = Category->getClassInterface();
    OS << getNameOrErrForObjCInterface(Class) << '(' << Category->getName()
       << ')';
    OS.flush();
    return Name;
  }
  if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(&C)) {
    std::string Name;
    llvm::raw_string_ostream OS(Name);
    const ObjCInterfaceDecl *Class = CID->getClassInterface();
    OS << getNameOrErrForObjCInterface(Class) << '(' << CID->getName() << ')';
    OS.flush();
    return Name;
  }
  return C.getNameAsString();
}

SymbolID getSymbolID(const Decl *D) {
  llvm::SmallString<128> USR;
  if (index::generateUSRForDecl(D, USR))
    return {};
  return SymbolID(USR);
}

SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
                     const SourceManager &SM) {
  if (MI == nullptr)
    return {};
  llvm::SmallString<128> USR;
  if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR))
    return {};
  return SymbolID(USR);
}

const ObjCImplDecl *getCorrespondingObjCImpl(const ObjCContainerDecl *D) {
  if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D))
    return ID->getImplementation();
  if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) {
    if (CD->IsClassExtension()) {
      if (const auto *ID = CD->getClassInterface())
        return ID->getImplementation();
      return nullptr;
    }
    return CD->getImplementation();
  }
  return nullptr;
}

Symbol::IncludeDirective
preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts,
                          ArrayRef<Inclusion> MainFileIncludes,
                          ArrayRef<const Decl *> TopLevelDecls) {
  // Always prefer #include for non-ObjC code.
  if (!LangOpts.ObjC)
    return Symbol::IncludeDirective::Include;
  // If this is not a header file and has ObjC set as the language, prefer
  // #import.
  if (!isHeaderFile(FileName, LangOpts))
    return Symbol::IncludeDirective::Import;

  // Headers lack proper compile flags most of the time, so we might treat a
  // header as ObjC accidentally. Perform some extra checks to make sure this
  // works.

  // Any file with a #import, should keep #import-ing.
  for (auto &Inc : MainFileIncludes)
    if (Inc.Directive == tok::pp_import)
      return Symbol::IncludeDirective::Import;

  // Any file declaring an ObjC decl should also be #import-ing.
  // No need to look over the references, as the file doesn't have any #imports,
  // it must be declaring interesting ObjC-like decls.
  for (const Decl *D : TopLevelDecls)
    if (isa<ObjCContainerDecl, ObjCIvarDecl, ObjCMethodDecl, ObjCPropertyDecl>(
            D))
      return Symbol::IncludeDirective::Import;

  return Symbol::IncludeDirective::Include;
}

std::string printType(const QualType QT, const DeclContext &CurContext,
                      const llvm::StringRef Placeholder) {
  std::string Result;
  llvm::raw_string_ostream OS(Result);
  PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
  PP.SuppressTagKeyword = true;
  PP.SuppressUnwrittenScope = true;

  class PrintCB : public PrintingCallbacks {
  public:
    PrintCB(const DeclContext *CurContext) : CurContext(CurContext) {}
    virtual ~PrintCB() {}
    bool isScopeVisible(const DeclContext *DC) const override {
      return DC->Encloses(CurContext);
    }

  private:
    const DeclContext *CurContext;
  };
  PrintCB PCB(&CurContext);
  PP.Callbacks = &PCB;

  QT.print(OS, PP, Placeholder);
  return OS.str();
}

bool hasReservedName(const Decl &D) {
  if (const auto *ND = llvm::dyn_cast<NamedDecl>(&D))
    if (const auto *II = ND->getIdentifier())
      return isReservedName(II->getName());
  return false;
}

bool hasReservedScope(const DeclContext &DC) {
  for (const DeclContext *D = &DC; D; D = D->getParent()) {
    if (D->isTransparentContext() || D->isInlineNamespace())
      continue;
    if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
      if (hasReservedName(*ND))
        return true;
  }
  return false;
}

QualType declaredType(const TypeDecl *D) {
  if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
    if (const auto *TSI = CTSD->getTypeAsWritten())
      return TSI->getType();
  return D->getASTContext().getTypeDeclType(D);
}

namespace {
/// Computes the deduced type at a given location by visiting the relevant
/// nodes. We use this to display the actual type when hovering over an "auto"
/// keyword or "decltype()" expression.
/// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it
/// seems that the AutoTypeLocs that can be visited along with their AutoType do
/// not have the deduced type set. Instead, we have to go to the appropriate
/// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have
/// a deduced type set. The AST should be improved to simplify this scenario.
class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
  SourceLocation SearchedLocation;

public:
  DeducedTypeVisitor(SourceLocation SearchedLocation)
      : SearchedLocation(SearchedLocation) {}

  // Handle auto initializers:
  //- auto i = 1;
  //- decltype(auto) i = 1;
  //- auto& i = 1;
  //- auto* i = &a;
  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
    if (!D->getTypeSourceInfo() ||
        !D->getTypeSourceInfo()->getTypeLoc().getContainedAutoTypeLoc() ||
        D->getTypeSourceInfo()
                ->getTypeLoc()
                .getContainedAutoTypeLoc()
                .getNameLoc() != SearchedLocation)
      return true;

    if (auto *AT = D->getType()->getContainedAutoType()) {
      DeducedType = AT->desugar();
    }
    return true;
  }

  // Handle auto return types:
  //- auto foo() {}
  //- auto& foo() {}
  //- auto foo() -> int {}
  //- auto foo() -> decltype(1+1) {}
  //- operator auto() const { return 10; }
  bool VisitFunctionDecl(FunctionDecl *D) {
    if (!D->getTypeSourceInfo())
      return true;
    // Loc of auto in return type (c++14).
    auto CurLoc = D->getReturnTypeSourceRange().getBegin();
    // Loc of "auto" in operator auto()
    if (CurLoc.isInvalid() && isa<CXXConversionDecl>(D))
      CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
    // Loc of "auto" in function with trailing return type (c++11).
    if (CurLoc.isInvalid())
      CurLoc = D->getSourceRange().getBegin();
    if (CurLoc != SearchedLocation)
      return true;

    const AutoType *AT = D->getReturnType()->getContainedAutoType();
    if (AT && !AT->getDeducedType().isNull()) {
      DeducedType = AT->getDeducedType();
    } else if (auto *DT = dyn_cast<DecltypeType>(D->getReturnType())) {
      // auto in a trailing return type just points to a DecltypeType and
      // getContainedAutoType does not unwrap it.
      if (!DT->getUnderlyingType().isNull())
        DeducedType = DT->getUnderlyingType();
    } else if (!D->getReturnType().isNull()) {
      DeducedType = D->getReturnType();
    }
    return true;
  }

  // Handle non-auto decltype, e.g.:
  // - auto foo() -> decltype(expr) {}
  // - decltype(expr);
  bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
    if (TL.getBeginLoc() != SearchedLocation)
      return true;

    // A DecltypeType's underlying type can be another DecltypeType! E.g.
    //  int I = 0;
    //  decltype(I) J = I;
    //  decltype(J) K = J;
    const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
    while (DT && !DT->getUnderlyingType().isNull()) {
      DeducedType = DT->getUnderlyingType();
      DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr());
    }
    return true;
  }

  // Handle functions/lambdas with `auto` typed parameters.
  // We deduce the type if there's exactly one instantiation visible.
  bool VisitParmVarDecl(ParmVarDecl *PVD) {
    if (!PVD->getType()->isDependentType())
      return true;
    // 'auto' here does not name an AutoType, but an implicit template param.
    TemplateTypeParmTypeLoc Auto =
        getContainedAutoParamType(PVD->getTypeSourceInfo()->getTypeLoc());
    if (Auto.isNull() || Auto.getNameLoc() != SearchedLocation)
      return true;

    // We expect the TTP to be attached to this function template.
    // Find the template and the param index.
    auto *Templated = llvm::dyn_cast<FunctionDecl>(PVD->getDeclContext());
    if (!Templated)
      return true;
    auto *FTD = Templated->getDescribedFunctionTemplate();
    if (!FTD)
      return true;
    int ParamIndex = paramIndex(*FTD, *Auto.getDecl());
    if (ParamIndex < 0) {
      assert(false && "auto TTP is not from enclosing function?");
      return true;
    }

    // Now find the instantiation and the deduced template type arg.
    auto *Instantiation =
        llvm::dyn_cast_or_null<FunctionDecl>(getOnlyInstantiation(Templated));
    if (!Instantiation)
      return true;
    const auto *Args = Instantiation->getTemplateSpecializationArgs();
    if (Args->size() != FTD->getTemplateParameters()->size())
      return true; // no weird variadic stuff
    DeducedType = Args->get(ParamIndex).getAsType();
    return true;
  }

  static int paramIndex(const TemplateDecl &TD, NamedDecl &Param) {
    unsigned I = 0;
    for (auto *ND : *TD.getTemplateParameters()) {
      if (&Param == ND)
        return I;
      ++I;
    }
    return -1;
  }

  QualType DeducedType;
};
} // namespace

std::optional<QualType> getDeducedType(ASTContext &ASTCtx, SourceLocation Loc) {
  if (!Loc.isValid())
    return {};
  DeducedTypeVisitor V(Loc);
  V.TraverseAST(ASTCtx);
  if (V.DeducedType.isNull())
    return std::nullopt;
  return V.DeducedType;
}

TemplateTypeParmTypeLoc getContainedAutoParamType(TypeLoc TL) {
  if (auto QTL = TL.getAs<QualifiedTypeLoc>())
    return getContainedAutoParamType(QTL.getUnqualifiedLoc());
  if (llvm::isa<PointerType, ReferenceType, ParenType>(TL.getTypePtr()))
    return getContainedAutoParamType(TL.getNextTypeLoc());
  if (auto FTL = TL.getAs<FunctionTypeLoc>())
    return getContainedAutoParamType(FTL.getReturnLoc());
  if (auto TTPTL = TL.getAs<TemplateTypeParmTypeLoc>()) {
    if (TTPTL.getTypePtr()->getDecl()->isImplicit())
      return TTPTL;
  }
  return {};
}

template <typename TemplateDeclTy>
static NamedDecl *getOnlyInstantiationImpl(TemplateDeclTy *TD) {
  NamedDecl *Only = nullptr;
  for (auto *Spec : TD->specializations()) {
    if (Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
      continue;
    if (Only != nullptr)
      return nullptr;
    Only = Spec;
  }
  return Only;
}

NamedDecl *getOnlyInstantiation(NamedDecl *TemplatedDecl) {
  if (TemplateDecl *TD = TemplatedDecl->getDescribedTemplate()) {
    if (auto *CTD = llvm::dyn_cast<ClassTemplateDecl>(TD))
      return getOnlyInstantiationImpl(CTD);
    if (auto *FTD = llvm::dyn_cast<FunctionTemplateDecl>(TD))
      return getOnlyInstantiationImpl(FTD);
    if (auto *VTD = llvm::dyn_cast<VarTemplateDecl>(TD))
      return getOnlyInstantiationImpl(VTD);
  }
  return nullptr;
}

std::vector<const Attr *> getAttributes(const DynTypedNode &N) {
  std::vector<const Attr *> Result;
  if (const auto *TL = N.get<TypeLoc>()) {
    for (AttributedTypeLoc ATL = TL->getAs<AttributedTypeLoc>(); !ATL.isNull();
         ATL = ATL.getModifiedLoc().getAs<AttributedTypeLoc>()) {
      if (const Attr *A = ATL.getAttr())
        Result.push_back(A);
      assert(!ATL.getModifiedLoc().isNull());
    }
  }
  if (const auto *S = N.get<AttributedStmt>()) {
    for (; S != nullptr; S = dyn_cast<AttributedStmt>(S->getSubStmt()))
      for (const Attr *A : S->getAttrs())
        if (A)
          Result.push_back(A);
  }
  if (const auto *D = N.get<Decl>()) {
    for (const Attr *A : D->attrs())
      if (A)
        Result.push_back(A);
  }
  return Result;
}

std::string getQualification(ASTContext &Context,
                             const DeclContext *DestContext,
                             SourceLocation InsertionPoint,
                             const NamedDecl *ND) {
  auto VisibleNamespaceDecls =
      getUsingNamespaceDirectives(DestContext, InsertionPoint);
  return getQualification(
      Context, DestContext, ND->getDeclContext(),
      [&](NestedNameSpecifier *NNS) {
        if (NNS->getKind() != NestedNameSpecifier::Namespace)
          return false;
        const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl();
        return llvm::any_of(VisibleNamespaceDecls,
                            [CanonNSD](const NamespaceDecl *NSD) {
                              return NSD->getCanonicalDecl() == CanonNSD;
                            });
      });
}

std::string getQualification(ASTContext &Context,
                             const DeclContext *DestContext,
                             const NamedDecl *ND,
                             llvm::ArrayRef<std::string> VisibleNamespaces) {
  for (llvm::StringRef NS : VisibleNamespaces) {
    assert(NS.ends_with("::"));
    (void)NS;
  }
  return getQualification(
      Context, DestContext, ND->getDeclContext(),
      [&](NestedNameSpecifier *NNS) {
        return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) {
          std::string NS;
          llvm::raw_string_ostream OS(NS);
          NNS->print(OS, Context.getPrintingPolicy());
          return OS.str() == Namespace;
        });
      });
}

bool hasUnstableLinkage(const Decl *D) {
  // Linkage of a ValueDecl depends on the type.
  // If that's not deduced yet, deducing it may change the linkage.
  auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
  return VD && !VD->getType().isNull() && VD->getType()->isUndeducedType();
}

bool isDeeplyNested(const Decl *D, unsigned MaxDepth) {
  size_t ContextDepth = 0;
  for (auto *Ctx = D->getDeclContext(); Ctx && !Ctx->isTranslationUnit();
       Ctx = Ctx->getParent()) {
    if (++ContextDepth == MaxDepth)
      return true;
  }
  return false;
}

namespace {

// returns true for `X` in `template <typename... X> void foo()`
bool isTemplateTypeParameterPack(NamedDecl *D) {
  if (const auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D)) {
    return TTPD->isParameterPack();
  }
  return false;
}

// Returns the template parameter pack type from an instantiated function
// template, if it exists, nullptr otherwise.
const TemplateTypeParmType *getFunctionPackType(const FunctionDecl *Callee) {
  if (const auto *TemplateDecl = Callee->getPrimaryTemplate()) {
    auto TemplateParams = TemplateDecl->getTemplateParameters()->asArray();
    // find the template parameter pack from the back
    const auto It = std::find_if(TemplateParams.rbegin(), TemplateParams.rend(),
                                 isTemplateTypeParameterPack);
    if (It != TemplateParams.rend()) {
      const auto *TTPD = dyn_cast<TemplateTypeParmDecl>(*It);
      return TTPD->getTypeForDecl()->castAs<TemplateTypeParmType>();
    }
  }
  return nullptr;
}

// Returns the template parameter pack type that this parameter was expanded
// from (if in the Args... or Args&... or Args&&... form), if this is the case,
// nullptr otherwise.
const TemplateTypeParmType *getUnderlyingPackType(const ParmVarDecl *Param) {
  const auto *PlainType = Param->getType().getTypePtr();
  if (auto *RT = dyn_cast<ReferenceType>(PlainType))
    PlainType = RT->getPointeeTypeAsWritten().getTypePtr();
  if (const auto *SubstType = dyn_cast<SubstTemplateTypeParmType>(PlainType)) {
    const auto *ReplacedParameter = SubstType->getReplacedParameter();
    if (ReplacedParameter->isParameterPack()) {
      return ReplacedParameter->getTypeForDecl()
          ->castAs<TemplateTypeParmType>();
    }
  }
  return nullptr;
}

// This visitor walks over the body of an instantiated function template.
// The template accepts a parameter pack and the visitor records whether
// the pack parameters were forwarded to another call. For example, given:
//
// template <typename T, typename... Args>
// auto make_unique(Args... args) {
//   return unique_ptr<T>(new T(args...));
// }
//
// When called as `make_unique<std::string>(2, 'x')` this yields a function
// `make_unique<std::string, int, char>` with two parameters.
// The visitor records that those two parameters are forwarded to the
// `constructor std::string(int, char);`.
//
// This information is recorded in the `ForwardingInfo` split into fully
// resolved parameters (passed as argument to a parameter that is not an
// expanded template type parameter pack) and forwarding parameters (passed to a
// parameter that is an expanded template type parameter pack).
class ForwardingCallVisitor
    : public RecursiveASTVisitor<ForwardingCallVisitor> {
public:
  ForwardingCallVisitor(ArrayRef<const ParmVarDecl *> Parameters)
      : Parameters{Parameters},
        PackType{getUnderlyingPackType(Parameters.front())} {}

  bool VisitCallExpr(CallExpr *E) {
    auto *Callee = getCalleeDeclOrUniqueOverload(E);
    if (Callee) {
      handleCall(Callee, E->arguments());
    }
    return !Info.has_value();
  }

  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    auto *Callee = E->getConstructor();
    if (Callee) {
      handleCall(Callee, E->arguments());
    }
    return !Info.has_value();
  }

  // The expanded parameter pack to be resolved
  ArrayRef<const ParmVarDecl *> Parameters;
  // The type of the parameter pack
  const TemplateTypeParmType *PackType;

  struct ForwardingInfo {
    // If the parameters were resolved to another FunctionDecl, these are its
    // first non-variadic parameters (i.e. the first entries of the parameter
    // pack that are passed as arguments bound to a non-pack parameter.)
    ArrayRef<const ParmVarDecl *> Head;
    // If the parameters were resolved to another FunctionDecl, these are its
    // variadic parameters (i.e. the entries of the parameter pack that are
    // passed as arguments bound to a pack parameter.)
    ArrayRef<const ParmVarDecl *> Pack;
    // If the parameters were resolved to another FunctionDecl, these are its
    // last non-variadic parameters (i.e. the last entries of the parameter pack
    // that are passed as arguments bound to a non-pack parameter.)
    ArrayRef<const ParmVarDecl *> Tail;
    // If the parameters were resolved to another forwarding FunctionDecl, this
    // is it.
    std::optional<FunctionDecl *> PackTarget;
  };

  // The output of this visitor
  std::optional<ForwardingInfo> Info;

private:
  // inspects the given callee with the given args to check whether it
  // contains Parameters, and sets Info accordingly.
  void handleCall(FunctionDecl *Callee, typename CallExpr::arg_range Args) {
    // Skip functions with less parameters, they can't be the target.
    if (Callee->parameters().size() < Parameters.size())
      return;
    if (llvm::any_of(Args,
                     [](const Expr *E) { return isa<PackExpansionExpr>(E); })) {
      return;
    }
    auto PackLocation = findPack(Args);
    if (!PackLocation)
      return;
    ArrayRef<ParmVarDecl *> MatchingParams =
        Callee->parameters().slice(*PackLocation, Parameters.size());
    // Check whether the function has a parameter pack as the last template
    // parameter
    if (const auto *TTPT = getFunctionPackType(Callee)) {
      // In this case: Separate the parameters into head, pack and tail
      auto IsExpandedPack = [&](const ParmVarDecl *P) {
        return getUnderlyingPackType(P) == TTPT;
      };
      ForwardingInfo FI;
      FI.Head = MatchingParams.take_until(IsExpandedPack);
      FI.Pack =
          MatchingParams.drop_front(FI.Head.size()).take_while(IsExpandedPack);
      FI.Tail = MatchingParams.drop_front(FI.Head.size() + FI.Pack.size());
      FI.PackTarget = Callee;
      Info = FI;
      return;
    }
    // Default case: assume all parameters were fully resolved
    ForwardingInfo FI;
    FI.Head = MatchingParams;
    Info = FI;
  }

  // Returns the beginning of the expanded pack represented by Parameters
  // in the given arguments, if it is there.
  std::optional<size_t> findPack(typename CallExpr::arg_range Args) {
    // find the argument directly referring to the first parameter
    assert(Parameters.size() <= static_cast<size_t>(llvm::size(Args)));
    for (auto Begin = Args.begin(), End = Args.end() - Parameters.size() + 1;
         Begin != End; ++Begin) {
      if (const auto *RefArg = unwrapForward(*Begin)) {
        if (Parameters.front() != RefArg->getDecl())
          continue;
        // Check that this expands all the way until the last parameter.
        // It's enough to look at the last parameter, because it isn't possible
        // to expand without expanding all of them.
        auto ParamEnd = Begin + Parameters.size() - 1;
        RefArg = unwrapForward(*ParamEnd);
        if (!RefArg || Parameters.back() != RefArg->getDecl())
          continue;
        return std::distance(Args.begin(), Begin);
      }
    }
    return std::nullopt;
  }

  static FunctionDecl *getCalleeDeclOrUniqueOverload(CallExpr *E) {
    Decl *CalleeDecl = E->getCalleeDecl();
    auto *Callee = dyn_cast_or_null<FunctionDecl>(CalleeDecl);
    if (!Callee) {
      if (auto *Lookup = dyn_cast<UnresolvedLookupExpr>(E->getCallee())) {
        Callee = resolveOverload(Lookup, E);
      }
    }
    // Ignore the callee if the number of arguments is wrong (deal with va_args)
    if (Callee && Callee->getNumParams() == E->getNumArgs())
      return Callee;
    return nullptr;
  }

  static FunctionDecl *resolveOverload(UnresolvedLookupExpr *Lookup,
                                       CallExpr *E) {
    FunctionDecl *MatchingDecl = nullptr;
    if (!Lookup->requiresADL()) {
      // Check whether there is a single overload with this number of
      // parameters
      for (auto *Candidate : Lookup->decls()) {
        if (auto *FuncCandidate = dyn_cast_or_null<FunctionDecl>(Candidate)) {
          if (FuncCandidate->getNumParams() == E->getNumArgs()) {
            if (MatchingDecl) {
              // there are multiple candidates - abort
              return nullptr;
            }
            MatchingDecl = FuncCandidate;
          }
        }
      }
    }
    return MatchingDecl;
  }

  // Tries to get to the underlying argument by unwrapping implicit nodes and
  // std::forward.
  static const DeclRefExpr *unwrapForward(const Expr *E) {
    E = E->IgnoreImplicitAsWritten();
    // There might be an implicit copy/move constructor call on top of the
    // forwarded arg.
    // FIXME: Maybe mark implicit calls in the AST to properly filter here.
    if (const auto *Const = dyn_cast<CXXConstructExpr>(E))
      if (Const->getConstructor()->isCopyOrMoveConstructor())
        E = Const->getArg(0)->IgnoreImplicitAsWritten();
    if (const auto *Call = dyn_cast<CallExpr>(E)) {
      const auto Callee = Call->getBuiltinCallee();
      if (Callee == Builtin::BIforward) {
        return dyn_cast<DeclRefExpr>(
            Call->getArg(0)->IgnoreImplicitAsWritten());
      }
    }
    return dyn_cast<DeclRefExpr>(E);
  }
};

} // namespace

SmallVector<const ParmVarDecl *>
resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) {
  auto Parameters = D->parameters();
  // If the function has a template parameter pack
  if (const auto *TTPT = getFunctionPackType(D)) {
    // Split the parameters into head, pack and tail
    auto IsExpandedPack = [TTPT](const ParmVarDecl *P) {
      return getUnderlyingPackType(P) == TTPT;
    };
    ArrayRef<const ParmVarDecl *> Head = Parameters.take_until(IsExpandedPack);
    ArrayRef<const ParmVarDecl *> Pack =
        Parameters.drop_front(Head.size()).take_while(IsExpandedPack);
    ArrayRef<const ParmVarDecl *> Tail =
        Parameters.drop_front(Head.size() + Pack.size());
    SmallVector<const ParmVarDecl *> Result(Parameters.size());
    // Fill in non-pack parameters
    auto HeadIt = std::copy(Head.begin(), Head.end(), Result.begin());
    auto TailIt = std::copy(Tail.rbegin(), Tail.rend(), Result.rbegin());
    // Recurse on pack parameters
    size_t Depth = 0;
    const FunctionDecl *CurrentFunction = D;
    llvm::SmallSet<const FunctionTemplateDecl *, 4> SeenTemplates;
    if (const auto *Template = D->getPrimaryTemplate()) {
      SeenTemplates.insert(Template);
    }
    while (!Pack.empty() && CurrentFunction && Depth < MaxDepth) {
      // Find call expressions involving the pack
      ForwardingCallVisitor V{Pack};
      V.TraverseStmt(CurrentFunction->getBody());
      if (!V.Info) {
        break;
      }
      // If we found something: Fill in non-pack parameters
      auto Info = *V.Info;
      HeadIt = std::copy(Info.Head.begin(), Info.Head.end(), HeadIt);
      TailIt = std::copy(Info.Tail.rbegin(), Info.Tail.rend(), TailIt);
      // Prepare next recursion level
      Pack = Info.Pack;
      CurrentFunction = Info.PackTarget.value_or(nullptr);
      Depth++;
      // If we are recursing into a previously encountered function: Abort
      if (CurrentFunction) {
        if (const auto *Template = CurrentFunction->getPrimaryTemplate()) {
          bool NewFunction = SeenTemplates.insert(Template).second;
          if (!NewFunction) {
            return {Parameters.begin(), Parameters.end()};
          }
        }
      }
    }
    // Fill in the remaining unresolved pack parameters
    HeadIt = std::copy(Pack.begin(), Pack.end(), HeadIt);
    assert(TailIt.base() == HeadIt);
    return Result;
  }
  return {Parameters.begin(), Parameters.end()};
}

bool isExpandedFromParameterPack(const ParmVarDecl *D) {
  return getUnderlyingPackType(D) != nullptr;
}

} // namespace clangd
} // namespace clang
