//===--- 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 "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace 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.
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(
            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(
            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(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(
            compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr(
                // - The object is an implicit cast of 'this' to a pointer to
                //   a base class.
                onImplicitObjectArgument(
                    implicitCastExpr(hasImplicitDestinationType(
                                         pointsTo(type(equalsNode(Base)))),
                                     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(
            compoundStmt(has(ignoringParenImpCasts(stmt(anyOf(
                binaryOperator(hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)),
                cxxOperatorCallExpr(hasOverloadedOperatorName("="),
                                    argumentCountIs(2), hasArgument(0, LHS),
                                    hasArgument(1, 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.getLocalOrGlobal("IgnoreMacros", true) != 0) {}

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

void UseEqualsDefaultCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  // Destructor.
  Finder->addMatcher(cxxDestructorDecl(isDefinition()).bind(SpecialFunction),
                     this);
  Finder->addMatcher(
      cxxConstructorDecl(
          isDefinition(),
          anyOf(
              // Default constructor.
              allOf(unless(hasAnyConstructorInitializer(isWritten())),
                    parameterCountIs(0)),
              // 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(),
                    // isCopyAssignmentOperator() allows the parameter to be
                    // passed by value, and in this case it cannot be
                    // defaulted.
                    hasParameter(0, hasType(lValueReferenceType())))
          .bind(SpecialFunction),
      this);
}

void UseEqualsDefaultCheck::check(const MatchFinder::MatchResult &Result) {
  std::string SpecialFunctionName;

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

  std::vector<FixItHint> RemoveInitializers;

  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(SpecialFunctionDecl)) {
    if (Ctor->getNumParams() == 0) {
      SpecialFunctionName = "default constructor";
    } else {
      if (!isCopyConstructorAndCanBeDefaulted(Result.Context, Ctor))
        return;
      SpecialFunctionName = "copy constructor";
      // 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)) {
    SpecialFunctionName = "destructor";
  } else {
    if (!isCopyAssignmentAndCanBeDefaulted(Result.Context, SpecialFunctionDecl))
      return;
    SpecialFunctionName = "copy-assignment operator";
  }

  // 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 " +
                                 SpecialFunctionName);

  if (ApplyFix)
    Diag << FixItHint::CreateReplacement(Body->getSourceRange(), "= default;")
         << RemoveInitializers;
}

} // namespace modernize
} // namespace tidy
} // namespace clang
