//===--- UseEqualsDefaultCheck.cpp - clang-tidy----------------------------===//
//
// 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 "UseEqualsDefaultCheck.h"
#include "../utils/LexerUtils.h"
#include "../utils/Matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include <optional>

using namespace clang::ast_matchers;

namespace clang::tidy::modernize {

static const char SpecialFunction[] = "SpecialFunction";

/// Finds all the named non-static fields of \p Record.
static std::set<const FieldDecl *>
getAllNamedFields(const CXXRecordDecl *Record) {
  std::set<const FieldDecl *> Result;
  for (const auto *Field : Record->fields()) {
    // Static data members are not in this range.
    if (Field->isUnnamedBitField())
      continue;
    Result.insert(Field);
  }
  return Result;
}

/// Returns the names of the direct bases of \p Record, both virtual and
/// non-virtual.
static std::set<const Type *> getAllDirectBases(const CXXRecordDecl *Record) {
  std::set<const Type *> Result;
  for (auto Base : Record->bases()) {
    // CXXBaseSpecifier.
    const auto *BaseType = Base.getTypeSourceInfo()->getType().getTypePtr();
    Result.insert(BaseType);
  }
  return Result;
}

/// Returns a matcher that matches member expressions where the base is
/// the variable declared as \p Var and the accessed member is the one declared
/// as \p Field.
static internal::Matcher<Expr> accessToFieldInVar(const FieldDecl *Field,
                                                  const ValueDecl *Var) {
  return ignoringImpCasts(
      memberExpr(hasObjectExpression(declRefExpr(to(varDecl(equalsNode(Var))))),
                 member(fieldDecl(equalsNode(Field)))));
}

/// Check that the given constructor has copy signature and that it
/// copy-initializes all its bases and members.
static bool isCopyConstructorAndCanBeDefaulted(ASTContext *Context,
                                               const CXXConstructorDecl *Ctor) {
  // An explicitly-defaulted constructor cannot have default arguments.
  if (Ctor->getMinRequiredArguments() != 1)
    return false;

  const auto *Record = Ctor->getParent();
  const auto *Param = Ctor->getParamDecl(0);

  // Base classes and members that have to be copied.
  auto BasesToInit = getAllDirectBases(Record);
  auto FieldsToInit = getAllNamedFields(Record);

  // Ensure that all the bases are copied.
  for (const auto *Base : BasesToInit) {
    // The initialization of a base class should be a call to a copy
    // constructor of the base.
    if (match(
            traverse(TK_AsIs,
                     cxxConstructorDecl(
                         forEachConstructorInitializer(cxxCtorInitializer(
                             isBaseInitializer(),
                             withInitializer(cxxConstructExpr(
                                 hasType(equalsNode(Base)),
                                 hasDeclaration(
                                     cxxConstructorDecl(isCopyConstructor())),
                                 argumentCountIs(1),
                                 hasArgument(0, declRefExpr(to(varDecl(
                                                    equalsNode(Param))))))))))),
            *Ctor, *Context)
            .empty())
      return false;
  }

  // Ensure that all the members are copied.
  for (const auto *Field : FieldsToInit) {
    auto AccessToFieldInParam = accessToFieldInVar(Field, Param);
    // The initialization is a CXXConstructExpr for class types.
    if (match(traverse(
                  TK_AsIs,
                  cxxConstructorDecl(
                      forEachConstructorInitializer(cxxCtorInitializer(
                          isMemberInitializer(), forField(equalsNode(Field)),
                          withInitializer(anyOf(
                              AccessToFieldInParam,
                              initListExpr(has(AccessToFieldInParam)),
                              cxxConstructExpr(
                                  hasDeclaration(
                                      cxxConstructorDecl(isCopyConstructor())),
                                  argumentCountIs(1),
                                  hasArgument(0, AccessToFieldInParam)))))))),
              *Ctor, *Context)
            .empty())
      return false;
  }

  // Ensure that we don't do anything else, like initializing an indirect base.
  return Ctor->getNumCtorInitializers() ==
         BasesToInit.size() + FieldsToInit.size();
}

/// Checks that the given method is an overloading of the assignment
/// operator, has copy signature, returns a reference to "*this" and copies
/// all its members and subobjects.
static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context,
                                              const CXXMethodDecl *Operator) {
  const auto *Record = Operator->getParent();
  const auto *Param = Operator->getParamDecl(0);

  // Base classes and members that have to be copied.
  auto BasesToInit = getAllDirectBases(Record);
  auto FieldsToInit = getAllNamedFields(Record);

  const auto *Compound = cast<CompoundStmt>(Operator->getBody());

  // The assignment operator definition has to end with the following return
  // statement:
  //   return *this;
  if (Compound->body_empty() ||
      match(traverse(
                TK_AsIs,
                returnStmt(has(ignoringParenImpCasts(unaryOperator(
                    hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())))))),
            *Compound->body_back(), *Context)
          .empty())
    return false;

  // Ensure that all the bases are copied.
  for (const auto *Base : BasesToInit) {
    // Assignment operator of a base class:
    //   Base::operator=(Other);
    //
    // Clang translates this into:
    //   ((Base*)this)->operator=((Base)Other);
    //
    // So we are looking for a member call that fulfills:
    if (match(traverse(
                  TK_AsIs,
                  compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr(
                      // - The object is an implicit cast of 'this' to a
                      // pointer to
                      //   a base class.
                      onImplicitObjectArgument(implicitCastExpr(
                          hasImplicitDestinationType(hasCanonicalType(pointsTo(
                              type(equalsNode(Base->getCanonicalTypeInternal()
                                                  .getTypePtr()))))),
                          hasSourceExpression(cxxThisExpr()))),
                      // - The called method is the operator=.
                      callee(cxxMethodDecl(isCopyAssignmentOperator())),
                      // - The argument is (an implicit cast to a Base of)
                      // the argument taken by "Operator".
                      argumentCountIs(1),
                      hasArgument(
                          0, declRefExpr(to(varDecl(equalsNode(Param)))))))))),
              *Compound, *Context)
            .empty())
      return false;
  }

  // Ensure that all the members are copied.
  for (const auto *Field : FieldsToInit) {
    // The assignment of data members:
    //   Field = Other.Field;
    // Is a BinaryOperator in non-class types, and a CXXOperatorCallExpr
    // otherwise.
    auto LHS = memberExpr(hasObjectExpression(cxxThisExpr()),
                          member(fieldDecl(equalsNode(Field))));
    auto RHS = accessToFieldInVar(Field, Param);
    if (match(traverse(TK_AsIs,
                       compoundStmt(has(ignoringParenImpCasts(binaryOperation(
                           hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)))))),
              *Compound, *Context)
            .empty())
      return false;
  }

  // Ensure that we don't do anything else.
  return Compound->size() == BasesToInit.size() + FieldsToInit.size() + 1;
}

/// Returns false if the body has any non-whitespace character.
static bool bodyEmpty(const ASTContext *Context, const CompoundStmt *Body) {
  bool Invalid = false;
  StringRef Text = Lexer::getSourceText(
      CharSourceRange::getCharRange(Body->getLBracLoc().getLocWithOffset(1),
                                    Body->getRBracLoc()),
      Context->getSourceManager(), Context->getLangOpts(), &Invalid);
  return !Invalid && std::strspn(Text.data(), " \t\r\n") == Text.size();
}

UseEqualsDefaultCheck::UseEqualsDefaultCheck(StringRef Name,
                                             ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      IgnoreMacros(Options.get("IgnoreMacros", true)) {}

void UseEqualsDefaultCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "IgnoreMacros", IgnoreMacros);
}

namespace {
AST_MATCHER(CXXMethodDecl, isOutOfLine) { return Node.isOutOfLine(); }
} // namespace

void UseEqualsDefaultCheck::registerMatchers(MatchFinder *Finder) {
  // Skip unions/union-like classes since their constructors behave differently
  // when defaulted vs. empty.
  auto IsUnionLikeClass = recordDecl(
      anyOf(isUnion(),
            has(fieldDecl(isImplicit(), hasType(cxxRecordDecl(isUnion()))))));

  const LangOptions &LangOpts = getLangOpts();
  auto IsPublicOrOutOfLineUntilCPP20 =
      LangOpts.CPlusPlus20
          ? cxxConstructorDecl()
          : cxxConstructorDecl(anyOf(isOutOfLine(), isPublic()));

  // Destructor.
  Finder->addMatcher(
      cxxDestructorDecl(isDefinition(), unless(ofClass(IsUnionLikeClass)))
          .bind(SpecialFunction),
      this);
  // Constructor.
  Finder->addMatcher(
      cxxConstructorDecl(
          isDefinition(), unless(ofClass(IsUnionLikeClass)),
          unless(hasParent(functionTemplateDecl())),
          anyOf(
              // Default constructor.
              allOf(parameterCountIs(0),
                    unless(hasAnyConstructorInitializer(isWritten())),
                    unless(isVariadic()), IsPublicOrOutOfLineUntilCPP20),
              // Copy constructor.
              allOf(isCopyConstructor(),
                    // Discard constructors that can be used as a copy
                    // constructor because all the other arguments have
                    // default values.
                    parameterCountIs(1))))
          .bind(SpecialFunction),
      this);
  // Copy-assignment operator.
  Finder->addMatcher(
      cxxMethodDecl(isDefinition(), isCopyAssignmentOperator(),
                    unless(ofClass(IsUnionLikeClass)),
                    unless(hasParent(functionTemplateDecl())),
                    // isCopyAssignmentOperator() allows the parameter to be
                    // passed by value, and in this case it cannot be
                    // defaulted.
                    hasParameter(0, hasType(lValueReferenceType())),
                    // isCopyAssignmentOperator() allows non lvalue reference
                    // return types, and in this case it cannot be defaulted.
                    returns(qualType(hasCanonicalType(
                        allOf(lValueReferenceType(pointee(type())),
                              unless(matchers::isReferenceToConst()))))))
          .bind(SpecialFunction),
      this);
}

void UseEqualsDefaultCheck::check(const MatchFinder::MatchResult &Result) {
  // Both CXXConstructorDecl and CXXDestructorDecl inherit from CXXMethodDecl.
  const auto *SpecialFunctionDecl =
      Result.Nodes.getNodeAs<CXXMethodDecl>(SpecialFunction);

  if (IgnoreMacros && SpecialFunctionDecl->getLocation().isMacroID())
    return;

  // Discard explicitly deleted/defaulted special member functions and those
  // that are not user-provided (automatically generated).
  if (SpecialFunctionDecl->isDeleted() ||
      SpecialFunctionDecl->isExplicitlyDefaulted() ||
      SpecialFunctionDecl->isLateTemplateParsed() ||
      SpecialFunctionDecl->isTemplateInstantiation() ||
      !SpecialFunctionDecl->isUserProvided() || !SpecialFunctionDecl->hasBody())
    return;

  const auto *Body = dyn_cast<CompoundStmt>(SpecialFunctionDecl->getBody());
  if (!Body)
    return;

  // If there is code inside the body, don't warn.
  if (!SpecialFunctionDecl->isCopyAssignmentOperator() && !Body->body_empty())
    return;

  // If body contain any preprocesor derictives, don't warn.
  if (IgnoreMacros && utils::lexer::rangeContainsExpansionsOrDirectives(
                          Body->getSourceRange(), *Result.SourceManager,
                          Result.Context->getLangOpts()))
    return;

  // If there are comments inside the body, don't do the change.
  bool ApplyFix = SpecialFunctionDecl->isCopyAssignmentOperator() ||
                  bodyEmpty(Result.Context, Body);

  std::vector<FixItHint> RemoveInitializers;
  unsigned MemberType = 0;
  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(SpecialFunctionDecl)) {
    if (Ctor->getNumParams() == 0) {
      MemberType = 0;
    } else {
      if (!isCopyConstructorAndCanBeDefaulted(Result.Context, Ctor))
        return;
      MemberType = 1;
      // If there are constructor initializers, they must be removed.
      for (const auto *Init : Ctor->inits()) {
        RemoveInitializers.emplace_back(
            FixItHint::CreateRemoval(Init->getSourceRange()));
      }
    }
  } else if (isa<CXXDestructorDecl>(SpecialFunctionDecl)) {
    MemberType = 2;
  } else {
    if (!isCopyAssignmentAndCanBeDefaulted(Result.Context, SpecialFunctionDecl))
      return;
    MemberType = 3;
  }

  // The location of the body is more useful inside a macro as spelling and
  // expansion locations are reported.
  SourceLocation Location = SpecialFunctionDecl->getLocation();
  if (Location.isMacroID())
    Location = Body->getBeginLoc();

  auto Diag = diag(
      Location,
      "use '= default' to define a trivial %select{default constructor|copy "
      "constructor|destructor|copy-assignment operator}0");
  Diag << MemberType;

  if (ApplyFix) {
    SourceLocation UnifiedEnd = utils::lexer::getUnifiedEndLoc(
        *Body, Result.Context->getSourceManager(),
        Result.Context->getLangOpts());
    // Skipping comments, check for a semicolon after Body->getSourceRange()
    std::optional<Token> Token = utils::lexer::findNextTokenSkippingComments(
        UnifiedEnd, Result.Context->getSourceManager(),
        Result.Context->getLangOpts());
    StringRef Replacement =
        Token && Token->is(tok::semi) ? "= default" : "= default;";
    Diag << FixItHint::CreateReplacement(Body->getSourceRange(), Replacement)
         << RemoveInitializers;
  }
}

} // namespace clang::tidy::modernize
