//===--- NarrowingConversionsCheck.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 "NarrowingConversionsCheck.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"

#include <cstdint>

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace cppcoreguidelines {

NarrowingConversionsCheck::NarrowingConversionsCheck(StringRef Name,
                                                     ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      WarnOnIntegerNarrowingConversion(
          Options.get("WarnOnIntegerNarrowingConversion", true)),
      WarnOnIntegerToFloatingPointNarrowingConversion(
          Options.get("WarnOnIntegerToFloatingPointNarrowingConversion", true)),
      WarnOnFloatingPointNarrowingConversion(
          Options.get("WarnOnFloatingPointNarrowingConversion", true)),
      WarnWithinTemplateInstantiation(
          Options.get("WarnWithinTemplateInstantiation", false)),
      WarnOnEquivalentBitWidth(Options.get("WarnOnEquivalentBitWidth", true)),
      IgnoreConversionFromTypes(Options.get("IgnoreConversionFromTypes", "")),
      PedanticMode(Options.get("PedanticMode", false)) {}

void NarrowingConversionsCheck::storeOptions(
    ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "WarnOnIntegerNarrowingConversion",
                WarnOnIntegerNarrowingConversion);
  Options.store(Opts, "WarnOnIntegerToFloatingPointNarrowingConversion",
                WarnOnIntegerToFloatingPointNarrowingConversion);
  Options.store(Opts, "WarnOnFloatingPointNarrowingConversion",
                WarnOnFloatingPointNarrowingConversion);
  Options.store(Opts, "WarnWithinTemplateInstantiation",
                WarnWithinTemplateInstantiation);
  Options.store(Opts, "WarnOnEquivalentBitWidth", WarnOnEquivalentBitWidth);
  Options.store(Opts, "IgnoreConversionFromTypes", IgnoreConversionFromTypes);
  Options.store(Opts, "PedanticMode", PedanticMode);
}

AST_MATCHER(FieldDecl, hasIntBitwidth) {
  assert(Node.isBitField());
  const ASTContext &Ctx = Node.getASTContext();
  unsigned IntBitWidth = Ctx.getIntWidth(Ctx.IntTy);
  unsigned CurrentBitWidth = Node.getBitWidthValue(Ctx);
  return IntBitWidth == CurrentBitWidth;
}

void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) {
  // ceil() and floor() are guaranteed to return integers, even though the type
  // is not integral.
  const auto IsCeilFloorCallExpr = expr(callExpr(callee(functionDecl(
      hasAnyName("::ceil", "::std::ceil", "::floor", "::std::floor")))));

  // We may want to exclude other types from the checks, such as `size_type`
  // and `difference_type`. These are often used to count elements, represented
  // in 64 bits and assigned to `int`. Rarely are people counting >2B elements.
  const auto IsConversionFromIgnoredType = hasType(namedDecl(
      hasAnyName(utils::options::parseStringList(IgnoreConversionFromTypes))));

  // `IsConversionFromIgnoredType` will ignore narrowing calls from those types,
  // but not expressions that are promoted to an ignored type as a result of a
  // binary expression with one of those types.
  // For example, it will continue to reject:
  // `int narrowed = int_value + container.size()`.
  // We attempt to address common incidents of compound expressions with
  // `IsIgnoredTypeTwoLevelsDeep`, allowing binary expressions that have one
  // operand of the ignored types and the other operand of another integer type.
  const auto IsIgnoredTypeTwoLevelsDeep =
      anyOf(IsConversionFromIgnoredType,
            binaryOperator(hasOperands(IsConversionFromIgnoredType,
                                       hasType(isInteger()))));

  // Bitfields are special. Due to integral promotion [conv.prom/5] bitfield
  // member access expressions are frequently wrapped by an implicit cast to
  // `int` if that type can represent all the values of the bitfield.
  //
  // Consider these examples:
  //   struct SmallBitfield { unsigned int id : 4; };
  //   x.id & 1;             (case-1)
  //   x.id & 1u;            (case-2)
  //   x.id << 1u;           (case-3)
  //   (unsigned)x.id << 1;  (case-4)
  //
  // Due to the promotion rules, we would get a warning for case-1. It's
  // debatable how useful this is, but the user at least has a convenient way of
  // //fixing// it by adding the `u` unsigned-suffix to the literal as
  // demonstrated by case-2. However, this won't work for shift operators like
  // the one in case-3. In case of a normal binary operator, both operands
  // contribute to the result type. However, the type of the shift expression is
  // the promoted type of the left operand. One could still suppress this
  // superfluous warning by explicitly casting the bitfield member access as
  // case-4 demonstrates, but why? The compiler already knew that the value from
  // the member access should safely fit into an `int`, why do we have this
  // warning in the first place? So, hereby we suppress this specific scenario.
  //
  // Note that the bitshift operation might invoke unspecified/undefined
  // behavior, but that's another topic, this checker is about detecting
  // conversion-related defects.
  //
  // Example AST for `x.id << 1`:
  //   BinaryOperator 'int' '<<'
  //   |-ImplicitCastExpr 'int' <IntegralCast>
  //   | `-ImplicitCastExpr 'unsigned int' <LValueToRValue>
  //   |   `-MemberExpr 'unsigned int' lvalue bitfield .id
  //   |     `-DeclRefExpr 'SmallBitfield' lvalue ParmVar 'x' 'SmallBitfield'
  //   `-IntegerLiteral 'int' 1
  const auto ImplicitIntWidenedBitfieldValue = implicitCastExpr(
      hasCastKind(CK_IntegralCast), hasType(asString("int")),
      has(castExpr(hasCastKind(CK_LValueToRValue),
                   has(ignoringParens(memberExpr(hasDeclaration(
                       fieldDecl(isBitField(), unless(hasIntBitwidth())))))))));

  // Casts:
  //   i = 0.5;
  //   void f(int); f(0.5);
  Finder->addMatcher(
      traverse(TK_AsIs, implicitCastExpr(
                            hasImplicitDestinationType(
                                hasUnqualifiedDesugaredType(builtinType())),
                            hasSourceExpression(hasType(
                                hasUnqualifiedDesugaredType(builtinType()))),
                            unless(hasSourceExpression(IsCeilFloorCallExpr)),
                            unless(hasParent(castExpr())),
                            WarnWithinTemplateInstantiation
                                ? stmt()
                                : stmt(unless(isInTemplateInstantiation())),
                            IgnoreConversionFromTypes.empty()
                                ? castExpr()
                                : castExpr(unless(hasSourceExpression(
                                      IsIgnoredTypeTwoLevelsDeep))),
                            unless(ImplicitIntWidenedBitfieldValue))
                            .bind("cast")),
      this);

  // Binary operators:
  //   i += 0.5;
  Finder->addMatcher(
      binaryOperator(
          isAssignmentOperator(),
          hasLHS(expr(hasType(hasUnqualifiedDesugaredType(builtinType())))),
          hasRHS(expr(hasType(hasUnqualifiedDesugaredType(builtinType())))),
          unless(hasRHS(IsCeilFloorCallExpr)),
          WarnWithinTemplateInstantiation
              ? binaryOperator()
              : binaryOperator(unless(isInTemplateInstantiation())),
          IgnoreConversionFromTypes.empty()
              ? binaryOperator()
              : binaryOperator(unless(hasRHS(IsIgnoredTypeTwoLevelsDeep))),
          // The `=` case generates an implicit cast
          // which is covered by the previous matcher.
          unless(hasOperatorName("=")))
          .bind("binary_op"),
      this);
}

static const BuiltinType *getBuiltinType(const Expr &E) {
  return E.getType().getCanonicalType().getTypePtr()->getAs<BuiltinType>();
}

static QualType getUnqualifiedType(const Expr &E) {
  return E.getType().getUnqualifiedType();
}

static APValue getConstantExprValue(const ASTContext &Ctx, const Expr &E) {
  if (auto IntegerConstant = E.getIntegerConstantExpr(Ctx))
    return APValue(*IntegerConstant);
  APValue Constant;
  if (Ctx.getLangOpts().CPlusPlus && E.isCXX11ConstantExpr(Ctx, &Constant))
    return Constant;
  return {};
}

static bool getIntegerConstantExprValue(const ASTContext &Context,
                                        const Expr &E, llvm::APSInt &Value) {
  APValue Constant = getConstantExprValue(Context, E);
  if (!Constant.isInt())
    return false;
  Value = Constant.getInt();
  return true;
}

static bool getFloatingConstantExprValue(const ASTContext &Context,
                                         const Expr &E, llvm::APFloat &Value) {
  APValue Constant = getConstantExprValue(Context, E);
  if (!Constant.isFloat())
    return false;
  Value = Constant.getFloat();
  return true;
}

namespace {

struct IntegerRange {
  bool contains(const IntegerRange &From) const {
    return llvm::APSInt::compareValues(Lower, From.Lower) <= 0 &&
           llvm::APSInt::compareValues(Upper, From.Upper) >= 0;
  }

  bool contains(const llvm::APSInt &Value) const {
    return llvm::APSInt::compareValues(Lower, Value) <= 0 &&
           llvm::APSInt::compareValues(Upper, Value) >= 0;
  }

  llvm::APSInt Lower;
  llvm::APSInt Upper;
};

} // namespace

static IntegerRange createFromType(const ASTContext &Context,
                                   const BuiltinType &T) {
  if (T.isFloatingPoint()) {
    unsigned PrecisionBits = llvm::APFloatBase::semanticsPrecision(
        Context.getFloatTypeSemantics(T.desugar()));
    // Contrary to two's complement integer, floating point values are
    // symmetric and have the same number of positive and negative values.
    // The range of valid integers for a floating point value is:
    // [-2^PrecisionBits, 2^PrecisionBits]

    // Values are created with PrecisionBits plus two bits:
    // - One to express the missing negative value of 2's complement
    //   representation.
    // - One for the sign.
    llvm::APSInt UpperValue(PrecisionBits + 2, /*isUnsigned*/ false);
    UpperValue.setBit(PrecisionBits);
    llvm::APSInt LowerValue(PrecisionBits + 2, /*isUnsigned*/ false);
    LowerValue.setBit(PrecisionBits);
    LowerValue.setSignBit();
    return {LowerValue, UpperValue};
  }
  assert(T.isInteger() && "Unexpected builtin type");
  uint64_t TypeSize = Context.getTypeSize(&T);
  bool IsUnsignedInteger = T.isUnsignedInteger();
  return {llvm::APSInt::getMinValue(TypeSize, IsUnsignedInteger),
          llvm::APSInt::getMaxValue(TypeSize, IsUnsignedInteger)};
}

static bool isWideEnoughToHold(const ASTContext &Context,
                               const BuiltinType &FromType,
                               const BuiltinType &ToType) {
  IntegerRange FromIntegerRange = createFromType(Context, FromType);
  IntegerRange ToIntegerRange = createFromType(Context, ToType);
  return ToIntegerRange.contains(FromIntegerRange);
}

static bool isWideEnoughToHold(const ASTContext &Context,
                               const llvm::APSInt &IntegerConstant,
                               const BuiltinType &ToType) {
  IntegerRange ToIntegerRange = createFromType(Context, ToType);
  return ToIntegerRange.contains(IntegerConstant);
}

// Returns true iff the floating point constant can be losslessly represented
// by an integer in the given destination type. eg. 2.0 can be accurately
// represented by an int32_t, but neither 2^33 nor 2.001 can.
static bool isFloatExactlyRepresentable(const ASTContext &Context,
                                        const llvm::APFloat &FloatConstant,
                                        const QualType &DestType) {
  unsigned DestWidth = Context.getIntWidth(DestType);
  bool DestSigned = DestType->isSignedIntegerOrEnumerationType();
  llvm::APSInt Result = llvm::APSInt(DestWidth, !DestSigned);
  bool IsExact = false;
  bool Overflows = FloatConstant.convertToInteger(
                       Result, llvm::APFloat::rmTowardZero, &IsExact) &
                   llvm::APFloat::opInvalidOp;
  return !Overflows && IsExact;
}

static llvm::SmallString<64> getValueAsString(const llvm::APSInt &Value,
                                              uint64_t HexBits) {
  llvm::SmallString<64> Str;
  Value.toString(Str, 10);
  if (HexBits > 0) {
    Str.append(" (0x");
    llvm::SmallString<32> HexValue;
    Value.toStringUnsigned(HexValue, 16);
    for (size_t I = HexValue.size(); I < (HexBits / 4); ++I)
      Str.append("0");
    Str.append(HexValue);
    Str.append(")");
  }
  return Str;
}

bool NarrowingConversionsCheck::isWarningInhibitedByEquivalentSize(
    const ASTContext &Context, const BuiltinType &FromType,
    const BuiltinType &ToType) const {
  // With this option, we don't warn on conversions that have equivalent width
  // in bits. eg. uint32 <-> int32.
  if (!WarnOnEquivalentBitWidth) {
    uint64_t FromTypeSize = Context.getTypeSize(&FromType);
    uint64_t ToTypeSize = Context.getTypeSize(&ToType);
    if (FromTypeSize == ToTypeSize) {
      return true;
    }
  }
  return false;
}

void NarrowingConversionsCheck::diagNarrowType(SourceLocation SourceLoc,
                                               const Expr &Lhs,
                                               const Expr &Rhs) {
  diag(SourceLoc, "narrowing conversion from %0 to %1")
      << getUnqualifiedType(Rhs) << getUnqualifiedType(Lhs);
}

void NarrowingConversionsCheck::diagNarrowTypeToSignedInt(
    SourceLocation SourceLoc, const Expr &Lhs, const Expr &Rhs) {
  diag(SourceLoc, "narrowing conversion from %0 to signed type %1 is "
                  "implementation-defined")
      << getUnqualifiedType(Rhs) << getUnqualifiedType(Lhs);
}

void NarrowingConversionsCheck::diagNarrowIntegerConstant(
    SourceLocation SourceLoc, const Expr &Lhs, const Expr &Rhs,
    const llvm::APSInt &Value) {
  diag(SourceLoc,
       "narrowing conversion from constant value %0 of type %1 to %2")
      << getValueAsString(Value, /*NoHex*/ 0) << getUnqualifiedType(Rhs)
      << getUnqualifiedType(Lhs);
}

void NarrowingConversionsCheck::diagNarrowIntegerConstantToSignedInt(
    SourceLocation SourceLoc, const Expr &Lhs, const Expr &Rhs,
    const llvm::APSInt &Value, const uint64_t HexBits) {
  diag(SourceLoc, "narrowing conversion from constant value %0 of type %1 "
                  "to signed type %2 is implementation-defined")
      << getValueAsString(Value, HexBits) << getUnqualifiedType(Rhs)
      << getUnqualifiedType(Lhs);
}

void NarrowingConversionsCheck::diagNarrowConstant(SourceLocation SourceLoc,
                                                   const Expr &Lhs,
                                                   const Expr &Rhs) {
  diag(SourceLoc, "narrowing conversion from constant %0 to %1")
      << getUnqualifiedType(Rhs) << getUnqualifiedType(Lhs);
}

void NarrowingConversionsCheck::diagConstantCast(SourceLocation SourceLoc,
                                                 const Expr &Lhs,
                                                 const Expr &Rhs) {
  diag(SourceLoc, "constant value should be of type of type %0 instead of %1")
      << getUnqualifiedType(Lhs) << getUnqualifiedType(Rhs);
}

void NarrowingConversionsCheck::diagNarrowTypeOrConstant(
    const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
    const Expr &Rhs) {
  APValue Constant = getConstantExprValue(Context, Rhs);
  if (Constant.isInt())
    return diagNarrowIntegerConstant(SourceLoc, Lhs, Rhs, Constant.getInt());
  if (Constant.isFloat())
    return diagNarrowConstant(SourceLoc, Lhs, Rhs);
  return diagNarrowType(SourceLoc, Lhs, Rhs);
}

void NarrowingConversionsCheck::handleIntegralCast(const ASTContext &Context,
                                                   SourceLocation SourceLoc,
                                                   const Expr &Lhs,
                                                   const Expr &Rhs) {
  if (WarnOnIntegerNarrowingConversion) {
    const BuiltinType *ToType = getBuiltinType(Lhs);
    // From [conv.integral]p7.3.8:
    // Conversions to unsigned integer is well defined so no warning is issued.
    // "The resulting value is the smallest unsigned value equal to the source
    // value modulo 2^n where n is the number of bits used to represent the
    // destination type."
    if (ToType->isUnsignedInteger())
      return;
    const BuiltinType *FromType = getBuiltinType(Rhs);

    // With this option, we don't warn on conversions that have equivalent width
    // in bits. eg. uint32 <-> int32.
    if (!WarnOnEquivalentBitWidth) {
      uint64_t FromTypeSize = Context.getTypeSize(FromType);
      uint64_t ToTypeSize = Context.getTypeSize(ToType);
      if (FromTypeSize == ToTypeSize)
        return;
    }

    llvm::APSInt IntegerConstant;
    if (getIntegerConstantExprValue(Context, Rhs, IntegerConstant)) {
      if (!isWideEnoughToHold(Context, IntegerConstant, *ToType))
        diagNarrowIntegerConstantToSignedInt(SourceLoc, Lhs, Rhs,
                                             IntegerConstant,
                                             Context.getTypeSize(FromType));
      return;
    }
    if (!isWideEnoughToHold(Context, *FromType, *ToType))
      diagNarrowTypeToSignedInt(SourceLoc, Lhs, Rhs);
  }
}

void NarrowingConversionsCheck::handleIntegralToBoolean(
    const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
    const Expr &Rhs) {
  // Conversion from Integral to Bool value is well defined.

  // We keep this function (even if it is empty) to make sure that
  // handleImplicitCast and handleBinaryOperator are symmetric in their behavior
  // and handle the same cases.
}

void NarrowingConversionsCheck::handleIntegralToFloating(
    const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
    const Expr &Rhs) {
  if (WarnOnIntegerToFloatingPointNarrowingConversion) {
    const BuiltinType *ToType = getBuiltinType(Lhs);
    llvm::APSInt IntegerConstant;
    if (getIntegerConstantExprValue(Context, Rhs, IntegerConstant)) {
      if (!isWideEnoughToHold(Context, IntegerConstant, *ToType))
        diagNarrowIntegerConstant(SourceLoc, Lhs, Rhs, IntegerConstant);
      return;
    }

    const BuiltinType *FromType = getBuiltinType(Rhs);
    if (isWarningInhibitedByEquivalentSize(Context, *FromType, *ToType))
      return;
    if (!isWideEnoughToHold(Context, *FromType, *ToType))
      diagNarrowType(SourceLoc, Lhs, Rhs);
  }
}

void NarrowingConversionsCheck::handleFloatingToIntegral(
    const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
    const Expr &Rhs) {
  llvm::APFloat FloatConstant(0.0);
  if (getFloatingConstantExprValue(Context, Rhs, FloatConstant)) {
    if (!isFloatExactlyRepresentable(Context, FloatConstant, Lhs.getType()))
      return diagNarrowConstant(SourceLoc, Lhs, Rhs);

    if (PedanticMode)
      return diagConstantCast(SourceLoc, Lhs, Rhs);

    return;
  }

  const BuiltinType *FromType = getBuiltinType(Rhs);
  const BuiltinType *ToType = getBuiltinType(Lhs);
  if (isWarningInhibitedByEquivalentSize(Context, *FromType, *ToType))
    return;
  diagNarrowType(SourceLoc, Lhs, Rhs); // Assumed always lossy.
}

void NarrowingConversionsCheck::handleFloatingToBoolean(
    const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
    const Expr &Rhs) {
  return diagNarrowTypeOrConstant(Context, SourceLoc, Lhs, Rhs);
}

void NarrowingConversionsCheck::handleBooleanToSignedIntegral(
    const ASTContext &Context, SourceLocation SourceLoc, const Expr &Lhs,
    const Expr &Rhs) {
  // Conversion from Bool to SignedIntegral value is well defined.

  // We keep this function (even if it is empty) to make sure that
  // handleImplicitCast and handleBinaryOperator are symmetric in their behavior
  // and handle the same cases.
}

void NarrowingConversionsCheck::handleFloatingCast(const ASTContext &Context,
                                                   SourceLocation SourceLoc,
                                                   const Expr &Lhs,
                                                   const Expr &Rhs) {
  if (WarnOnFloatingPointNarrowingConversion) {
    const BuiltinType *ToType = getBuiltinType(Lhs);
    APValue Constant = getConstantExprValue(Context, Rhs);
    if (Constant.isFloat()) {
      // From [dcl.init.list]p7.2:
      // Floating point constant narrowing only takes place when the value is
      // not within destination range. We convert the value to the destination
      // type and check if the resulting value is infinity.
      llvm::APFloat Tmp = Constant.getFloat();
      bool UnusedLosesInfo;
      Tmp.convert(Context.getFloatTypeSemantics(ToType->desugar()),
                  llvm::APFloatBase::rmNearestTiesToEven, &UnusedLosesInfo);
      if (Tmp.isInfinity())
        diagNarrowConstant(SourceLoc, Lhs, Rhs);
      return;
    }
    const BuiltinType *FromType = getBuiltinType(Rhs);
    if (ToType->getKind() < FromType->getKind())
      diagNarrowType(SourceLoc, Lhs, Rhs);
  }
}

void NarrowingConversionsCheck::handleBinaryOperator(const ASTContext &Context,
                                                     SourceLocation SourceLoc,
                                                     const Expr &Lhs,
                                                     const Expr &Rhs) {
  assert(!Lhs.isInstantiationDependent() && !Rhs.isInstantiationDependent() &&
         "Dependent types must be check before calling this function");
  const BuiltinType *LhsType = getBuiltinType(Lhs);
  const BuiltinType *RhsType = getBuiltinType(Rhs);
  if (RhsType == nullptr || LhsType == nullptr)
    return;
  if (RhsType->getKind() == BuiltinType::Bool && LhsType->isSignedInteger())
    return handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
  if (RhsType->isInteger() && LhsType->getKind() == BuiltinType::Bool)
    return handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
  if (RhsType->isInteger() && LhsType->isFloatingPoint())
    return handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
  if (RhsType->isInteger() && LhsType->isInteger())
    return handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
  if (RhsType->isFloatingPoint() && LhsType->getKind() == BuiltinType::Bool)
    return handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
  if (RhsType->isFloatingPoint() && LhsType->isInteger())
    return handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
  if (RhsType->isFloatingPoint() && LhsType->isFloatingPoint())
    return handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
}

bool NarrowingConversionsCheck::handleConditionalOperator(
    const ASTContext &Context, const Expr &Lhs, const Expr &Rhs) {
  if (const auto *CO = llvm::dyn_cast<ConditionalOperator>(&Rhs)) {
    // We have an expression like so: `output = cond ? lhs : rhs`
    // From the point of view of narrowing conversion we treat it as two
    // expressions `output = lhs` and `output = rhs`.
    handleBinaryOperator(Context, CO->getLHS()->getExprLoc(), Lhs,
                         *CO->getLHS());
    handleBinaryOperator(Context, CO->getRHS()->getExprLoc(), Lhs,
                         *CO->getRHS());
    return true;
  }
  return false;
}

void NarrowingConversionsCheck::handleImplicitCast(
    const ASTContext &Context, const ImplicitCastExpr &Cast) {
  if (Cast.getExprLoc().isMacroID())
    return;
  const Expr &Lhs = Cast;
  const Expr &Rhs = *Cast.getSubExpr();
  if (Lhs.isInstantiationDependent() || Rhs.isInstantiationDependent())
    return;
  if (handleConditionalOperator(Context, Lhs, Rhs))
    return;
  SourceLocation SourceLoc = Lhs.getExprLoc();
  switch (Cast.getCastKind()) {
  case CK_BooleanToSignedIntegral:
    return handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
  case CK_IntegralToBoolean:
    return handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
  case CK_IntegralToFloating:
    return handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
  case CK_IntegralCast:
    return handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
  case CK_FloatingToBoolean:
    return handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
  case CK_FloatingToIntegral:
    return handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
  case CK_FloatingCast:
    return handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
  default:
    break;
  }
}

void NarrowingConversionsCheck::handleBinaryOperator(const ASTContext &Context,
                                                     const BinaryOperator &Op) {
  if (Op.getBeginLoc().isMacroID())
    return;
  const Expr &Lhs = *Op.getLHS();
  const Expr &Rhs = *Op.getRHS();
  if (Lhs.isInstantiationDependent() || Rhs.isInstantiationDependent())
    return;
  if (handleConditionalOperator(Context, Lhs, Rhs))
    return;
  handleBinaryOperator(Context, Rhs.getBeginLoc(), Lhs, Rhs);
}

void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) {
  if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("binary_op"))
    return handleBinaryOperator(*Result.Context, *Op);
  if (const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast"))
    return handleImplicitCast(*Result.Context, *Cast);
  llvm_unreachable("must be binary operator or cast expression");
}
} // namespace cppcoreguidelines
} // namespace tidy
} // namespace clang
