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

using namespace clang::ast_matchers;
using namespace clang::ast_matchers::internal;

namespace clang {
namespace tidy {
namespace bugprone {

static constexpr int UnsignedASCIIUpperBound = 127;

static Matcher<TypedefDecl> hasAnyListedName(const std::string &Names) {
  const std::vector<std::string> NameList =
      utils::options::parseStringList(Names);
  return hasAnyName(std::vector<StringRef>(NameList.begin(), NameList.end()));
}

SignedCharMisuseCheck::SignedCharMisuseCheck(StringRef Name,
                                             ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      CharTypdefsToIgnoreList(Options.get("CharTypdefsToIgnore", "")),
      DiagnoseSignedUnsignedCharComparisons(
          Options.get("DiagnoseSignedUnsignedCharComparisons", true)) {}

void SignedCharMisuseCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "CharTypdefsToIgnore", CharTypdefsToIgnoreList);
  Options.store(Opts, "DiagnoseSignedUnsignedCharComparisons",
                DiagnoseSignedUnsignedCharComparisons);
}

// Create a matcher for char -> integer cast.
BindableMatcher<clang::Stmt> SignedCharMisuseCheck::charCastExpression(
    bool IsSigned, const Matcher<clang::QualType> &IntegerType,
    const std::string &CastBindName) const {
  // We can ignore typedefs which are some kind of integer types
  // (e.g. typedef char sal_Int8). In this case, we don't need to
  // worry about the misinterpretation of char values.
  const auto IntTypedef = qualType(
      hasDeclaration(typedefDecl(hasAnyListedName(CharTypdefsToIgnoreList))));

  auto CharTypeExpr = expr();
  if (IsSigned) {
    CharTypeExpr = expr(hasType(
        qualType(isAnyCharacter(), isSignedInteger(), unless(IntTypedef))));
  } else {
    CharTypeExpr = expr(hasType(qualType(
        isAnyCharacter(), unless(isSignedInteger()), unless(IntTypedef))));
  }

  const auto ImplicitCastExpr =
      implicitCastExpr(hasSourceExpression(CharTypeExpr),
                       hasImplicitDestinationType(IntegerType))
          .bind(CastBindName);

  const auto CStyleCastExpr = cStyleCastExpr(has(ImplicitCastExpr));
  const auto StaticCastExpr = cxxStaticCastExpr(has(ImplicitCastExpr));
  const auto FunctionalCastExpr = cxxFunctionalCastExpr(has(ImplicitCastExpr));

  // We catch any type of casts to an integer. We need to have these cast
  // expressions explicitly to catch only those casts which are direct children
  // of the checked expressions. (e.g. assignment, declaration).
  return traverse(TK_AsIs, expr(anyOf(ImplicitCastExpr, CStyleCastExpr,
                                      StaticCastExpr, FunctionalCastExpr)));
}

void SignedCharMisuseCheck::registerMatchers(MatchFinder *Finder) {
  const auto IntegerType =
      qualType(isInteger(), unless(isAnyCharacter()), unless(booleanType()))
          .bind("integerType");
  const auto SignedCharCastExpr =
      charCastExpression(true, IntegerType, "signedCastExpression");
  const auto UnSignedCharCastExpr =
      charCastExpression(false, IntegerType, "unsignedCastExpression");

  // Catch assignments with signed char -> integer conversion.
  const auto AssignmentOperatorExpr =
      expr(binaryOperator(hasOperatorName("="), hasLHS(hasType(IntegerType)),
                          hasRHS(SignedCharCastExpr)));

  Finder->addMatcher(AssignmentOperatorExpr, this);

  // Catch declarations with signed char -> integer conversion.
  const auto Declaration = varDecl(isDefinition(), hasType(IntegerType),
                                   hasInitializer(SignedCharCastExpr));

  Finder->addMatcher(Declaration, this);

  if (DiagnoseSignedUnsignedCharComparisons) {
    // Catch signed char/unsigned char comparison.
    const auto CompareOperator =
        expr(binaryOperator(hasAnyOperatorName("==", "!="),
                            anyOf(allOf(hasLHS(SignedCharCastExpr),
                                        hasRHS(UnSignedCharCastExpr)),
                                  allOf(hasLHS(UnSignedCharCastExpr),
                                        hasRHS(SignedCharCastExpr)))))
            .bind("comparison");

    Finder->addMatcher(CompareOperator, this);
  }

  // Catch array subscripts with signed char -> integer conversion.
  // Matcher for C arrays.
  const auto CArraySubscript =
      arraySubscriptExpr(hasIndex(SignedCharCastExpr)).bind("arraySubscript");

  Finder->addMatcher(CArraySubscript, this);

  // Matcher for std arrays.
  const auto STDArraySubscript =
      cxxOperatorCallExpr(
          hasOverloadedOperatorName("[]"),
          hasArgument(0, hasType(cxxRecordDecl(hasName("::std::array")))),
          hasArgument(1, SignedCharCastExpr))
          .bind("arraySubscript");

  Finder->addMatcher(STDArraySubscript, this);
}

void SignedCharMisuseCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *SignedCastExpression =
      Result.Nodes.getNodeAs<ImplicitCastExpr>("signedCastExpression");
  const auto *IntegerType = Result.Nodes.getNodeAs<QualType>("integerType");
  assert(SignedCastExpression);
  assert(IntegerType);

  // Ignore the match if we know that the signed char's value is not negative.
  // The potential misinterpretation happens for negative values only.
  Expr::EvalResult EVResult;
  if (!SignedCastExpression->isValueDependent() &&
      SignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult,
                                                        *Result.Context)) {
    llvm::APSInt Value = EVResult.Val.getInt();
    if (Value.isNonNegative())
      return;
  }

  if (const auto *Comparison = Result.Nodes.getNodeAs<Expr>("comparison")) {
    const auto *UnSignedCastExpression =
        Result.Nodes.getNodeAs<ImplicitCastExpr>("unsignedCastExpression");

    // We can ignore the ASCII value range also for unsigned char.
    Expr::EvalResult EVResult;
    if (!UnSignedCastExpression->isValueDependent() &&
        UnSignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult,
                                                            *Result.Context)) {
      llvm::APSInt Value = EVResult.Val.getInt();
      if (Value <= UnsignedASCIIUpperBound)
        return;
    }

    diag(Comparison->getBeginLoc(),
         "comparison between 'signed char' and 'unsigned char'");
  } else if (Result.Nodes.getNodeAs<Expr>("arraySubscript")) {
    diag(SignedCastExpression->getBeginLoc(),
         "'signed char' to %0 conversion in array subscript; "
         "consider casting to 'unsigned char' first.")
        << *IntegerType;
  } else {
    diag(SignedCastExpression->getBeginLoc(),
         "'signed char' to %0 conversion; "
         "consider casting to 'unsigned char' first.")
        << *IntegerType;
  }
}

} // namespace bugprone
} // namespace tidy
} // namespace clang
