//===--- StandaloneEmptyCheck.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 "StandaloneEmptyCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"

namespace clang::tidy::bugprone {

using ast_matchers::BoundNodes;
using ast_matchers::callee;
using ast_matchers::callExpr;
using ast_matchers::classTemplateDecl;
using ast_matchers::cxxMemberCallExpr;
using ast_matchers::cxxMethodDecl;
using ast_matchers::expr;
using ast_matchers::functionDecl;
using ast_matchers::hasAncestor;
using ast_matchers::hasName;
using ast_matchers::hasParent;
using ast_matchers::ignoringImplicit;
using ast_matchers::ignoringParenImpCasts;
using ast_matchers::MatchFinder;
using ast_matchers::optionally;
using ast_matchers::returns;
using ast_matchers::stmt;
using ast_matchers::stmtExpr;
using ast_matchers::unless;
using ast_matchers::voidType;

const Expr *getCondition(const BoundNodes &Nodes, const StringRef NodeId) {
  const auto *If = Nodes.getNodeAs<IfStmt>(NodeId);
  if (If != nullptr)
    return If->getCond();

  const auto *For = Nodes.getNodeAs<ForStmt>(NodeId);
  if (For != nullptr)
    return For->getCond();

  const auto *While = Nodes.getNodeAs<WhileStmt>(NodeId);
  if (While != nullptr)
    return While->getCond();

  const auto *Do = Nodes.getNodeAs<DoStmt>(NodeId);
  if (Do != nullptr)
    return Do->getCond();

  const auto *Switch = Nodes.getNodeAs<SwitchStmt>(NodeId);
  if (Switch != nullptr)
    return Switch->getCond();

  return nullptr;
}

void StandaloneEmptyCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
  // Ignore empty calls in a template definition which fall under callExpr
  // non-member matcher even if they are methods.
  const auto NonMemberMatcher = expr(ignoringImplicit(ignoringParenImpCasts(
      callExpr(
          hasParent(stmt(optionally(hasParent(stmtExpr().bind("stexpr"))))
                        .bind("parent")),
          unless(hasAncestor(classTemplateDecl())),
          callee(functionDecl(hasName("empty"), unless(returns(voidType())))))
          .bind("empty"))));
  const auto MemberMatcher =
      expr(ignoringImplicit(ignoringParenImpCasts(cxxMemberCallExpr(
               hasParent(stmt(optionally(hasParent(stmtExpr().bind("stexpr"))))
                             .bind("parent")),
               callee(cxxMethodDecl(hasName("empty"),
                                    unless(returns(voidType()))))))))
          .bind("empty");

  Finder->addMatcher(MemberMatcher, this);
  Finder->addMatcher(NonMemberMatcher, this);
}

void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) {
  // Skip if the parent node is Expr.
  if (Result.Nodes.getNodeAs<Expr>("parent"))
    return;

  const auto PParentStmtExpr = Result.Nodes.getNodeAs<Expr>("stexpr");
  const auto ParentCompStmt = Result.Nodes.getNodeAs<CompoundStmt>("parent");
  const auto *ParentCond = getCondition(Result.Nodes, "parent");
  const auto *ParentReturnStmt = Result.Nodes.getNodeAs<ReturnStmt>("parent");

  if (const auto *MemberCall =
          Result.Nodes.getNodeAs<CXXMemberCallExpr>("empty")) {
    // Skip if it's a condition of the parent statement.
    if (ParentCond == MemberCall->getExprStmt())
      return;
    // Skip if it's the last statement in the GNU extension
    // statement expression.
    if (PParentStmtExpr && ParentCompStmt &&
        ParentCompStmt->body_back() == MemberCall->getExprStmt())
      return;
    // Skip if it's a return statement
    if (ParentReturnStmt)
      return;

    SourceLocation MemberLoc = MemberCall->getBeginLoc();
    SourceLocation ReplacementLoc = MemberCall->getExprLoc();
    SourceRange ReplacementRange = SourceRange(ReplacementLoc, ReplacementLoc);

    ASTContext &Context = MemberCall->getRecordDecl()->getASTContext();
    DeclarationName Name =
        Context.DeclarationNames.getIdentifier(&Context.Idents.get("clear"));

    auto Candidates = MemberCall->getRecordDecl()->lookupDependentName(
        Name, [](const NamedDecl *ND) {
          return isa<CXXMethodDecl>(ND) &&
                 llvm::cast<CXXMethodDecl>(ND)->getMinRequiredArguments() ==
                     0 &&
                 !llvm::cast<CXXMethodDecl>(ND)->isConst();
        });

    bool HasClear = !Candidates.empty();
    if (HasClear) {
      const auto *Clear = llvm::cast<CXXMethodDecl>(Candidates.at(0));
      QualType RangeType = MemberCall->getImplicitObjectArgument()->getType();
      bool QualifierIncompatible =
          (!Clear->isVolatile() && RangeType.isVolatileQualified()) ||
          RangeType.isConstQualified();
      if (!QualifierIncompatible) {
        diag(MemberLoc,
             "ignoring the result of 'empty()'; did you mean 'clear()'? ")
            << FixItHint::CreateReplacement(ReplacementRange, "clear");
        return;
      }
    }

    diag(MemberLoc, "ignoring the result of 'empty()'");

  } else if (const auto *NonMemberCall =
                 Result.Nodes.getNodeAs<CallExpr>("empty")) {
    if (ParentCond == NonMemberCall->getExprStmt())
      return;
    if (PParentStmtExpr && ParentCompStmt &&
        ParentCompStmt->body_back() == NonMemberCall->getExprStmt())
      return;
    if (ParentReturnStmt)
      return;
    if (NonMemberCall->getNumArgs() != 1)
      return;

    SourceLocation NonMemberLoc = NonMemberCall->getExprLoc();
    SourceLocation NonMemberEndLoc = NonMemberCall->getEndLoc();

    const Expr *Arg = NonMemberCall->getArg(0);
    CXXRecordDecl *ArgRecordDecl = Arg->getType()->getAsCXXRecordDecl();
    if (ArgRecordDecl == nullptr)
      return;

    ASTContext &Context = ArgRecordDecl->getASTContext();
    DeclarationName Name =
        Context.DeclarationNames.getIdentifier(&Context.Idents.get("clear"));

    auto Candidates =
        ArgRecordDecl->lookupDependentName(Name, [](const NamedDecl *ND) {
          return isa<CXXMethodDecl>(ND) &&
                 llvm::cast<CXXMethodDecl>(ND)->getMinRequiredArguments() ==
                     0 &&
                 !llvm::cast<CXXMethodDecl>(ND)->isConst();
        });

    bool HasClear = !Candidates.empty();

    if (HasClear) {
      const auto *Clear = llvm::cast<CXXMethodDecl>(Candidates.at(0));
      bool QualifierIncompatible =
          (!Clear->isVolatile() && Arg->getType().isVolatileQualified()) ||
          Arg->getType().isConstQualified();
      if (!QualifierIncompatible) {
        std::string ReplacementText =
            std::string(Lexer::getSourceText(
                CharSourceRange::getTokenRange(Arg->getSourceRange()),
                *Result.SourceManager, getLangOpts())) +
            ".clear()";
        SourceRange ReplacementRange =
            SourceRange(NonMemberLoc, NonMemberEndLoc);
        diag(NonMemberLoc,
             "ignoring the result of '%0'; did you mean 'clear()'?")
            << llvm::dyn_cast<NamedDecl>(NonMemberCall->getCalleeDecl())
                   ->getQualifiedNameAsString()
            << FixItHint::CreateReplacement(ReplacementRange, ReplacementText);
        return;
      }
    }

    diag(NonMemberLoc, "ignoring the result of '%0'")
        << llvm::dyn_cast<NamedDecl>(NonMemberCall->getCalleeDecl())
               ->getQualifiedNameAsString();
  }
}

} // namespace clang::tidy::bugprone
