//===--- 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/STLExtras.h"
#include "llvm/ADT/SmallString.h"

#include <cstdint>

using namespace clang::ast_matchers;

namespace clang::tidy::bugprone {

namespace {

AST_MATCHER_P(QualType, hasAnyType, std::vector<StringRef>, Names) {
  if (Names.empty())
    return false;

  std::string Name = Node.getLocalUnqualifiedType().getAsString();
  return llvm::is_contained(Names, Name);
}

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

} // namespace

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);
}

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")))));

  std::vector<StringRef> IgnoreConversionFromTypesVec =
      utils::options::parseStringList(IgnoreConversionFromTypes);

  // 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 =
      anyOf(hasType(namedDecl(hasAnyName(IgnoreConversionFromTypesVec))),
            allOf(unless(hasType(namedDecl())),
                  hasType(qualType(hasAnyType(IgnoreConversionFromTypesVec)))));

  // `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())
    diagNarrowIntegerConstant(SourceLoc, Lhs, Rhs, Constant.getInt());
  else if (Constant.isFloat())
    diagNarrowConstant(SourceLoc, Lhs, Rhs);
  else
    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()))
      diagNarrowConstant(SourceLoc, Lhs, Rhs);

    else if (PedanticMode)
      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) {
  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 = false;
      Tmp.convert(Context.getFloatTypeSemantics(ToType->desugar()),
                  llvm::APFloatBase::rmNearestTiesToEven, &UnusedLosesInfo);
      if (Tmp.isInfinity())
        diagNarrowConstant(SourceLoc, Lhs, Rhs);
      return;
    }
    const BuiltinType *FromType = getBuiltinType(Rhs);
    if (!llvm::APFloatBase::isRepresentableBy(
            Context.getFloatTypeSemantics(FromType->desugar()),
            Context.getFloatTypeSemantics(ToType->desugar())))
      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 (LhsType == RhsType)
    return;
  if (RhsType->getKind() == BuiltinType::Bool && LhsType->isSignedInteger())
    handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
  else if (RhsType->isInteger() && LhsType->getKind() == BuiltinType::Bool)
    handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
  else if (RhsType->isInteger() && LhsType->isFloatingPoint())
    handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
  else if (RhsType->isInteger() && LhsType->isInteger())
    handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
  else if (RhsType->isFloatingPoint() &&
           LhsType->getKind() == BuiltinType::Bool)
    handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
  else if (RhsType->isFloatingPoint() && LhsType->isInteger())
    handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
  else if (RhsType->isFloatingPoint() && LhsType->isFloatingPoint())
    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`.
    handleConditionalOperatorArgument(Context, Lhs, CO->getLHS());
    handleConditionalOperatorArgument(Context, Lhs, CO->getRHS());
    return true;
  }
  return false;
}

void NarrowingConversionsCheck::handleConditionalOperatorArgument(
    const ASTContext &Context, const Expr &Lhs, const Expr *Arg) {
  if (const auto *ICE = llvm::dyn_cast<ImplicitCastExpr>(Arg))
    if (!Arg->getIntegerConstantExpr(Context))
      Arg = ICE->getSubExpr();

  handleBinaryOperator(Context, Arg->getExprLoc(), Lhs, *Arg);
}

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 (getBuiltinType(Lhs) == getBuiltinType(Rhs))
    return;
  if (handleConditionalOperator(Context, Lhs, Rhs))
    return;
  SourceLocation SourceLoc = Lhs.getExprLoc();
  switch (Cast.getCastKind()) {
  case CK_BooleanToSignedIntegral:
    handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs);
    return;
  case CK_IntegralToBoolean:
    handleIntegralToBoolean(Context, SourceLoc, Lhs, Rhs);
    return;
  case CK_IntegralToFloating:
    handleIntegralToFloating(Context, SourceLoc, Lhs, Rhs);
    return;
  case CK_IntegralCast:
    handleIntegralCast(Context, SourceLoc, Lhs, Rhs);
    return;
  case CK_FloatingToBoolean:
    handleFloatingToBoolean(Context, SourceLoc, Lhs, Rhs);
    return;
  case CK_FloatingToIntegral:
    handleFloatingToIntegral(Context, SourceLoc, Lhs, Rhs);
    return;
  case CK_FloatingCast:
    handleFloatingCast(Context, SourceLoc, Lhs, Rhs);
    return;
  default:
    return;
  }
}

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"))
    handleBinaryOperator(*Result.Context, *Op);
  else if (const auto *Cast = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast"))
    handleImplicitCast(*Result.Context, *Cast);
  else
    llvm_unreachable("must be binary operator or cast expression");
}
} // namespace clang::tidy::bugprone
