//===--- WalkAST.cpp - Find declaration references in the AST -------------===//
//
// 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 "AnalysisInternal.h"
#include "clang-include-cleaner/Types.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"

namespace clang::include_cleaner {
namespace {
using DeclCallback =
    llvm::function_ref<void(SourceLocation, NamedDecl &, RefType)>;

class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
  DeclCallback Callback;

  void report(SourceLocation Loc, NamedDecl *ND,
              RefType RT = RefType::Explicit) {
    if (!ND || Loc.isInvalid())
      return;
    Callback(Loc, *cast<NamedDecl>(ND->getCanonicalDecl()), RT);
  }

  NamedDecl *resolveTemplateName(TemplateName TN) {
    // For using-templates, only mark the alias.
    if (auto *USD = TN.getAsUsingShadowDecl())
      return USD;
    return TN.getAsTemplateDecl();
  }
  NamedDecl *getMemberProvider(QualType Base) {
    if (Base->isPointerType())
      return getMemberProvider(Base->getPointeeType());
    // Unwrap the sugar ElaboratedType.
    if (const auto *ElTy = dyn_cast<ElaboratedType>(Base))
      return getMemberProvider(ElTy->getNamedType());

    if (const auto *TT = dyn_cast<TypedefType>(Base))
      return TT->getDecl();
    if (const auto *UT = dyn_cast<UsingType>(Base))
      return UT->getFoundDecl();
    // A heuristic: to resolve a template type to **only** its template name.
    // We're only using this method for the base type of MemberExpr, in general
    // the template provides the member, and the critical case `unique_ptr<Foo>`
    // is supported (the base type is a Foo*).
    //
    // There are some exceptions that this heuristic could fail (dependent base,
    // dependent typealias), but we believe these are rare.
    if (const auto *TST = dyn_cast<TemplateSpecializationType>(Base))
      return resolveTemplateName(TST->getTemplateName());
    return Base->getAsRecordDecl();
  }
  // Templated as TemplateSpecializationType and
  // DeducedTemplateSpecializationType doesn't share a common base.
  template <typename T>
  // Picks the most specific specialization for a
  // (Deduced)TemplateSpecializationType, while prioritizing using-decls.
  NamedDecl *getMostRelevantTemplatePattern(const T *TST) {
    // In case of exported template names always prefer the using-decl. This
    // implies we'll point at the using-decl even when there's an explicit
    // specializaiton using the exported name, but that's rare.
    auto *ND = resolveTemplateName(TST->getTemplateName());
    if (llvm::isa_and_present<UsingShadowDecl, TypeAliasTemplateDecl>(ND))
      return ND;
    // This is the underlying decl used by TemplateSpecializationType, can be
    // null when type is dependent or not resolved to a pattern yet.
    // If so, fallback to primary template.
    CXXRecordDecl *TD = TST->getAsCXXRecordDecl();
    if (!TD || TD->getTemplateSpecializationKind() == TSK_Undeclared)
      return ND;
    // We ignore explicit instantiations. This might imply marking the wrong
    // declaration as used in specific cases, but seems like the right trade-off
    // in general (e.g. we don't want to include a custom library that has an
    // explicit specialization of a common type).
    if (auto *Pat = TD->getTemplateInstantiationPattern())
      return Pat;
    // For explicit specializations, use the specialized decl directly.
    return TD;
  }

public:
  ASTWalker(DeclCallback Callback) : Callback(Callback) {}

  // Operators are almost always ADL extension points and by design references
  // to them doesn't count as uses (generally the type should provide them, so
  // ignore them).
  // Unless we're using an operator defined as a member, in such cases treat
  // these as regular member references.
  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
    if (!WalkUpFromCXXOperatorCallExpr(S))
      return false;
    if (auto *CD = S->getCalleeDecl()) {
      if (llvm::isa<CXXMethodDecl>(CD)) {
        // Treat this as a regular member reference.
        report(S->getOperatorLoc(), getMemberProvider(S->getArg(0)->getType()),
               RefType::Implicit);
      } else {
        report(S->getOperatorLoc(), llvm::dyn_cast<NamedDecl>(CD),
               RefType::Implicit);
      }
    }
    for (auto *Arg : S->arguments())
      if (!TraverseStmt(Arg))
        return false;
    return true;
  }

  bool VisitDeclRefExpr(DeclRefExpr *DRE) {
    auto *FD = DRE->getFoundDecl();
    // Prefer the underlying decl if FoundDecl isn't a shadow decl, e.g:
    // - For templates, found-decl is always primary template, but we want the
    // specializaiton itself.
    if (!llvm::isa<UsingShadowDecl>(FD))
      FD = DRE->getDecl();
    // For refs to non-meber-like decls, use the found decl.
    // For member-like decls, we should have a reference from the qualifier to
    // the container decl instead, which is preferred as it'll handle
    // aliases/exports properly.
    if (!FD->isCXXClassMember() && !llvm::isa<EnumConstantDecl>(FD)) {
      report(DRE->getLocation(), FD);
      return true;
    }
    // If the ref is without a qualifier, and is a member, ignore it. As it is
    // available in current context due to some other construct (e.g. base
    // specifiers, using decls) that has to spell the name explicitly.
    //
    // If it's an enum constant, it must be due to prior decl. Report references
    // to it when qualifier isn't a type.
    if (llvm::isa<EnumConstantDecl>(FD)) {
      if (!DRE->getQualifier() || DRE->getQualifier()->getAsNamespace())
        report(DRE->getLocation(), FD);
    }
    return true;
  }

  bool VisitMemberExpr(MemberExpr *E) {
    // Reporting a usage of the member decl would cause issues (e.g. force
    // including the base class for inherited members). Instead, we report a
    // usage of the base type of the MemberExpr, so that e.g. code
    // `returnFoo().bar` can keep #include "foo.h" (rather than inserting
    // "bar.h" for the underlying base type `Bar`).
    QualType Type = E->getBase()->IgnoreImpCasts()->getType();
    report(E->getMemberLoc(), getMemberProvider(Type), RefType::Implicit);
    return true;
  }
  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
    report(E->getMemberLoc(), getMemberProvider(E->getBaseType()),
           RefType::Implicit);
    return true;
  }

  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    // Always treat consturctor calls as implicit. We'll have an explicit
    // reference for the constructor calls that mention the type-name (through
    // TypeLocs). This reference only matters for cases where there's no
    // explicit syntax at all or there're only braces.
    report(E->getLocation(), getMemberProvider(E->getType()),
           RefType::Implicit);
    return true;
  }

  bool VisitOverloadExpr(OverloadExpr *E) {
    // Since we can't prove which overloads are used, report all of them.
    for (NamedDecl *D : E->decls())
      report(E->getNameLoc(), D, RefType::Ambiguous);
    return true;
  }

  // Report all (partial) specializations of a class/var template decl.
  template <typename TemplateDeclType, typename ParitialDeclType>
  void reportSpecializations(SourceLocation Loc, NamedDecl *ND) {
    const auto *TD = llvm::dyn_cast<TemplateDeclType>(ND);
    if (!TD)
      return;

    for (auto *Spec : TD->specializations())
      report(Loc, Spec, RefType::Ambiguous);
    llvm::SmallVector<ParitialDeclType *> PartialSpecializations;
    TD->getPartialSpecializations(PartialSpecializations);
    for (auto *PartialSpec : PartialSpecializations)
      report(Loc, PartialSpec, RefType::Ambiguous);
  }
  bool VisitUsingDecl(UsingDecl *UD) {
    for (const auto *Shadow : UD->shadows()) {
      auto *TD = Shadow->getTargetDecl();
      auto IsUsed = TD->isUsed() || TD->isReferenced();
      report(UD->getLocation(), TD,
             IsUsed ? RefType::Explicit : RefType::Ambiguous);

      // All (partial) template specializations are visible via a using-decl,
      // However a using-decl only refers to the primary template (per C++ name
      // lookup). Thus, we need to manually report all specializations.
      reportSpecializations<ClassTemplateDecl,
                            ClassTemplatePartialSpecializationDecl>(
          UD->getLocation(), TD);
      reportSpecializations<VarTemplateDecl,
                            VarTemplatePartialSpecializationDecl>(
          UD->getLocation(), TD);
      if (const auto *FTD = llvm::dyn_cast<FunctionTemplateDecl>(TD))
        for (auto *Spec : FTD->specializations())
          report(UD->getLocation(), Spec, RefType::Ambiguous);
    }
    return true;
  }

  bool VisitFunctionDecl(FunctionDecl *FD) {
    // Mark declaration from definition as it needs type-checking.
    if (FD->isThisDeclarationADefinition())
      report(FD->getLocation(), FD);
    // Explicit specializaiton/instantiations of a function template requires
    // primary template.
    if (clang::isTemplateExplicitInstantiationOrSpecialization(
            FD->getTemplateSpecializationKind()))
      report(FD->getLocation(), FD->getPrimaryTemplate());
    return true;
  }
  bool VisitVarDecl(VarDecl *VD) {
    // Ignore the parameter decl itself (its children were handled elsewhere),
    // as they don't contribute to the main-file #include.
    if (llvm::isa<ParmVarDecl>(VD))
      return true;
    // Mark declaration from definition as it needs type-checking.
    if (VD->isThisDeclarationADefinition())
      report(VD->getLocation(), VD);
    return true;
  }

  bool VisitEnumDecl(EnumDecl *D) {
    // Definition of an enum with an underlying type references declaration for
    // type-checking purposes.
    if (D->isThisDeclarationADefinition() && D->getIntegerTypeSourceInfo())
      report(D->getLocation(), D);
    return true;
  }

  bool VisitFriendDecl(FriendDecl *D) {
    // We already visit the TypeLoc properly, but need to special case the decl
    // case.
    if (auto *FD = D->getFriendDecl())
      report(D->getLocation(), FD);
    return true;
  }

  bool VisitConceptReference(const ConceptReference *CR) {
    report(CR->getConceptNameLoc(), CR->getFoundDecl());
    return true;
  }

  // Report a reference from explicit specializations to the specialized
  // template. Implicit ones are filtered out by RAV and explicit instantiations
  // are already traversed through typelocs.
  bool
  VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
    if (CTSD->isExplicitSpecialization())
      report(CTSD->getLocation(),
             CTSD->getSpecializedTemplate()->getTemplatedDecl());
    return true;
  }
  bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
    if (VTSD->isExplicitSpecialization())
      report(VTSD->getLocation(),
             VTSD->getSpecializedTemplate()->getTemplatedDecl());
    return true;
  }

  // TypeLoc visitors.
  void reportType(SourceLocation RefLoc, NamedDecl *ND) {
    // Reporting explicit references to types nested inside classes can cause
    // issues, e.g. a type accessed through a derived class shouldn't require
    // inclusion of the base.
    // Hence we report all such references as implicit. The code must spell the
    // outer type-location somewhere, which will trigger an explicit reference
    // and per IWYS, it's that spelling's responsibility to bring in necessary
    // declarations.
    RefType RT = llvm::isa<RecordDecl>(ND->getDeclContext())
                     ? RefType::Implicit
                     : RefType::Explicit;
    return report(RefLoc, ND, RT);
  }

  bool VisitUsingTypeLoc(UsingTypeLoc TL) {
    reportType(TL.getNameLoc(), TL.getFoundDecl());
    return true;
  }

  bool VisitTagTypeLoc(TagTypeLoc TTL) {
    reportType(TTL.getNameLoc(), TTL.getDecl());
    return true;
  }

  bool VisitTypedefTypeLoc(TypedefTypeLoc TTL) {
    reportType(TTL.getNameLoc(), TTL.getTypedefNameDecl());
    return true;
  }

  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
    reportType(TL.getTemplateNameLoc(),
               getMostRelevantTemplatePattern(TL.getTypePtr()));
    return true;
  }

  bool VisitDeducedTemplateSpecializationTypeLoc(
      DeducedTemplateSpecializationTypeLoc TL) {
    reportType(TL.getTemplateNameLoc(),
               getMostRelevantTemplatePattern(TL.getTypePtr()));
    return true;
  }

  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &TL) {
    auto &Arg = TL.getArgument();
    // Template-template parameters require special attention, as there's no
    // TemplateNameLoc.
    if (Arg.getKind() == TemplateArgument::Template ||
        Arg.getKind() == TemplateArgument::TemplateExpansion) {
      report(TL.getLocation(),
             resolveTemplateName(Arg.getAsTemplateOrTemplatePattern()));
      return true;
    }
    return RecursiveASTVisitor::TraverseTemplateArgumentLoc(TL);
  }

  bool VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
    // Reliance on initializer_lists requires std::initializer_list to be
    // visible per standard. So report a reference to it, otherwise include of
    // `<initializer_list>` might not receive any use.
    report(E->getExprLoc(),
           const_cast<CXXRecordDecl *>(E->getBestDynamicClassType()),
           RefType::Implicit);
    return true;
  }
};

} // namespace

void walkAST(Decl &Root, DeclCallback Callback) {
  ASTWalker(Callback).TraverseDecl(&Root);
}

} // namespace clang::include_cleaner
