//===--- 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<ClassTemplateSpecializationDecl>(&ND)) {
    if (auto *Args = Cls->getTemplateArgsAsWritten())
      return Args->arguments();
  } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) {
    if (auto *Args = Var->getTemplateArgsAsWritten())
      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)) {
    if (Parent != *Parents.rbegin() && Parent->isDependent() &&
        Parent->getAsRecordDecl() &&
        Parent->getAsRecordDecl()->getDescribedClassTemplate())
      OS << "template ";
    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);
  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)) {
    // 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);
  }
  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 << ']';
  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()
       << ')';
    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() << ')';
    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) {
  ASTContext &Context = D->getASTContext();
  if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
    if (const auto *Args = CTSD->getTemplateArgsAsWritten())
      return Context.getTemplateSpecializationType(
          TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
  return Context.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
