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

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace readability {

namespace {

AST_MATCHER(Stmt, isMacroExpansion) {
  SourceManager &SM = Finder->getASTContext().getSourceManager();
  SourceLocation Loc = Node.getBeginLoc();
  return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
}

bool isNULLMacroExpansion(const Stmt *Statement, ASTContext &Context) {
  SourceManager &SM = Context.getSourceManager();
  const LangOptions &LO = Context.getLangOpts();
  SourceLocation Loc = Statement->getBeginLoc();
  return SM.isMacroBodyExpansion(Loc) &&
         Lexer::getImmediateMacroName(Loc, SM, LO) == "NULL";
}

AST_MATCHER(Stmt, isNULLMacroExpansion) {
  return isNULLMacroExpansion(&Node, Finder->getASTContext());
}

StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
                                             QualType Type,
                                             ASTContext &Context) {
  switch (CastExprKind) {
  case CK_IntegralToBoolean:
    return Type->isUnsignedIntegerType() ? "0u" : "0";

  case CK_FloatingToBoolean:
    return Context.hasSameType(Type, Context.FloatTy) ? "0.0f" : "0.0";

  case CK_PointerToBoolean:
  case CK_MemberPointerToBoolean: // Fall-through on purpose.
    return Context.getLangOpts().CPlusPlus11 ? "nullptr" : "0";

  default:
    llvm_unreachable("Unexpected cast kind");
  }
}

bool isUnaryLogicalNotOperator(const Stmt *Statement) {
  const auto *UnaryOperatorExpr = dyn_cast<UnaryOperator>(Statement);
  return UnaryOperatorExpr && UnaryOperatorExpr->getOpcode() == UO_LNot;
}

bool areParensNeededForOverloadedOperator(OverloadedOperatorKind OperatorKind) {
  switch (OperatorKind) {
  case OO_New:
  case OO_Delete: // Fall-through on purpose.
  case OO_Array_New:
  case OO_Array_Delete:
  case OO_ArrowStar:
  case OO_Arrow:
  case OO_Call:
  case OO_Subscript:
    return false;

  default:
    return true;
  }
}

bool areParensNeededForStatement(const Stmt *Statement) {
  if (const auto *OperatorCall = dyn_cast<CXXOperatorCallExpr>(Statement)) {
    return areParensNeededForOverloadedOperator(OperatorCall->getOperator());
  }

  return isa<BinaryOperator>(Statement) || isa<UnaryOperator>(Statement);
}

void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
                              const ImplicitCastExpr *Cast, const Stmt *Parent,
                              ASTContext &Context) {
  // In case of expressions like (! integer), we should remove the redundant not
  // operator and use inverted comparison (integer == 0).
  bool InvertComparison =
      Parent != nullptr && isUnaryLogicalNotOperator(Parent);
  if (InvertComparison) {
    SourceLocation ParentStartLoc = Parent->getBeginLoc();
    SourceLocation ParentEndLoc =
        cast<UnaryOperator>(Parent)->getSubExpr()->getBeginLoc();
    Diag << FixItHint::CreateRemoval(
        CharSourceRange::getCharRange(ParentStartLoc, ParentEndLoc));

    Parent = Context.getParents(*Parent)[0].get<Stmt>();
  }

  const Expr *SubExpr = Cast->getSubExpr();

  bool NeedInnerParens = areParensNeededForStatement(SubExpr);
  bool NeedOuterParens =
      Parent != nullptr && areParensNeededForStatement(Parent);

  std::string StartLocInsertion;

  if (NeedOuterParens) {
    StartLocInsertion += "(";
  }
  if (NeedInnerParens) {
    StartLocInsertion += "(";
  }

  if (!StartLocInsertion.empty()) {
    Diag << FixItHint::CreateInsertion(Cast->getBeginLoc(), StartLocInsertion);
  }

  std::string EndLocInsertion;

  if (NeedInnerParens) {
    EndLocInsertion += ")";
  }

  if (InvertComparison) {
    EndLocInsertion += " == ";
  } else {
    EndLocInsertion += " != ";
  }

  EndLocInsertion += getZeroLiteralToCompareWithForType(
      Cast->getCastKind(), SubExpr->getType(), Context);

  if (NeedOuterParens) {
    EndLocInsertion += ")";
  }

  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
      Cast->getEndLoc(), 0, Context.getSourceManager(), Context.getLangOpts());
  Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
}

StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
                                          ASTContext &Context) {
  if (isNULLMacroExpansion(Expression, Context)) {
    return "false";
  }

  if (const auto *IntLit = dyn_cast<IntegerLiteral>(Expression)) {
    return (IntLit->getValue() == 0) ? "false" : "true";
  }

  if (const auto *FloatLit = dyn_cast<FloatingLiteral>(Expression)) {
    llvm::APFloat FloatLitAbsValue = FloatLit->getValue();
    FloatLitAbsValue.clearSign();
    return (FloatLitAbsValue.bitcastToAPInt() == 0) ? "false" : "true";
  }

  if (const auto *CharLit = dyn_cast<CharacterLiteral>(Expression)) {
    return (CharLit->getValue() == 0) ? "false" : "true";
  }

  if (isa<StringLiteral>(Expression->IgnoreCasts())) {
    return "true";
  }

  return StringRef();
}

void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
                                const ImplicitCastExpr *Cast,
                                ASTContext &Context, StringRef OtherType) {
  const Expr *SubExpr = Cast->getSubExpr();
  bool NeedParens = !isa<ParenExpr>(SubExpr);

  Diag << FixItHint::CreateInsertion(
      Cast->getBeginLoc(),
      (Twine("static_cast<") + OtherType + ">" + (NeedParens ? "(" : ""))
          .str());

  if (NeedParens) {
    SourceLocation EndLoc = Lexer::getLocForEndOfToken(
        Cast->getEndLoc(), 0, Context.getSourceManager(),
        Context.getLangOpts());

    Diag << FixItHint::CreateInsertion(EndLoc, ")");
  }
}

StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
                                      QualType DestType, ASTContext &Context) {
  // Prior to C++11, false literal could be implicitly converted to pointer.
  if (!Context.getLangOpts().CPlusPlus11 &&
      (DestType->isPointerType() || DestType->isMemberPointerType()) &&
      BoolLiteral->getValue() == false) {
    return "0";
  }

  if (DestType->isFloatingType()) {
    if (Context.hasSameType(DestType, Context.FloatTy)) {
      return BoolLiteral->getValue() ? "1.0f" : "0.0f";
    }
    return BoolLiteral->getValue() ? "1.0" : "0.0";
  }

  if (DestType->isUnsignedIntegerType()) {
    return BoolLiteral->getValue() ? "1u" : "0u";
  }
  return BoolLiteral->getValue() ? "1" : "0";
}

bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
                              ASTContext &Context) {
  std::queue<const Stmt *> Q;
  Q.push(Cast);

  TraversalKindScope RAII(Context, TK_AsIs);

  while (!Q.empty()) {
    for (const auto &N : Context.getParents(*Q.front())) {
      const Stmt *S = N.get<Stmt>();
      if (!S)
        return false;
      if (isa<IfStmt>(S) || isa<ConditionalOperator>(S) || isa<ForStmt>(S) ||
          isa<WhileStmt>(S) || isa<BinaryConditionalOperator>(S))
        return true;
      if (isa<ParenExpr>(S) || isa<ImplicitCastExpr>(S) ||
          isUnaryLogicalNotOperator(S) ||
          (isa<BinaryOperator>(S) && cast<BinaryOperator>(S)->isLogicalOp())) {
        Q.push(S);
      } else {
        return false;
      }
    }
    Q.pop();
  }
  return false;
}

} // anonymous namespace

ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
      AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}

void ImplicitBoolConversionCheck::storeOptions(
    ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
  Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
}

void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
  auto ExceptionCases =
      expr(anyOf(allOf(isMacroExpansion(), unless(isNULLMacroExpansion())),
                 has(ignoringImplicit(
                     memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1)))))),
                 hasParent(explicitCastExpr())));
  auto ImplicitCastFromBool = implicitCastExpr(
      anyOf(hasCastKind(CK_IntegralCast), hasCastKind(CK_IntegralToFloating),
            // Prior to C++11 cast from bool literal to pointer was allowed.
            allOf(anyOf(hasCastKind(CK_NullToPointer),
                        hasCastKind(CK_NullToMemberPointer)),
                  hasSourceExpression(cxxBoolLiteral()))),
      hasSourceExpression(expr(hasType(booleanType()))),
      unless(ExceptionCases));
  auto BoolXor =
      binaryOperator(hasOperatorName("^"), hasLHS(ImplicitCastFromBool),
                     hasRHS(ImplicitCastFromBool));
  Finder->addMatcher(
      traverse(TK_AsIs,
               implicitCastExpr(
                   anyOf(hasCastKind(CK_IntegralToBoolean),
                         hasCastKind(CK_FloatingToBoolean),
                         hasCastKind(CK_PointerToBoolean),
                         hasCastKind(CK_MemberPointerToBoolean)),
                   // Exclude case of using if or while statements with variable
                   // declaration, e.g.:
                   //   if (int var = functionCall()) {}
                   unless(hasParent(
                       stmt(anyOf(ifStmt(), whileStmt()), has(declStmt())))),
                   // Exclude cases common to implicit cast to and from bool.
                   unless(ExceptionCases), unless(has(BoolXor)),
                   // Retrieve also parent statement, to check if we need
                   // additional parens in replacement.
                   anyOf(hasParent(stmt().bind("parentStmt")), anything()),
                   unless(isInTemplateInstantiation()),
                   unless(hasAncestor(functionTemplateDecl())))
                   .bind("implicitCastToBool")),
      this);

  auto BoolComparison = binaryOperator(hasAnyOperatorName("==", "!="),
                                       hasLHS(ImplicitCastFromBool),
                                       hasRHS(ImplicitCastFromBool));
  auto BoolOpAssignment = binaryOperator(hasAnyOperatorName("|=", "&="),
                                         hasLHS(expr(hasType(booleanType()))));
  auto BitfieldAssignment = binaryOperator(
      hasLHS(memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1))))));
  auto BitfieldConstruct = cxxConstructorDecl(hasDescendant(cxxCtorInitializer(
      withInitializer(equalsBoundNode("implicitCastFromBool")),
      forField(hasBitWidth(1)))));
  Finder->addMatcher(
      traverse(
          TK_AsIs,
          implicitCastExpr(
              ImplicitCastFromBool,
              // Exclude comparisons of bools, as they are always cast to
              // integers in such context:
              //   bool_expr_a == bool_expr_b
              //   bool_expr_a != bool_expr_b
              unless(hasParent(
                  binaryOperator(anyOf(BoolComparison, BoolXor,
                                       BoolOpAssignment, BitfieldAssignment)))),
              implicitCastExpr().bind("implicitCastFromBool"),
              unless(hasParent(BitfieldConstruct)),
              // Check also for nested casts, for example: bool -> int -> float.
              anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")),
                    anything()),
              unless(isInTemplateInstantiation()),
              unless(hasAncestor(functionTemplateDecl())))),
      this);
}

void ImplicitBoolConversionCheck::check(
    const MatchFinder::MatchResult &Result) {

  if (const auto *CastToBool =
          Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
    const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
    return handleCastToBool(CastToBool, Parent, *Result.Context);
  }

  if (const auto *CastFromBool =
          Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastFromBool")) {
    const auto *NextImplicitCast =
        Result.Nodes.getNodeAs<ImplicitCastExpr>("furtherImplicitCast");
    return handleCastFromBool(CastFromBool, NextImplicitCast, *Result.Context);
  }
}

void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
                                                   const Stmt *Parent,
                                                   ASTContext &Context) {
  if (AllowPointerConditions &&
      (Cast->getCastKind() == CK_PointerToBoolean ||
       Cast->getCastKind() == CK_MemberPointerToBoolean) &&
      isCastAllowedInCondition(Cast, Context)) {
    return;
  }

  if (AllowIntegerConditions && Cast->getCastKind() == CK_IntegralToBoolean &&
      isCastAllowedInCondition(Cast, Context)) {
    return;
  }

  auto Diag = diag(Cast->getBeginLoc(), "implicit conversion %0 -> bool")
              << Cast->getSubExpr()->getType();

  StringRef EquivalentLiteral =
      getEquivalentBoolLiteralForExpr(Cast->getSubExpr(), Context);
  if (!EquivalentLiteral.empty()) {
    Diag << tooling::fixit::createReplacement(*Cast, EquivalentLiteral);
  } else {
    fixGenericExprCastToBool(Diag, Cast, Parent, Context);
  }
}

void ImplicitBoolConversionCheck::handleCastFromBool(
    const ImplicitCastExpr *Cast, const ImplicitCastExpr *NextImplicitCast,
    ASTContext &Context) {
  QualType DestType =
      NextImplicitCast ? NextImplicitCast->getType() : Cast->getType();
  auto Diag = diag(Cast->getBeginLoc(), "implicit conversion bool -> %0")
              << DestType;

  if (const auto *BoolLiteral =
          dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr())) {
    Diag << tooling::fixit::createReplacement(
        *Cast, getEquivalentForBoolLiteral(BoolLiteral, DestType, Context));
  } else {
    fixGenericExprCastFromBool(Diag, Cast, Context, DestType.getAsString());
  }
}

} // namespace readability
} // namespace tidy
} // namespace clang
