//===--- EasilySwappableParametersCheck.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 "EasilySwappableParametersCheck.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallSet.h"

#define DEBUG_TYPE "EasilySwappableParametersCheck"
#include "llvm/Support/Debug.h"
#include <optional>

namespace optutils = clang::tidy::utils::options;

/// The default value for the MinimumLength check option.
static constexpr std::size_t DefaultMinimumLength = 2;

/// The default value for ignored parameter names.
static constexpr llvm::StringLiteral DefaultIgnoredParameterNames = "\"\";"
                                                                    "iterator;"
                                                                    "Iterator;"
                                                                    "begin;"
                                                                    "Begin;"
                                                                    "end;"
                                                                    "End;"
                                                                    "first;"
                                                                    "First;"
                                                                    "last;"
                                                                    "Last;"
                                                                    "lhs;"
                                                                    "LHS;"
                                                                    "rhs;"
                                                                    "RHS";

/// The default value for ignored parameter type suffixes.
static constexpr llvm::StringLiteral DefaultIgnoredParameterTypeSuffixes =
    "bool;"
    "Bool;"
    "_Bool;"
    "it;"
    "It;"
    "iterator;"
    "Iterator;"
    "inputit;"
    "InputIt;"
    "forwardit;"
    "ForwardIt;"
    "bidirit;"
    "BidirIt;"
    "constiterator;"
    "const_iterator;"
    "Const_Iterator;"
    "Constiterator;"
    "ConstIterator;"
    "RandomIt;"
    "randomit;"
    "random_iterator;"
    "ReverseIt;"
    "reverse_iterator;"
    "reverse_const_iterator;"
    "ConstReverseIterator;"
    "Const_Reverse_Iterator;"
    "const_reverse_iterator;"
    "Constreverseiterator;"
    "constreverseiterator";

/// The default value for the QualifiersMix check option.
static constexpr bool DefaultQualifiersMix = false;

/// The default value for the ModelImplicitConversions check option.
static constexpr bool DefaultModelImplicitConversions = true;

/// The default value for suppressing diagnostics about parameters that are
/// used together.
static constexpr bool DefaultSuppressParametersUsedTogether = true;

/// The default value for the NamePrefixSuffixSilenceDissimilarityTreshold
/// check option.
static constexpr std::size_t
    DefaultNamePrefixSuffixSilenceDissimilarityTreshold = 1;

using namespace clang::ast_matchers;

namespace clang::tidy::bugprone {

using TheCheck = EasilySwappableParametersCheck;

namespace filter {
class SimilarlyUsedParameterPairSuppressor;

static bool isIgnoredParameter(const TheCheck &Check, const ParmVarDecl *Node);
static inline bool
isSimilarlyUsedParameter(const SimilarlyUsedParameterPairSuppressor &Suppressor,
                         const ParmVarDecl *Param1, const ParmVarDecl *Param2);
static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold,
                                            StringRef Str1, StringRef Str2);
} // namespace filter

namespace model {

/// The language features involved in allowing the mix between two parameters.
enum class MixFlags : unsigned char {
  Invalid = 0, ///< Sentinel bit pattern. DO NOT USE!

  /// Certain constructs (such as pointers to noexcept/non-noexcept functions)
  /// have the same CanonicalType, which would result in false positives.
  /// During the recursive modelling call, this flag is set if a later diagnosed
  /// canonical type equivalence should be thrown away.
  WorkaroundDisableCanonicalEquivalence = 1,

  None = 2,           ///< Mix between the two parameters is not possible.
  Trivial = 4,        ///< The two mix trivially, and are the exact same type.
  Canonical = 8,      ///< The two mix because the types refer to the same
                      /// CanonicalType, but we do not elaborate as to how.
  TypeAlias = 16,     ///< The path from one type to the other involves
                      /// desugaring type aliases.
  ReferenceBind = 32, ///< The mix involves the binding power of "const &".
  Qualifiers = 64,    ///< The mix involves change in the qualifiers.
  ImplicitConversion = 128, ///< The mixing of the parameters is possible
                            /// through implicit conversions between the types.

  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue =*/ImplicitConversion)
};
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();

/// Returns whether the SearchedFlag is turned on in the Data.
static inline bool hasFlag(MixFlags Data, MixFlags SearchedFlag) {
  assert(SearchedFlag != MixFlags::Invalid &&
         "can't be used to detect lack of all bits!");

  // "Data & SearchedFlag" would need static_cast<bool>() in conditions.
  return (Data & SearchedFlag) == SearchedFlag;
}

#ifndef NDEBUG

// The modelling logic of this check is more complex than usual, and
// potentially hard to understand without the ability to see into the
// representation during the recursive descent. This debug code is only
// compiled in 'Debug' mode, or if LLVM_ENABLE_ASSERTIONS config is turned on.

/// Formats the MixFlags enum into a useful, user-readable representation.
static inline std::string formatMixFlags(MixFlags F) {
  if (F == MixFlags::Invalid)
    return "#Inv!";

  SmallString<8> Str{"-------"};

  if (hasFlag(F, MixFlags::None))
    // Shows the None bit explicitly, as it can be applied in the recursion
    // even if other bits are set.
    Str[0] = '!';
  if (hasFlag(F, MixFlags::Trivial))
    Str[1] = 'T';
  if (hasFlag(F, MixFlags::Canonical))
    Str[2] = 'C';
  if (hasFlag(F, MixFlags::TypeAlias))
    Str[3] = 't';
  if (hasFlag(F, MixFlags::ReferenceBind))
    Str[4] = '&';
  if (hasFlag(F, MixFlags::Qualifiers))
    Str[5] = 'Q';
  if (hasFlag(F, MixFlags::ImplicitConversion))
    Str[6] = 'i';

  if (hasFlag(F, MixFlags::WorkaroundDisableCanonicalEquivalence))
    Str.append("(~C)");

  return Str.str().str();
}

#endif // NDEBUG

/// The results of the steps of an Implicit Conversion Sequence is saved in
/// an instance of this record.
///
/// A ConversionSequence maps the steps of the conversion with a member for
/// each type involved in the conversion. Imagine going from a hypothetical
/// Complex class to projecting it to the real part as a const double.
///
/// I.e., given:
///
///    struct Complex {
///      operator double() const;
///    };
///
///    void functionBeingAnalysed(Complex C, const double R);
///
/// we will get the following sequence:
///
/// (Begin=) Complex
///
///     The first standard conversion is a qualification adjustment.
/// (AfterFirstStandard=) const Complex
///
///     Then the user-defined conversion is executed.
/// (UDConvOp.ConversionOperatorResultType=) double
///
///     Then this 'double' is qualifier-adjusted to 'const double'.
/// (AfterSecondStandard=) double
///
/// The conversion's result has now been calculated, so it ends here.
/// (End=) double.
///
/// Explicit storing of Begin and End in this record is needed, because
/// getting to what Begin and End here are needs further resolution of types,
/// e.g. in the case of typedefs:
///
///     using Comp = Complex;
///     using CD = const double;
///     void functionBeingAnalysed2(Comp C, CD R);
///
/// In this case, the user will be diagnosed with a potential conversion
/// between the two typedefs as written in the code, but to elaborate the
/// reasoning behind this conversion, we also need to show what the typedefs
/// mean. See FormattedConversionSequence towards the bottom of this file!
struct ConversionSequence {
  enum UserDefinedConversionKind { UDCK_None, UDCK_Ctor, UDCK_Oper };

  struct UserDefinedConvertingConstructor {
    const CXXConstructorDecl *Fun;
    QualType ConstructorParameterType;
    QualType UserDefinedType;
  };

  struct UserDefinedConversionOperator {
    const CXXConversionDecl *Fun;
    QualType UserDefinedType;
    QualType ConversionOperatorResultType;
  };

  /// The type the conversion stared from.
  QualType Begin;

  /// The intermediate type after the first Standard Conversion Sequence.
  QualType AfterFirstStandard;

  /// The details of the user-defined conversion involved, as a tagged union.
  union {
    char None;
    UserDefinedConvertingConstructor UDConvCtor;
    UserDefinedConversionOperator UDConvOp;
  };
  UserDefinedConversionKind UDConvKind;

  /// The intermediate type after performing the second Standard Conversion
  /// Sequence.
  QualType AfterSecondStandard;

  /// The result type the conversion targeted.
  QualType End;

  ConversionSequence() : None(0), UDConvKind(UDCK_None) {}
  ConversionSequence(QualType From, QualType To)
      : Begin(From), None(0), UDConvKind(UDCK_None), End(To) {}

  explicit operator bool() const {
    return !AfterFirstStandard.isNull() || UDConvKind != UDCK_None ||
           !AfterSecondStandard.isNull();
  }

  /// Returns all the "steps" (non-unique and non-similar) types involved in
  /// the conversion sequence. This method does **NOT** return Begin and End.
  SmallVector<QualType, 4> getInvolvedTypesInSequence() const {
    SmallVector<QualType, 4> Ret;
    auto EmplaceIfDifferent = [&Ret](QualType QT) {
      if (QT.isNull())
        return;
      if (Ret.empty())
        Ret.emplace_back(QT);
      else if (Ret.back() != QT)
        Ret.emplace_back(QT);
    };

    EmplaceIfDifferent(AfterFirstStandard);
    switch (UDConvKind) {
    case UDCK_Ctor:
      EmplaceIfDifferent(UDConvCtor.ConstructorParameterType);
      EmplaceIfDifferent(UDConvCtor.UserDefinedType);
      break;
    case UDCK_Oper:
      EmplaceIfDifferent(UDConvOp.UserDefinedType);
      EmplaceIfDifferent(UDConvOp.ConversionOperatorResultType);
      break;
    case UDCK_None:
      break;
    }
    EmplaceIfDifferent(AfterSecondStandard);

    return Ret;
  }

  /// Updates the steps of the conversion sequence with the steps from the
  /// other instance.
  ///
  /// \note This method does not check if the resulting conversion sequence is
  /// sensible!
  ConversionSequence &update(const ConversionSequence &RHS) {
    if (!RHS.AfterFirstStandard.isNull())
      AfterFirstStandard = RHS.AfterFirstStandard;
    switch (RHS.UDConvKind) {
    case UDCK_Ctor:
      UDConvKind = UDCK_Ctor;
      UDConvCtor = RHS.UDConvCtor;
      break;
    case UDCK_Oper:
      UDConvKind = UDCK_Oper;
      UDConvOp = RHS.UDConvOp;
      break;
    case UDCK_None:
      break;
    }
    if (!RHS.AfterSecondStandard.isNull())
      AfterSecondStandard = RHS.AfterSecondStandard;

    return *this;
  }

  /// Sets the user-defined conversion to the given constructor.
  void setConversion(const UserDefinedConvertingConstructor &UDCC) {
    UDConvKind = UDCK_Ctor;
    UDConvCtor = UDCC;
  }

  /// Sets the user-defined conversion to the given operator.
  void setConversion(const UserDefinedConversionOperator &UDCO) {
    UDConvKind = UDCK_Oper;
    UDConvOp = UDCO;
  }

  /// Returns the type in the conversion that's formally "in our hands" once
  /// the user-defined conversion is executed.
  QualType getTypeAfterUserDefinedConversion() const {
    switch (UDConvKind) {
    case UDCK_Ctor:
      return UDConvCtor.UserDefinedType;
    case UDCK_Oper:
      return UDConvOp.ConversionOperatorResultType;
    case UDCK_None:
      return {};
    }
    llvm_unreachable("Invalid UDConv kind.");
  }

  const CXXMethodDecl *getUserDefinedConversionFunction() const {
    switch (UDConvKind) {
    case UDCK_Ctor:
      return UDConvCtor.Fun;
    case UDCK_Oper:
      return UDConvOp.Fun;
    case UDCK_None:
      return {};
    }
    llvm_unreachable("Invalid UDConv kind.");
  }

  /// Returns the SourceRange in the text that corresponds to the interesting
  /// part of the user-defined conversion. This is either the parameter type
  /// in a converting constructor, or the conversion result type in a conversion
  /// operator.
  SourceRange getUserDefinedConversionHighlight() const {
    switch (UDConvKind) {
    case UDCK_Ctor:
      return UDConvCtor.Fun->getParamDecl(0)->getSourceRange();
    case UDCK_Oper:
      // getReturnTypeSourceRange() does not work for CXXConversionDecls as the
      // returned type is physically behind the declaration's name ("operator").
      if (const FunctionTypeLoc FTL = UDConvOp.Fun->getFunctionTypeLoc())
        if (const TypeLoc RetLoc = FTL.getReturnLoc())
          return RetLoc.getSourceRange();
      return {};
    case UDCK_None:
      return {};
    }
    llvm_unreachable("Invalid UDConv kind.");
  }
};

/// Contains the metadata for the mixability result between two types,
/// independently of which parameters they were calculated from.
struct MixData {
  /// The flag bits of the mix indicating what language features allow for it.
  MixFlags Flags = MixFlags::Invalid;

  /// A potentially calculated common underlying type after desugaring, that
  /// both sides of the mix can originate from.
  QualType CommonType;

  /// The steps an implicit conversion performs to get from one type to the
  /// other.
  ConversionSequence Conversion, ConversionRTL;

  /// True if the MixData was specifically created with only a one-way
  /// conversion modelled.
  bool CreatedFromOneWayConversion = false;

  MixData(MixFlags Flags) : Flags(Flags) {}
  MixData(MixFlags Flags, QualType CommonType)
      : Flags(Flags), CommonType(CommonType) {}
  MixData(MixFlags Flags, ConversionSequence Conv)
      : Flags(Flags), Conversion(Conv), CreatedFromOneWayConversion(true) {}
  MixData(MixFlags Flags, ConversionSequence LTR, ConversionSequence RTL)
      : Flags(Flags), Conversion(LTR), ConversionRTL(RTL) {}
  MixData(MixFlags Flags, QualType CommonType, ConversionSequence LTR,
          ConversionSequence RTL)
      : Flags(Flags), CommonType(CommonType), Conversion(LTR),
        ConversionRTL(RTL) {}

  void sanitize() {
    assert(Flags != MixFlags::Invalid && "sanitize() called on invalid bitvec");

    MixFlags CanonicalAndWorkaround =
        MixFlags::Canonical | MixFlags::WorkaroundDisableCanonicalEquivalence;
    if ((Flags & CanonicalAndWorkaround) == CanonicalAndWorkaround) {
      // A workaround for too eagerly equivalent canonical types was requested,
      // and a canonical equivalence was proven. Fulfill the request and throw
      // this result away.
      Flags = MixFlags::None;
      return;
    }

    if (hasFlag(Flags, MixFlags::None)) {
      // If anywhere down the recursion a potential mix "path" is deemed
      // impossible, throw away all the other bits because the mix is not
      // possible.
      Flags = MixFlags::None;
      return;
    }

    if (Flags == MixFlags::Trivial)
      return;

    if (static_cast<bool>(Flags ^ MixFlags::Trivial))
      // If the mix involves somewhere trivial equivalence but down the
      // recursion other bit(s) were set, remove the trivial bit, as it is not
      // trivial.
      Flags &= ~MixFlags::Trivial;

    bool ShouldHaveImplicitConvFlag = false;
    if (CreatedFromOneWayConversion && Conversion)
      ShouldHaveImplicitConvFlag = true;
    else if (!CreatedFromOneWayConversion && Conversion && ConversionRTL)
      // Only say that we have implicit conversion mix possibility if it is
      // bidirectional. Otherwise, the compiler would report an *actual* swap
      // at a call site...
      ShouldHaveImplicitConvFlag = true;

    if (ShouldHaveImplicitConvFlag)
      Flags |= MixFlags::ImplicitConversion;
    else
      Flags &= ~MixFlags::ImplicitConversion;
  }

  bool isValid() const { return Flags >= MixFlags::None; }

  bool indicatesMixability() const { return Flags > MixFlags::None; }

  /// Add the specified flag bits to the flags.
  MixData operator|(MixFlags EnableFlags) const {
    if (CreatedFromOneWayConversion) {
      MixData M{Flags | EnableFlags, Conversion};
      M.CommonType = CommonType;
      return M;
    }
    return {Flags | EnableFlags, CommonType, Conversion, ConversionRTL};
  }

  /// Add the specified flag bits to the flags.
  MixData &operator|=(MixFlags EnableFlags) {
    Flags |= EnableFlags;
    return *this;
  }

  template <typename F> MixData withCommonTypeTransformed(const F &Func) const {
    if (CommonType.isNull())
      return *this;

    QualType NewCommonType = Func(CommonType);

    if (CreatedFromOneWayConversion) {
      MixData M{Flags, Conversion};
      M.CommonType = NewCommonType;
      return M;
    }

    return {Flags, NewCommonType, Conversion, ConversionRTL};
  }
};

/// A named tuple that contains the information for a mix between two concrete
/// parameters.
struct Mix {
  const ParmVarDecl *First, *Second;
  MixData Data;

  Mix(const ParmVarDecl *F, const ParmVarDecl *S, MixData Data)
      : First(F), Second(S), Data(std::move(Data)) {}

  void sanitize() { Data.sanitize(); }
  MixFlags flags() const { return Data.Flags; }
  bool flagsValid() const { return Data.isValid(); }
  bool mixable() const { return Data.indicatesMixability(); }
  QualType commonUnderlyingType() const { return Data.CommonType; }
  const ConversionSequence &leftToRightConversionSequence() const {
    return Data.Conversion;
  }
  const ConversionSequence &rightToLeftConversionSequence() const {
    return Data.ConversionRTL;
  }
};

// NOLINTNEXTLINE(misc-redundant-expression): Seems to be a bogus warning.
static_assert(std::is_trivially_copyable_v<Mix> &&
                  std::is_trivially_move_constructible_v<Mix> &&
                  std::is_trivially_move_assignable_v<Mix>,
              "Keep frequently used data simple!");

struct MixableParameterRange {
  /// A container for Mixes.
  using MixVector = SmallVector<Mix, 8>;

  /// The number of parameters iterated to build the instance.
  std::size_t NumParamsChecked = 0;

  /// The individual flags and supporting information for the mixes.
  MixVector Mixes;

  /// Gets the leftmost parameter of the range.
  const ParmVarDecl *getFirstParam() const {
    // The first element is the LHS of the very first mix in the range.
    assert(!Mixes.empty());
    return Mixes.front().First;
  }

  /// Gets the rightmost parameter of the range.
  const ParmVarDecl *getLastParam() const {
    // The builder function breaks building an instance of this type if it
    // finds something that can not be mixed with the rest, by going *forward*
    // in the list of parameters. So at any moment of break, the RHS of the last
    // element of the mix vector is also the last element of the mixing range.
    assert(!Mixes.empty());
    return Mixes.back().Second;
  }
};

/// Helper enum for the recursive calls in the modelling that toggle what kinds
/// of implicit conversions are to be modelled.
enum class ImplicitConversionModellingMode : unsigned char {
  ///< No implicit conversions are modelled.
  None,

  ///< The full implicit conversion sequence is modelled.
  All,

  ///< Only model a unidirectional implicit conversion and within it only one
  /// standard conversion sequence.
  OneWaySingleStandardOnly
};

static MixData
isLRefEquallyBindingToType(const TheCheck &Check,
                           const LValueReferenceType *LRef, QualType Ty,
                           const ASTContext &Ctx, bool IsRefRHS,
                           ImplicitConversionModellingMode ImplicitMode);

static MixData
approximateImplicitConversion(const TheCheck &Check, QualType LType,
                              QualType RType, const ASTContext &Ctx,
                              ImplicitConversionModellingMode ImplicitMode);

static inline bool isUselessSugar(const Type *T) {
  return isa<AttributedType, DecayedType, ElaboratedType, ParenType>(T);
}

namespace {

struct NonCVRQualifiersResult {
  /// True if the types are qualified in a way that even after equating or
  /// removing local CVR qualification, even if the unqualified types
  /// themselves would mix, the qualified ones don't, because there are some
  /// other local qualifiers that are not equal.
  bool HasMixabilityBreakingQualifiers;

  /// The set of equal qualifiers between the two types.
  Qualifiers CommonQualifiers;
};

} // namespace

/// Returns if the two types are qualified in a way that ever after equating or
/// removing local CVR qualification, even if the unqualified types would mix,
/// the qualified ones don't, because there are some other local qualifiers
/// that aren't equal.
static NonCVRQualifiersResult
getNonCVRQualifiers(const ASTContext &Ctx, QualType LType, QualType RType) {
  LLVM_DEBUG(llvm::dbgs() << ">>> getNonCVRQualifiers for LType:\n";
             LType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
             RType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);
  Qualifiers LQual = LType.getLocalQualifiers(),
             RQual = RType.getLocalQualifiers();

  // Strip potential CVR. That is handled by the check option QualifiersMix.
  LQual.removeCVRQualifiers();
  RQual.removeCVRQualifiers();

  NonCVRQualifiersResult Ret;
  Ret.CommonQualifiers = Qualifiers::removeCommonQualifiers(LQual, RQual);

  LLVM_DEBUG(llvm::dbgs() << "--- hasNonCVRMixabilityBreakingQualifiers. "
                             "Removed common qualifiers: ";
             Ret.CommonQualifiers.print(llvm::dbgs(), Ctx.getPrintingPolicy());
             llvm::dbgs() << "\n\tremaining on LType: ";
             LQual.print(llvm::dbgs(), Ctx.getPrintingPolicy());
             llvm::dbgs() << "\n\tremaining on RType: ";
             RQual.print(llvm::dbgs(), Ctx.getPrintingPolicy());
             llvm::dbgs() << '\n';);

  // If there are no other non-cvr non-common qualifiers left, we can deduce
  // that mixability isn't broken.
  Ret.HasMixabilityBreakingQualifiers =
      LQual.hasQualifiers() || RQual.hasQualifiers();

  return Ret;
}

/// Approximate the way how LType and RType might refer to "essentially the
/// same" type, in a sense that at a particular call site, an expression of
/// type LType and RType might be successfully passed to a variable (in our
/// specific case, a parameter) of type RType and LType, respectively.
/// Note the swapped order!
///
/// The returned data structure is not guaranteed to be properly set, as this
/// function is potentially recursive. It is the caller's responsibility to
/// call sanitize() on the result once the recursion is over.
static MixData
calculateMixability(const TheCheck &Check, QualType LType, QualType RType,
                    const ASTContext &Ctx,
                    ImplicitConversionModellingMode ImplicitMode) {
  LLVM_DEBUG(llvm::dbgs() << ">>> calculateMixability for LType:\n";
             LType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
             RType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);
  if (LType == RType) {
    LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Trivial equality.\n");
    return {MixFlags::Trivial, LType};
  }

  // Dissolve certain type sugars that do not affect the mixability of one type
  // with the other, and also do not require any sort of elaboration for the
  // user to understand.
  if (isUselessSugar(LType.getTypePtr())) {
    LLVM_DEBUG(llvm::dbgs()
               << "--- calculateMixability. LHS is useless sugar.\n");
    return calculateMixability(Check, LType.getSingleStepDesugaredType(Ctx),
                               RType, Ctx, ImplicitMode);
  }
  if (isUselessSugar(RType.getTypePtr())) {
    LLVM_DEBUG(llvm::dbgs()
               << "--- calculateMixability. RHS is useless sugar.\n");
    return calculateMixability(
        Check, LType, RType.getSingleStepDesugaredType(Ctx), Ctx, ImplicitMode);
  }

  const auto *LLRef = LType->getAs<LValueReferenceType>();
  const auto *RLRef = RType->getAs<LValueReferenceType>();
  if (LLRef && RLRef) {
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS and RHS are &.\n");

    return calculateMixability(Check, LLRef->getPointeeType(),
                               RLRef->getPointeeType(), Ctx, ImplicitMode)
        .withCommonTypeTransformed(
            [&Ctx](QualType QT) { return Ctx.getLValueReferenceType(QT); });
  }
  // At a particular call site, what could be passed to a 'T' or 'const T' might
  // also be passed to a 'const T &' without the call site putting a direct
  // side effect on the passed expressions.
  if (LLRef) {
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS is &.\n");
    return isLRefEquallyBindingToType(Check, LLRef, RType, Ctx, false,
                                      ImplicitMode) |
           MixFlags::ReferenceBind;
  }
  if (RLRef) {
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. RHS is &.\n");
    return isLRefEquallyBindingToType(Check, RLRef, LType, Ctx, true,
                                      ImplicitMode) |
           MixFlags::ReferenceBind;
  }

  if (LType->getAs<TypedefType>()) {
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. LHS is typedef.\n");
    return calculateMixability(Check, LType.getSingleStepDesugaredType(Ctx),
                               RType, Ctx, ImplicitMode) |
           MixFlags::TypeAlias;
  }
  if (RType->getAs<TypedefType>()) {
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. RHS is typedef.\n");
    return calculateMixability(Check, LType,
                               RType.getSingleStepDesugaredType(Ctx), Ctx,
                               ImplicitMode) |
           MixFlags::TypeAlias;
  }

  // A parameter of type 'cvr1 T' and another of potentially differently
  // qualified 'cvr2 T' may bind with the same power, if the user so requested.
  //
  // Whether to do this check for the inner unqualified types.
  bool CompareUnqualifiedTypes = false;
  if (LType.getLocalCVRQualifiers() != RType.getLocalCVRQualifiers()) {
    LLVM_DEBUG(if (LType.getLocalCVRQualifiers()) {
      llvm::dbgs() << "--- calculateMixability. LHS has CVR-Qualifiers: ";
      Qualifiers::fromCVRMask(LType.getLocalCVRQualifiers())
          .print(llvm::dbgs(), Ctx.getPrintingPolicy());
      llvm::dbgs() << '\n';
    });
    LLVM_DEBUG(if (RType.getLocalCVRQualifiers()) {
      llvm::dbgs() << "--- calculateMixability. RHS has CVR-Qualifiers: ";
      Qualifiers::fromCVRMask(RType.getLocalCVRQualifiers())
          .print(llvm::dbgs(), Ctx.getPrintingPolicy());
      llvm::dbgs() << '\n';
    });

    if (!Check.QualifiersMix) {
      LLVM_DEBUG(llvm::dbgs()
                 << "<<< calculateMixability. QualifiersMix turned off - not "
                    "mixable.\n");
      return {MixFlags::None};
    }

    CompareUnqualifiedTypes = true;
  }
  // Whether the two types had the same CVR qualifiers.
  bool OriginallySameQualifiers = false;
  if (LType.getLocalCVRQualifiers() == RType.getLocalCVRQualifiers() &&
      LType.getLocalCVRQualifiers() != 0) {
    LLVM_DEBUG(if (LType.getLocalCVRQualifiers()) {
      llvm::dbgs()
          << "--- calculateMixability. LHS and RHS have same CVR-Qualifiers: ";
      Qualifiers::fromCVRMask(LType.getLocalCVRQualifiers())
          .print(llvm::dbgs(), Ctx.getPrintingPolicy());
      llvm::dbgs() << '\n';
    });

    CompareUnqualifiedTypes = true;
    OriginallySameQualifiers = true;
  }

  if (CompareUnqualifiedTypes) {
    NonCVRQualifiersResult AdditionalQuals =
        getNonCVRQualifiers(Ctx, LType, RType);
    if (AdditionalQuals.HasMixabilityBreakingQualifiers) {
      LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Additional "
                                 "non-equal incompatible qualifiers.\n");
      return {MixFlags::None};
    }

    MixData UnqualifiedMixability =
        calculateMixability(Check, LType.getLocalUnqualifiedType(),
                            RType.getLocalUnqualifiedType(), Ctx, ImplicitMode)
            .withCommonTypeTransformed([&AdditionalQuals, &Ctx](QualType QT) {
              // Once the mixability was deduced, apply the qualifiers common
              // to the two type back onto the diagnostic printout.
              return Ctx.getQualifiedType(QT, AdditionalQuals.CommonQualifiers);
            });

    if (!OriginallySameQualifiers)
      // User-enabled qualifier change modelled for the mix.
      return UnqualifiedMixability | MixFlags::Qualifiers;

    // Apply the same qualifier back into the found common type if they were
    // the same.
    return UnqualifiedMixability.withCommonTypeTransformed(
        [&Ctx, LType](QualType QT) {
          return Ctx.getQualifiedType(QT, LType.getLocalQualifiers());
        });
  }

  // Certain constructs match on the last catch-all getCanonicalType() equality,
  // which is perhaps something not what we want. If this variable is true,
  // the canonical type equality will be ignored.
  bool RecursiveReturnDiscardingCanonicalType = false;

  if (LType->isPointerType() && RType->isPointerType()) {
    // If both types are pointers, and pointed to the exact same type,
    // LType == RType took care of that. Try to see if the pointee type has
    // some other match. However, this must not consider implicit conversions.
    LLVM_DEBUG(llvm::dbgs()
               << "--- calculateMixability. LHS and RHS are Ptrs.\n");
    MixData MixOfPointee =
        calculateMixability(Check, LType->getPointeeType(),
                            RType->getPointeeType(), Ctx,
                            ImplicitConversionModellingMode::None)
            .withCommonTypeTransformed(
                [&Ctx](QualType QT) { return Ctx.getPointerType(QT); });
    if (hasFlag(MixOfPointee.Flags,
                MixFlags::WorkaroundDisableCanonicalEquivalence))
      RecursiveReturnDiscardingCanonicalType = true;

    MixOfPointee.sanitize();
    if (MixOfPointee.indicatesMixability()) {
      LLVM_DEBUG(llvm::dbgs()
                 << "<<< calculateMixability. Pointees are mixable.\n");
      return MixOfPointee;
    }
  }

  if (ImplicitMode > ImplicitConversionModellingMode::None) {
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Start implicit...\n");
    MixData MixLTR =
        approximateImplicitConversion(Check, LType, RType, Ctx, ImplicitMode);
    LLVM_DEBUG(
        if (hasFlag(MixLTR.Flags, MixFlags::ImplicitConversion)) llvm::dbgs()
            << "--- calculateMixability. Implicit Left -> Right found.\n";);

    if (ImplicitMode ==
            ImplicitConversionModellingMode::OneWaySingleStandardOnly &&
        MixLTR.Conversion && !MixLTR.Conversion.AfterFirstStandard.isNull() &&
        MixLTR.Conversion.UDConvKind == ConversionSequence::UDCK_None &&
        MixLTR.Conversion.AfterSecondStandard.isNull()) {
      // The invoker of the method requested only modelling a single standard
      // conversion, in only the forward direction, and they got just that.
      LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Implicit "
                                 "conversion, one-way, standard-only.\n");
      return {MixFlags::ImplicitConversion, MixLTR.Conversion};
    }

    // Otherwise if the invoker requested a full modelling, do the other
    // direction as well.
    MixData MixRTL =
        approximateImplicitConversion(Check, RType, LType, Ctx, ImplicitMode);
    LLVM_DEBUG(
        if (hasFlag(MixRTL.Flags, MixFlags::ImplicitConversion)) llvm::dbgs()
            << "--- calculateMixability. Implicit Right -> Left found.\n";);

    if (MixLTR.Conversion && MixRTL.Conversion) {
      LLVM_DEBUG(
          llvm::dbgs()
          << "<<< calculateMixability. Implicit conversion, bidirectional.\n");
      return {MixFlags::ImplicitConversion, MixLTR.Conversion,
              MixRTL.Conversion};
    }
  }

  if (RecursiveReturnDiscardingCanonicalType)
    LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Before CanonicalType, "
                               "Discard was enabled.\n");

  // Certain kinds unfortunately need to be side-stepped for canonical type
  // matching.
  if (LType->getAs<FunctionProtoType>() || RType->getAs<FunctionProtoType>()) {
    // Unfortunately, the canonical type of a function pointer becomes the
    // same even if exactly one is "noexcept" and the other isn't, making us
    // give a false positive report irrespective of implicit conversions.
    LLVM_DEBUG(llvm::dbgs()
               << "--- calculateMixability. Discarding potential canonical "
                  "equivalence on FunctionProtoTypes.\n");
    RecursiveReturnDiscardingCanonicalType = true;
  }

  MixData MixToReturn{MixFlags::None};

  // If none of the previous logic found a match, try if Clang otherwise
  // believes the types to be the same.
  QualType LCanonical = LType.getCanonicalType();
  if (LCanonical == RType.getCanonicalType()) {
    LLVM_DEBUG(llvm::dbgs()
               << "<<< calculateMixability. Same CanonicalType.\n");
    MixToReturn = {MixFlags::Canonical, LCanonical};
  }

  if (RecursiveReturnDiscardingCanonicalType)
    MixToReturn |= MixFlags::WorkaroundDisableCanonicalEquivalence;

  LLVM_DEBUG(if (MixToReturn.Flags == MixFlags::None) llvm::dbgs()
             << "<<< calculateMixability. No match found.\n");
  return MixToReturn;
}

/// Calculates if the reference binds an expression of the given type. This is
/// true iff 'LRef' is some 'const T &' type, and the 'Ty' is 'T' or 'const T'.
///
/// \param ImplicitMode is forwarded in the possible recursive call to
/// calculateMixability.
static MixData
isLRefEquallyBindingToType(const TheCheck &Check,
                           const LValueReferenceType *LRef, QualType Ty,
                           const ASTContext &Ctx, bool IsRefRHS,
                           ImplicitConversionModellingMode ImplicitMode) {
  LLVM_DEBUG(llvm::dbgs() << ">>> isLRefEquallyBindingToType for LRef:\n";
             LRef->dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand Type:\n";
             Ty.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);

  QualType ReferredType = LRef->getPointeeType();
  if (!ReferredType.isLocalConstQualified() &&
      ReferredType->getAs<TypedefType>()) {
    LLVM_DEBUG(
        llvm::dbgs()
        << "--- isLRefEquallyBindingToType. Non-const LRef to Typedef.\n");
    ReferredType = ReferredType.getDesugaredType(Ctx);
    if (!ReferredType.isLocalConstQualified()) {
      LLVM_DEBUG(llvm::dbgs()
                 << "<<< isLRefEquallyBindingToType. Typedef is not const.\n");
      return {MixFlags::None};
    }

    LLVM_DEBUG(llvm::dbgs() << "--- isLRefEquallyBindingToType. Typedef is "
                               "const, considering as const LRef.\n");
  } else if (!ReferredType.isLocalConstQualified()) {
    LLVM_DEBUG(llvm::dbgs()
               << "<<< isLRefEquallyBindingToType. Not const LRef.\n");
    return {MixFlags::None};
  };

  assert(ReferredType.isLocalConstQualified() &&
         "Reaching this point means we are sure LRef is effectively a const&.");

  if (ReferredType == Ty) {
    LLVM_DEBUG(
        llvm::dbgs()
        << "<<< isLRefEquallyBindingToType. Type of referred matches.\n");
    return {MixFlags::Trivial, ReferredType};
  }

  QualType NonConstReferredType = ReferredType;
  NonConstReferredType.removeLocalConst();
  if (NonConstReferredType == Ty) {
    LLVM_DEBUG(llvm::dbgs() << "<<< isLRefEquallyBindingToType. Type of "
                               "referred matches to non-const qualified.\n");
    return {MixFlags::Trivial, NonConstReferredType};
  }

  LLVM_DEBUG(
      llvm::dbgs()
      << "--- isLRefEquallyBindingToType. Checking mix for underlying type.\n");
  return IsRefRHS ? calculateMixability(Check, Ty, NonConstReferredType, Ctx,
                                        ImplicitMode)
                  : calculateMixability(Check, NonConstReferredType, Ty, Ctx,
                                        ImplicitMode);
}

static inline bool isDerivedToBase(const CXXRecordDecl *Derived,
                                   const CXXRecordDecl *Base) {
  return Derived && Base && Derived->isCompleteDefinition() &&
         Base->isCompleteDefinition() && Derived->isDerivedFrom(Base);
}

static std::optional<QualType>
approximateStandardConversionSequence(const TheCheck &Check, QualType From,
                                      QualType To, const ASTContext &Ctx) {
  LLVM_DEBUG(llvm::dbgs() << ">>> approximateStdConv for LType:\n";
             From.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
             To.dump(llvm::dbgs(), Ctx); llvm::dbgs() << '\n';);

  // A standard conversion sequence consists of the following, in order:
  //  * Maybe either LValue->RValue conv., Array->Ptr conv., Function->Ptr conv.
  //  * Maybe Numeric promotion or conversion.
  //  * Maybe function pointer conversion.
  //  * Maybe qualifier adjustments.
  QualType WorkType = From;
  // Get out the qualifiers of the original type. This will always be
  // re-applied to the WorkType to ensure it is the same qualification as the
  // original From was.
  auto QualifiersToApply = From.split().Quals.getAsOpaqueValue();

  // LValue->RValue is irrelevant for the check, because it is a thing to be
  // done at a call site, and will be performed if need be performed.

  // Array->Pointer decay is handled by the main method in desugaring
  // the parameter's DecayedType as "useless sugar".

  // Function->Pointer conversions are also irrelevant, because a
  // "FunctionType" cannot be the type of a parameter variable, so this
  // conversion is only meaningful at call sites.

  // Numeric promotions and conversions.
  const auto *FromBuiltin = WorkType->getAs<BuiltinType>();
  const auto *ToBuiltin = To->getAs<BuiltinType>();
  bool FromNumeric = FromBuiltin && (FromBuiltin->isIntegerType() ||
                                     FromBuiltin->isFloatingType());
  bool ToNumeric =
      ToBuiltin && (ToBuiltin->isIntegerType() || ToBuiltin->isFloatingType());
  if (FromNumeric && ToNumeric) {
    // If both are integral types, the numeric conversion is performed.
    // Reapply the qualifiers of the original type, however, so
    // "const int -> double" in this case moves over to
    // "const double -> double".
    LLVM_DEBUG(llvm::dbgs()
               << "--- approximateStdConv. Conversion between numerics.\n");
    WorkType = QualType{ToBuiltin, QualifiersToApply};
  }

  const auto *FromEnum = WorkType->getAs<EnumType>();
  const auto *ToEnum = To->getAs<EnumType>();
  if (FromEnum && ToNumeric && FromEnum->isUnscopedEnumerationType()) {
    // Unscoped enumerations (or enumerations in C) convert to numerics.
    LLVM_DEBUG(llvm::dbgs()
               << "--- approximateStdConv. Unscoped enum to numeric.\n");
    WorkType = QualType{ToBuiltin, QualifiersToApply};
  } else if (FromNumeric && ToEnum && ToEnum->isUnscopedEnumerationType()) {
    // Numeric types convert to enumerations only in C.
    if (Ctx.getLangOpts().CPlusPlus) {
      LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Numeric to unscoped "
                                 "enum, not possible in C++!\n");
      return {};
    }

    LLVM_DEBUG(llvm::dbgs()
               << "--- approximateStdConv. Numeric to unscoped enum.\n");
    WorkType = QualType{ToEnum, QualifiersToApply};
  }

  // Check for pointer conversions.
  const auto *FromPtr = WorkType->getAs<PointerType>();
  const auto *ToPtr = To->getAs<PointerType>();
  if (FromPtr && ToPtr) {
    if (ToPtr->isVoidPointerType()) {
      LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n");
      WorkType = QualType{ToPtr, QualifiersToApply};
    }

    const auto *FromRecordPtr = FromPtr->getPointeeCXXRecordDecl();
    const auto *ToRecordPtr = ToPtr->getPointeeCXXRecordDecl();
    if (isDerivedToBase(FromRecordPtr, ToRecordPtr)) {
      LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n");
      WorkType = QualType{ToPtr, QualifiersToApply};
    }
  }

  // Model the slicing Derived-to-Base too, as "BaseT temporary = derived;"
  // can also be compiled.
  const auto *FromRecord = WorkType->getAsCXXRecordDecl();
  const auto *ToRecord = To->getAsCXXRecordDecl();
  if (isDerivedToBase(FromRecord, ToRecord)) {
    LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n");
    WorkType = QualType{ToRecord->getTypeForDecl(), QualifiersToApply};
  }

  if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) {
    // Function pointer conversion: A noexcept function pointer can be passed
    // to a non-noexcept one.
    const auto *FromFunctionPtr =
        FromPtr->getPointeeType()->getAs<FunctionProtoType>();
    const auto *ToFunctionPtr =
        ToPtr->getPointeeType()->getAs<FunctionProtoType>();
    if (FromFunctionPtr && ToFunctionPtr &&
        FromFunctionPtr->hasNoexceptExceptionSpec() &&
        !ToFunctionPtr->hasNoexceptExceptionSpec()) {
      LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function "
                                 "pointer to non-noexcept.\n");
      WorkType = QualType{ToPtr, QualifiersToApply};
    }
  }

  // Qualifier adjustments are modelled according to the user's request in
  // the QualifiersMix check config.
  LLVM_DEBUG(llvm::dbgs()
             << "--- approximateStdConv. Trying qualifier adjustment...\n");
  MixData QualConv = calculateMixability(Check, WorkType, To, Ctx,
                                         ImplicitConversionModellingMode::None);
  QualConv.sanitize();
  if (hasFlag(QualConv.Flags, MixFlags::Qualifiers)) {
    LLVM_DEBUG(llvm::dbgs()
               << "<<< approximateStdConv. Qualifiers adjusted.\n");
    WorkType = To;
  }

  if (WorkType == To) {
    LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Reached 'To' type.\n");
    return {WorkType};
  }

  LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Did not reach 'To'.\n");
  return {};
}

namespace {

/// Helper class for storing possible user-defined conversion calls that
/// *could* take place in an implicit conversion, and selecting the one that
/// most likely *does*, if any.
class UserDefinedConversionSelector {
public:
  /// The conversion associated with a conversion function, together with the
  /// mixability flags of the conversion function's parameter or return type
  /// to the rest of the sequence the selector is used in, and the sequence
  /// that applied through the conversion itself.
  struct PreparedConversion {
    const CXXMethodDecl *ConversionFun;
    MixFlags Flags;
    ConversionSequence Seq;

    PreparedConversion(const CXXMethodDecl *CMD, MixFlags F,
                       ConversionSequence S)
        : ConversionFun(CMD), Flags(F), Seq(S) {}
  };

  UserDefinedConversionSelector(const TheCheck &Check) : Check(Check) {}

  /// Adds the conversion between the two types for the given function into
  /// the possible implicit conversion set. FromType and ToType is either:
  ///   * the result of a standard sequence and a converting ctor parameter
  ///   * the return type of a conversion operator and the expected target of
  ///     an implicit conversion.
  void addConversion(const CXXMethodDecl *ConvFun, QualType FromType,
                     QualType ToType) {
    // Try to go from the FromType to the ToType with only a single implicit
    // conversion, to see if the conversion function is applicable.
    MixData Mix = calculateMixability(
        Check, FromType, ToType, ConvFun->getASTContext(),
        ImplicitConversionModellingMode::OneWaySingleStandardOnly);
    Mix.sanitize();
    if (!Mix.indicatesMixability())
      return;

    LLVM_DEBUG(llvm::dbgs() << "--- tryConversion. Found viable with flags: "
                            << formatMixFlags(Mix.Flags) << '\n');
    FlaggedConversions.emplace_back(ConvFun, Mix.Flags, Mix.Conversion);
  }

  /// Selects the best conversion function that is applicable from the
  /// prepared set of potential conversion functions taken.
  std::optional<PreparedConversion> operator()() const {
    if (FlaggedConversions.empty()) {
      LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Empty.\n");
      return {};
    }
    if (FlaggedConversions.size() == 1) {
      LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Single.\n");
      return FlaggedConversions.front();
    }

    std::optional<PreparedConversion> BestConversion;
    unsigned short HowManyGoodConversions = 0;
    for (const auto &Prepared : FlaggedConversions) {
      LLVM_DEBUG(llvm::dbgs() << "--- selectUserDefinedConv. Candidate flags: "
                              << formatMixFlags(Prepared.Flags) << '\n');
      if (!BestConversion) {
        BestConversion = Prepared;
        ++HowManyGoodConversions;
        continue;
      }

      bool BestConversionHasImplicit =
          hasFlag(BestConversion->Flags, MixFlags::ImplicitConversion);
      bool ThisConversionHasImplicit =
          hasFlag(Prepared.Flags, MixFlags::ImplicitConversion);
      if (!BestConversionHasImplicit && ThisConversionHasImplicit)
        // This is a worse conversion, because a better one was found earlier.
        continue;

      if (BestConversionHasImplicit && !ThisConversionHasImplicit) {
        // If the so far best selected conversion needs a previous implicit
        // conversion to match the user-defined converting function, but this
        // conversion does not, this is a better conversion, and we can throw
        // away the previously selected conversion(s).
        BestConversion = Prepared;
        HowManyGoodConversions = 1;
        continue;
      }

      if (BestConversionHasImplicit == ThisConversionHasImplicit)
        // The current conversion is the same in term of goodness than the
        // already selected one.
        ++HowManyGoodConversions;
    }

    if (HowManyGoodConversions == 1) {
      LLVM_DEBUG(llvm::dbgs()
                 << "--- selectUserDefinedConv. Unique result. Flags: "
                 << formatMixFlags(BestConversion->Flags) << '\n');
      return BestConversion;
    }

    LLVM_DEBUG(llvm::dbgs()
               << "--- selectUserDefinedConv. No, or ambiguous.\n");
    return {};
  }

private:
  llvm::SmallVector<PreparedConversion, 2> FlaggedConversions;
  const TheCheck &Check;
};

} // namespace

static std::optional<ConversionSequence>
tryConversionOperators(const TheCheck &Check, const CXXRecordDecl *RD,
                       QualType ToType) {
  if (!RD || !RD->isCompleteDefinition())
    return {};
  RD = RD->getDefinition();

  LLVM_DEBUG(llvm::dbgs() << ">>> tryConversionOperators: " << RD->getName()
                          << " to:\n";
             ToType.dump(llvm::dbgs(), RD->getASTContext());
             llvm::dbgs() << '\n';);

  UserDefinedConversionSelector ConversionSet{Check};

  for (const NamedDecl *Method : RD->getVisibleConversionFunctions()) {
    const auto *Con = dyn_cast<CXXConversionDecl>(Method);
    if (!Con || Con->isExplicit())
      continue;
    LLVM_DEBUG(llvm::dbgs() << "--- tryConversionOperators. Trying:\n";
               Con->dump(llvm::dbgs()); llvm::dbgs() << '\n';);

    // Try to go from the result of conversion operator to the expected type,
    // without calculating another user-defined conversion.
    ConversionSet.addConversion(Con, Con->getConversionType(), ToType);
  }

  if (std::optional<UserDefinedConversionSelector::PreparedConversion>
          SelectedConversion = ConversionSet()) {
    QualType RecordType{RD->getTypeForDecl(), 0};

    ConversionSequence Result{RecordType, ToType};
    // The conversion from the operator call's return type to ToType was
    // modelled as a "pre-conversion" in the operator call, but it is the
    // "post-conversion" from the point of view of the original conversion
    // we are modelling.
    Result.AfterSecondStandard = SelectedConversion->Seq.AfterFirstStandard;

    ConversionSequence::UserDefinedConversionOperator ConvOp;
    ConvOp.Fun = cast<CXXConversionDecl>(SelectedConversion->ConversionFun);
    ConvOp.UserDefinedType = RecordType;
    ConvOp.ConversionOperatorResultType = ConvOp.Fun->getConversionType();
    Result.setConversion(ConvOp);

    LLVM_DEBUG(llvm::dbgs() << "<<< tryConversionOperators. Found result.\n");
    return Result;
  }

  LLVM_DEBUG(llvm::dbgs() << "<<< tryConversionOperators. No conversion.\n");
  return {};
}

static std::optional<ConversionSequence>
tryConvertingConstructors(const TheCheck &Check, QualType FromType,
                          const CXXRecordDecl *RD) {
  if (!RD || !RD->isCompleteDefinition())
    return {};
  RD = RD->getDefinition();

  LLVM_DEBUG(llvm::dbgs() << ">>> tryConveringConstructors: " << RD->getName()
                          << " from:\n";
             FromType.dump(llvm::dbgs(), RD->getASTContext());
             llvm::dbgs() << '\n';);

  UserDefinedConversionSelector ConversionSet{Check};

  for (const CXXConstructorDecl *Con : RD->ctors()) {
    if (Con->isCopyOrMoveConstructor() ||
        !Con->isConvertingConstructor(/* AllowExplicit =*/false))
      continue;
    LLVM_DEBUG(llvm::dbgs() << "--- tryConvertingConstructors. Trying:\n";
               Con->dump(llvm::dbgs()); llvm::dbgs() << '\n';);

    // Try to go from the original FromType to the converting constructor's
    // parameter type without another user-defined conversion.
    ConversionSet.addConversion(Con, FromType, Con->getParamDecl(0)->getType());
  }

  if (std::optional<UserDefinedConversionSelector::PreparedConversion>
          SelectedConversion = ConversionSet()) {
    QualType RecordType{RD->getTypeForDecl(), 0};

    ConversionSequence Result{FromType, RecordType};
    Result.AfterFirstStandard = SelectedConversion->Seq.AfterFirstStandard;

    ConversionSequence::UserDefinedConvertingConstructor Ctor;
    Ctor.Fun = cast<CXXConstructorDecl>(SelectedConversion->ConversionFun);
    Ctor.ConstructorParameterType = Ctor.Fun->getParamDecl(0)->getType();
    Ctor.UserDefinedType = RecordType;
    Result.setConversion(Ctor);

    LLVM_DEBUG(llvm::dbgs()
               << "<<< tryConvertingConstructors. Found result.\n");
    return Result;
  }

  LLVM_DEBUG(llvm::dbgs() << "<<< tryConvertingConstructors. No conversion.\n");
  return {};
}

/// Returns whether an expression of LType can be used in an RType context, as
/// per the implicit conversion rules.
///
/// Note: the result of this operation, unlike that of calculateMixability, is
/// **NOT** symmetric.
static MixData
approximateImplicitConversion(const TheCheck &Check, QualType LType,
                              QualType RType, const ASTContext &Ctx,
                              ImplicitConversionModellingMode ImplicitMode) {
  LLVM_DEBUG(llvm::dbgs() << ">>> approximateImplicitConversion for LType:\n";
             LType.dump(llvm::dbgs(), Ctx); llvm::dbgs() << "\nand RType:\n";
             RType.dump(llvm::dbgs(), Ctx);
             llvm::dbgs() << "\nimplicit mode: "; switch (ImplicitMode) {
               case ImplicitConversionModellingMode::None:
                 llvm::dbgs() << "None";
                 break;
               case ImplicitConversionModellingMode::All:
                 llvm::dbgs() << "All";
                 break;
               case ImplicitConversionModellingMode::OneWaySingleStandardOnly:
                 llvm::dbgs() << "OneWay, Single, STD Only";
                 break;
             } llvm::dbgs() << '\n';);
  if (LType == RType)
    return {MixFlags::Trivial, LType};

  // An implicit conversion sequence consists of the following, in order:
  //  * Maybe standard conversion sequence.
  //  * Maybe user-defined conversion.
  //  * Maybe standard conversion sequence.
  ConversionSequence ImplicitSeq{LType, RType};
  QualType WorkType = LType;

  std::optional<QualType> AfterFirstStdConv =
      approximateStandardConversionSequence(Check, LType, RType, Ctx);
  if (AfterFirstStdConv) {
    LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Standard "
                               "Pre-Conversion found!\n");
    ImplicitSeq.AfterFirstStandard = *AfterFirstStdConv;
    WorkType = ImplicitSeq.AfterFirstStandard;
  }

  if (ImplicitMode == ImplicitConversionModellingMode::OneWaySingleStandardOnly)
    // If the caller only requested modelling of a standard conversion, bail.
    return {ImplicitSeq.AfterFirstStandard.isNull()
                ? MixFlags::None
                : MixFlags::ImplicitConversion,
            ImplicitSeq};

  if (Ctx.getLangOpts().CPlusPlus) {
    bool FoundConversionOperator = false, FoundConvertingCtor = false;

    if (const auto *LRD = WorkType->getAsCXXRecordDecl()) {
      std::optional<ConversionSequence> ConversionOperatorResult =
          tryConversionOperators(Check, LRD, RType);
      if (ConversionOperatorResult) {
        LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Found "
                                   "conversion operator.\n");
        ImplicitSeq.update(*ConversionOperatorResult);
        WorkType = ImplicitSeq.getTypeAfterUserDefinedConversion();
        FoundConversionOperator = true;
      }
    }

    if (const auto *RRD = RType->getAsCXXRecordDecl()) {
      // Use the original "LType" here, and not WorkType, because the
      // conversion to the converting constructors' parameters will be
      // modelled in the recursive call.
      std::optional<ConversionSequence> ConvCtorResult =
          tryConvertingConstructors(Check, LType, RRD);
      if (ConvCtorResult) {
        LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Found "
                                   "converting constructor.\n");
        ImplicitSeq.update(*ConvCtorResult);
        WorkType = ImplicitSeq.getTypeAfterUserDefinedConversion();
        FoundConvertingCtor = true;
      }
    }

    if (FoundConversionOperator && FoundConvertingCtor) {
      // If both an operator and a ctor matches, the sequence is ambiguous.
      LLVM_DEBUG(llvm::dbgs()
                 << "<<< approximateImplicitConversion. Found both "
                    "user-defined conversion kinds in the same sequence!\n");
      return {MixFlags::None};
    }
  }

  // After the potential user-defined conversion, another standard conversion
  // sequence might exist.
  LLVM_DEBUG(
      llvm::dbgs()
      << "--- approximateImplicitConversion. Try to find post-conversion.\n");
  MixData SecondStdConv = approximateImplicitConversion(
      Check, WorkType, RType, Ctx,
      ImplicitConversionModellingMode::OneWaySingleStandardOnly);
  if (SecondStdConv.indicatesMixability()) {
    LLVM_DEBUG(llvm::dbgs() << "--- approximateImplicitConversion. Standard "
                               "Post-Conversion found!\n");

    // The single-step modelling puts the modelled conversion into the "PreStd"
    // variable in the recursive call, but from the PoV of this function, it is
    // the post-conversion.
    ImplicitSeq.AfterSecondStandard =
        SecondStdConv.Conversion.AfterFirstStandard;
    WorkType = ImplicitSeq.AfterSecondStandard;
  }

  if (ImplicitSeq) {
    LLVM_DEBUG(llvm::dbgs()
               << "<<< approximateImplicitConversion. Found a conversion.\n");
    return {MixFlags::ImplicitConversion, ImplicitSeq};
  }

  LLVM_DEBUG(
      llvm::dbgs() << "<<< approximateImplicitConversion. No match found.\n");
  return {MixFlags::None};
}

static MixableParameterRange modelMixingRange(
    const TheCheck &Check, const FunctionDecl *FD, std::size_t StartIndex,
    const filter::SimilarlyUsedParameterPairSuppressor &UsageBasedSuppressor) {
  std::size_t NumParams = FD->getNumParams();
  assert(StartIndex < NumParams && "out of bounds for start");
  const ASTContext &Ctx = FD->getASTContext();

  MixableParameterRange Ret;
  // A parameter at index 'StartIndex' had been trivially "checked".
  Ret.NumParamsChecked = 1;

  for (std::size_t I = StartIndex + 1; I < NumParams; ++I) {
    const ParmVarDecl *Ith = FD->getParamDecl(I);
    StringRef ParamName = Ith->getName();
    LLVM_DEBUG(llvm::dbgs()
               << "Check param #" << I << " '" << ParamName << "'...\n");
    if (filter::isIgnoredParameter(Check, Ith)) {
      LLVM_DEBUG(llvm::dbgs() << "Param #" << I << " is ignored. Break!\n");
      break;
    }

    StringRef PrevParamName = FD->getParamDecl(I - 1)->getName();
    if (!ParamName.empty() && !PrevParamName.empty() &&
        filter::prefixSuffixCoverUnderThreshold(
            Check.NamePrefixSuffixSilenceDissimilarityTreshold, PrevParamName,
            ParamName)) {
      LLVM_DEBUG(llvm::dbgs() << "Parameter '" << ParamName
                              << "' follows a pattern with previous parameter '"
                              << PrevParamName << "'. Break!\n");
      break;
    }

    // Now try to go forward and build the range of [Start, ..., I, I + 1, ...]
    // parameters that can be messed up at a call site.
    MixableParameterRange::MixVector MixesOfIth;
    for (std::size_t J = StartIndex; J < I; ++J) {
      const ParmVarDecl *Jth = FD->getParamDecl(J);
      LLVM_DEBUG(llvm::dbgs()
                 << "Check mix of #" << J << " against #" << I << "...\n");

      if (isSimilarlyUsedParameter(UsageBasedSuppressor, Ith, Jth)) {
        // Consider the two similarly used parameters to not be possible in a
        // mix-up at the user's request, if they enabled this heuristic.
        LLVM_DEBUG(llvm::dbgs() << "Parameters #" << I << " and #" << J
                                << " deemed related, ignoring...\n");

        // If the parameter #I and #J mixes, then I is mixable with something
        // in the current range, so the range has to be broken and I not
        // included.
        MixesOfIth.clear();
        break;
      }

      Mix M{Jth, Ith,
            calculateMixability(Check, Jth->getType(), Ith->getType(), Ctx,
                                Check.ModelImplicitConversions
                                    ? ImplicitConversionModellingMode::All
                                    : ImplicitConversionModellingMode::None)};
      LLVM_DEBUG(llvm::dbgs() << "Mix flags (raw)           : "
                              << formatMixFlags(M.flags()) << '\n');
      M.sanitize();
      LLVM_DEBUG(llvm::dbgs() << "Mix flags (after sanitize): "
                              << formatMixFlags(M.flags()) << '\n');

      assert(M.flagsValid() && "All flags decayed!");

      if (M.mixable())
        MixesOfIth.emplace_back(std::move(M));
    }

    if (MixesOfIth.empty()) {
      // If there weren't any new mixes stored for Ith, the range is
      // [Start, ..., I].
      LLVM_DEBUG(llvm::dbgs()
                 << "Param #" << I
                 << " does not mix with any in the current range. Break!\n");
      break;
    }

    Ret.Mixes.insert(Ret.Mixes.end(), MixesOfIth.begin(), MixesOfIth.end());
    ++Ret.NumParamsChecked; // Otherwise a new param was iterated.
  }

  return Ret;
}

} // namespace model

/// Matches DeclRefExprs and their ignorable wrappers to ParmVarDecls.
AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<Stmt>, paramRefExpr) {
  return expr(ignoringParenImpCasts(ignoringElidableConstructorCall(
      declRefExpr(to(parmVarDecl().bind("param"))))));
}

namespace filter {

/// Returns whether the parameter's name or the parameter's type's name is
/// configured by the user to be ignored from analysis and diagnostic.
static bool isIgnoredParameter(const TheCheck &Check, const ParmVarDecl *Node) {
  LLVM_DEBUG(llvm::dbgs() << "Checking if '" << Node->getName()
                          << "' is ignored.\n");

  if (!Node->getIdentifier())
    return llvm::is_contained(Check.IgnoredParameterNames, "\"\"");

  StringRef NodeName = Node->getName();
  if (llvm::is_contained(Check.IgnoredParameterNames, NodeName)) {
    LLVM_DEBUG(llvm::dbgs() << "\tName ignored.\n");
    return true;
  }

  StringRef NodeTypeName = [Node] {
    const ASTContext &Ctx = Node->getASTContext();
    const SourceManager &SM = Ctx.getSourceManager();
    SourceLocation B = Node->getTypeSpecStartLoc();
    SourceLocation E = Node->getTypeSpecEndLoc();
    LangOptions LO;

    LLVM_DEBUG(llvm::dbgs() << "\tType name code is '"
                            << Lexer::getSourceText(
                                   CharSourceRange::getTokenRange(B, E), SM, LO)
                            << "'...\n");
    if (B.isMacroID()) {
      LLVM_DEBUG(llvm::dbgs() << "\t\tBeginning is macro.\n");
      B = SM.getTopMacroCallerLoc(B);
    }
    if (E.isMacroID()) {
      LLVM_DEBUG(llvm::dbgs() << "\t\tEnding is macro.\n");
      E = Lexer::getLocForEndOfToken(SM.getTopMacroCallerLoc(E), 0, SM, LO);
    }
    LLVM_DEBUG(llvm::dbgs() << "\tType name code is '"
                            << Lexer::getSourceText(
                                   CharSourceRange::getTokenRange(B, E), SM, LO)
                            << "'...\n");

    return Lexer::getSourceText(CharSourceRange::getTokenRange(B, E), SM, LO);
  }();

  LLVM_DEBUG(llvm::dbgs() << "\tType name is '" << NodeTypeName << "'\n");
  if (!NodeTypeName.empty()) {
    if (llvm::any_of(Check.IgnoredParameterTypeSuffixes,
                     [NodeTypeName](StringRef E) {
                       return !E.empty() && NodeTypeName.ends_with(E);
                     })) {
      LLVM_DEBUG(llvm::dbgs() << "\tType suffix ignored.\n");
      return true;
    }
  }

  return false;
}

/// This namespace contains the implementations for the suppression of
/// diagnostics from similarly-used ("related") parameters.
namespace relatedness_heuristic {

static constexpr std::size_t SmallDataStructureSize = 4;

template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallSetMap =
    llvm::DenseMap<const ParmVarDecl *, llvm::SmallSet<T, N>>;

/// Returns whether the sets mapped to the two elements in the map have at
/// least one element in common.
template <typename MapTy, typename ElemTy>
bool lazyMapOfSetsIntersectionExists(const MapTy &Map, const ElemTy &E1,
                                     const ElemTy &E2) {
  auto E1Iterator = Map.find(E1);
  auto E2Iterator = Map.find(E2);
  if (E1Iterator == Map.end() || E2Iterator == Map.end())
    return false;

  for (const auto &E1SetElem : E1Iterator->second)
    if (E2Iterator->second.contains(E1SetElem))
      return true;

  return false;
}

/// Implements the heuristic that marks two parameters related if there is
/// a usage for both in the same strict expression subtree. A strict
/// expression subtree is a tree which only includes Expr nodes, i.e. no
/// Stmts and no Decls.
class AppearsInSameExpr : public RecursiveASTVisitor<AppearsInSameExpr> {
  using Base = RecursiveASTVisitor<AppearsInSameExpr>;

  const FunctionDecl *FD;
  const Expr *CurrentExprOnlyTreeRoot = nullptr;
  llvm::DenseMap<const ParmVarDecl *,
                 llvm::SmallPtrSet<const Expr *, SmallDataStructureSize>>
      ParentExprsForParamRefs;

public:
  void setup(const FunctionDecl *FD) {
    this->FD = FD;
    TraverseFunctionDecl(const_cast<FunctionDecl *>(FD));
  }

  bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
    return lazyMapOfSetsIntersectionExists(ParentExprsForParamRefs, Param1,
                                           Param2);
  }

  bool TraverseDecl(Decl *D) {
    CurrentExprOnlyTreeRoot = nullptr;
    return Base::TraverseDecl(D);
  }

  bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr) {
    if (auto *E = dyn_cast_or_null<Expr>(S)) {
      bool RootSetInCurrentStackFrame = false;
      if (!CurrentExprOnlyTreeRoot) {
        CurrentExprOnlyTreeRoot = E;
        RootSetInCurrentStackFrame = true;
      }

      bool Ret = Base::TraverseStmt(S);

      if (RootSetInCurrentStackFrame)
        CurrentExprOnlyTreeRoot = nullptr;

      return Ret;
    }

    // A Stmt breaks the strictly Expr subtree.
    CurrentExprOnlyTreeRoot = nullptr;
    return Base::TraverseStmt(S);
  }

  bool VisitDeclRefExpr(DeclRefExpr *DRE) {
    if (!CurrentExprOnlyTreeRoot)
      return true;

    if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
      if (llvm::find(FD->parameters(), PVD))
        ParentExprsForParamRefs[PVD].insert(CurrentExprOnlyTreeRoot);

    return true;
  }
};

/// Implements the heuristic that marks two parameters related if there are
/// two separate calls to the same function (overload) and the parameters are
/// passed to the same index in both calls, i.e f(a, b) and f(a, c) passes
/// b and c to the same index (2) of f(), marking them related.
class PassedToSameFunction {
  ParamToSmallSetMap<std::pair<const FunctionDecl *, unsigned>> TargetParams;

public:
  void setup(const FunctionDecl *FD) {
    auto ParamsAsArgsInFnCalls =
        match(functionDecl(forEachDescendant(
                  callExpr(forEachArgumentWithParam(
                               paramRefExpr(), parmVarDecl().bind("passed-to")))
                      .bind("call-expr"))),
              *FD, FD->getASTContext());
    for (const auto &Match : ParamsAsArgsInFnCalls) {
      const auto *PassedParamOfThisFn = Match.getNodeAs<ParmVarDecl>("param");
      const auto *CE = Match.getNodeAs<CallExpr>("call-expr");
      const auto *PassedToParam = Match.getNodeAs<ParmVarDecl>("passed-to");
      assert(PassedParamOfThisFn && CE && PassedToParam);

      const FunctionDecl *CalledFn = CE->getDirectCallee();
      if (!CalledFn)
        continue;

      std::optional<unsigned> TargetIdx;
      unsigned NumFnParams = CalledFn->getNumParams();
      for (unsigned Idx = 0; Idx < NumFnParams; ++Idx)
        if (CalledFn->getParamDecl(Idx) == PassedToParam)
          TargetIdx.emplace(Idx);

      assert(TargetIdx && "Matched, but didn't find index?");
      TargetParams[PassedParamOfThisFn].insert(
          {CalledFn->getCanonicalDecl(), *TargetIdx});
    }
  }

  bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
    return lazyMapOfSetsIntersectionExists(TargetParams, Param1, Param2);
  }
};

/// Implements the heuristic that marks two parameters related if the same
/// member is accessed (referred to) inside the current function's body.
class AccessedSameMemberOf {
  ParamToSmallSetMap<const Decl *> AccessedMembers;

public:
  void setup(const FunctionDecl *FD) {
    auto MembersCalledOnParams = match(
        functionDecl(forEachDescendant(
            memberExpr(hasObjectExpression(paramRefExpr())).bind("mem-expr"))),
        *FD, FD->getASTContext());

    for (const auto &Match : MembersCalledOnParams) {
      const auto *AccessedParam = Match.getNodeAs<ParmVarDecl>("param");
      const auto *ME = Match.getNodeAs<MemberExpr>("mem-expr");
      assert(AccessedParam && ME);
      AccessedMembers[AccessedParam].insert(
          ME->getMemberDecl()->getCanonicalDecl());
    }
  }

  bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
    return lazyMapOfSetsIntersectionExists(AccessedMembers, Param1, Param2);
  }
};

/// Implements the heuristic that marks two parameters related if different
/// ReturnStmts return them from the function.
class Returned {
  llvm::SmallVector<const ParmVarDecl *, SmallDataStructureSize> ReturnedParams;

public:
  void setup(const FunctionDecl *FD) {
    // TODO: Handle co_return.
    auto ParamReturns = match(functionDecl(forEachDescendant(
                                  returnStmt(hasReturnValue(paramRefExpr())))),
                              *FD, FD->getASTContext());
    for (const auto &Match : ParamReturns) {
      const auto *ReturnedParam = Match.getNodeAs<ParmVarDecl>("param");
      assert(ReturnedParam);

      if (find(FD->parameters(), ReturnedParam) == FD->param_end())
        // Inside the subtree of a FunctionDecl there might be ReturnStmts of
        // a parameter that isn't the parameter of the function, e.g. in the
        // case of lambdas.
        continue;

      ReturnedParams.emplace_back(ReturnedParam);
    }
  }

  bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
    return llvm::is_contained(ReturnedParams, Param1) &&
           llvm::is_contained(ReturnedParams, Param2);
  }
};

} // namespace relatedness_heuristic

/// Helper class that is used to detect if two parameters of the same function
/// are used in a similar fashion, to suppress the result.
class SimilarlyUsedParameterPairSuppressor {
  const bool Enabled;
  relatedness_heuristic::AppearsInSameExpr SameExpr;
  relatedness_heuristic::PassedToSameFunction PassToFun;
  relatedness_heuristic::AccessedSameMemberOf SameMember;
  relatedness_heuristic::Returned Returns;

public:
  SimilarlyUsedParameterPairSuppressor(const FunctionDecl *FD, bool Enable)
      : Enabled(Enable) {
    if (!Enable)
      return;

    SameExpr.setup(FD);
    PassToFun.setup(FD);
    SameMember.setup(FD);
    Returns.setup(FD);
  }

  /// Returns whether the specified two parameters are deemed similarly used
  /// or related by the heuristics.
  bool operator()(const ParmVarDecl *Param1, const ParmVarDecl *Param2) const {
    if (!Enabled)
      return false;

    LLVM_DEBUG(llvm::dbgs()
               << "::: Matching similar usage / relatedness heuristic...\n");

    if (SameExpr(Param1, Param2)) {
      LLVM_DEBUG(llvm::dbgs() << "::: Used in the same expression.\n");
      return true;
    }

    if (PassToFun(Param1, Param2)) {
      LLVM_DEBUG(llvm::dbgs()
                 << "::: Passed to same function in different calls.\n");
      return true;
    }

    if (SameMember(Param1, Param2)) {
      LLVM_DEBUG(llvm::dbgs()
                 << "::: Same member field access or method called.\n");
      return true;
    }

    if (Returns(Param1, Param2)) {
      LLVM_DEBUG(llvm::dbgs() << "::: Both parameter returned.\n");
      return true;
    }

    LLVM_DEBUG(llvm::dbgs() << "::: None.\n");
    return false;
  }
};

// (This function hoists the call to operator() of the wrapper, so we do not
// need to define the previous class at the top of the file.)
static inline bool
isSimilarlyUsedParameter(const SimilarlyUsedParameterPairSuppressor &Suppressor,
                         const ParmVarDecl *Param1, const ParmVarDecl *Param2) {
  return Suppressor(Param1, Param2);
}

static void padStringAtEnd(SmallVectorImpl<char> &Str, std::size_t ToLen) {
  while (Str.size() < ToLen)
    Str.emplace_back('\0');
}

static void padStringAtBegin(SmallVectorImpl<char> &Str, std::size_t ToLen) {
  while (Str.size() < ToLen)
    Str.insert(Str.begin(), '\0');
}

static bool isCommonPrefixWithoutSomeCharacters(std::size_t N, StringRef S1,
                                                StringRef S2) {
  assert(S1.size() >= N && S2.size() >= N);
  StringRef S1Prefix = S1.take_front(S1.size() - N),
            S2Prefix = S2.take_front(S2.size() - N);
  return S1Prefix == S2Prefix && !S1Prefix.empty();
}

static bool isCommonSuffixWithoutSomeCharacters(std::size_t N, StringRef S1,
                                                StringRef S2) {
  assert(S1.size() >= N && S2.size() >= N);
  StringRef S1Suffix = S1.take_back(S1.size() - N),
            S2Suffix = S2.take_back(S2.size() - N);
  return S1Suffix == S2Suffix && !S1Suffix.empty();
}

/// Returns whether the two strings are prefixes or suffixes of each other with
/// at most Threshold characters differing on the non-common end.
static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold,
                                            StringRef Str1, StringRef Str2) {
  if (Threshold == 0)
    return false;

  // Pad the two strings to the longer length.
  std::size_t BiggerLength = std::max(Str1.size(), Str2.size());

  if (BiggerLength <= Threshold)
    // If the length of the strings is still smaller than the threshold, they
    // would be covered by an empty prefix/suffix with the rest differing.
    // (E.g. "A" and "X" with Threshold = 1 would mean we think they are
    // similar and do not warn about them, which is a too eager assumption.)
    return false;

  SmallString<32> S1PadE{Str1}, S2PadE{Str2};
  padStringAtEnd(S1PadE, BiggerLength);
  padStringAtEnd(S2PadE, BiggerLength);

  if (isCommonPrefixWithoutSomeCharacters(
          Threshold, StringRef{S1PadE.begin(), BiggerLength},
          StringRef{S2PadE.begin(), BiggerLength}))
    return true;

  SmallString<32> S1PadB{Str1}, S2PadB{Str2};
  padStringAtBegin(S1PadB, BiggerLength);
  padStringAtBegin(S2PadB, BiggerLength);

  if (isCommonSuffixWithoutSomeCharacters(
          Threshold, StringRef{S1PadB.begin(), BiggerLength},
          StringRef{S2PadB.begin(), BiggerLength}))
    return true;

  return false;
}

} // namespace filter

/// Matches functions that have at least the specified amount of parameters.
AST_MATCHER_P(FunctionDecl, parameterCountGE, unsigned, N) {
  return Node.getNumParams() >= N;
}

/// Matches *any* overloaded unary and binary operators.
AST_MATCHER(FunctionDecl, isOverloadedUnaryOrBinaryOperator) {
  switch (Node.getOverloadedOperator()) {
  case OO_None:
  case OO_New:
  case OO_Delete:
  case OO_Array_New:
  case OO_Array_Delete:
  case OO_Conditional:
  case OO_Coawait:
    return false;

  default:
    return Node.getNumParams() <= 2;
  }
}

/// Returns the DefaultMinimumLength if the Value of requested minimum length
/// is less than 2. Minimum lengths of 0 or 1 are not accepted.
static inline unsigned clampMinimumLength(const unsigned Value) {
  return Value < 2 ? DefaultMinimumLength : Value;
}

// FIXME: Maybe unneeded, getNameForDiagnostic() is expected to change to return
// a crafted location when the node itself is unnamed. (See D84658, D85033.)
/// Returns the diagnostic-friendly name of the node, or empty string.
static SmallString<64> getName(const NamedDecl *ND) {
  SmallString<64> Name;
  llvm::raw_svector_ostream OS{Name};
  ND->getNameForDiagnostic(OS, ND->getASTContext().getPrintingPolicy(), false);
  return Name;
}

/// Returns the diagnostic-friendly name of the node, or a constant value.
static SmallString<64> getNameOrUnnamed(const NamedDecl *ND) {
  auto Name = getName(ND);
  if (Name.empty())
    Name = "<unnamed>";
  return Name;
}

/// Returns whether a particular Mix between two parameters should have the
/// types involved diagnosed to the user. This is only a flag check.
static inline bool needsToPrintTypeInDiagnostic(const model::Mix &M) {
  using namespace model;
  return static_cast<bool>(
      M.flags() &
      (MixFlags::TypeAlias | MixFlags::ReferenceBind | MixFlags::Qualifiers));
}

/// Returns whether a particular Mix between the two parameters should have
/// implicit conversions elaborated.
static inline bool needsToElaborateImplicitConversion(const model::Mix &M) {
  return hasFlag(M.flags(), model::MixFlags::ImplicitConversion);
}

namespace {

/// This class formats a conversion sequence into a "Ty1 -> Ty2 -> Ty3" line
/// that can be used in diagnostics.
struct FormattedConversionSequence {
  std::string DiagnosticText;

  /// The formatted sequence is trivial if it is "Ty1 -> Ty2", but Ty1 and
  /// Ty2 are the types that are shown in the code. A trivial diagnostic
  /// does not need to be printed.
  bool Trivial = true;

  FormattedConversionSequence(const PrintingPolicy &PP,
                              StringRef StartTypeAsDiagnosed,
                              const model::ConversionSequence &Conv,
                              StringRef DestinationTypeAsDiagnosed) {
    llvm::raw_string_ostream OS{DiagnosticText};

    // Print the type name as it is printed in other places in the diagnostic.
    OS << '\'' << StartTypeAsDiagnosed << '\'';
    std::string LastAddedType = StartTypeAsDiagnosed.str();
    std::size_t NumElementsAdded = 1;

    // However, the parameter's defined type might not be what the implicit
    // conversion started with, e.g. if a typedef is found to convert.
    std::string SeqBeginTypeStr = Conv.Begin.getAsString(PP);
    std::string SeqEndTypeStr = Conv.End.getAsString(PP);
    if (StartTypeAsDiagnosed != SeqBeginTypeStr) {
      OS << " (as '" << SeqBeginTypeStr << "')";
      LastAddedType = SeqBeginTypeStr;
      Trivial = false;
    }

    auto AddType = [&](StringRef ToAdd) {
      if (LastAddedType != ToAdd && ToAdd != SeqEndTypeStr) {
        OS << " -> '" << ToAdd << "'";
        LastAddedType = ToAdd.str();
        ++NumElementsAdded;
      }
    };
    for (QualType InvolvedType : Conv.getInvolvedTypesInSequence())
      // Print every type that's unique in the sequence into the diagnosis.
      AddType(InvolvedType.getAsString(PP));

    if (LastAddedType != DestinationTypeAsDiagnosed) {
      OS << " -> '" << DestinationTypeAsDiagnosed << "'";
      LastAddedType = DestinationTypeAsDiagnosed.str();
      ++NumElementsAdded;
    }

    // Same reasoning as with the Begin, e.g. if the converted-to type is a
    // typedef, it will not be the same inside the conversion sequence (where
    // the model already tore off typedefs) as in the code.
    if (DestinationTypeAsDiagnosed != SeqEndTypeStr) {
      OS << " (as '" << SeqEndTypeStr << "')";
      LastAddedType = SeqEndTypeStr;
      Trivial = false;
    }

    if (Trivial && NumElementsAdded > 2)
      // If the thing is still marked trivial but we have more than the
      // from and to types added, it should not be trivial, and elaborated
      // when printing the diagnostic.
      Trivial = false;
  }
};

/// Retains the elements called with and returns whether the call is done with
/// a new element.
template <typename E, std::size_t N> class InsertOnce {
  llvm::SmallSet<E, N> CalledWith;

public:
  bool operator()(E El) { return CalledWith.insert(std::move(El)).second; }

  bool calledWith(const E &El) const { return CalledWith.contains(El); }
};

struct SwappedEqualQualTypePair {
  QualType LHSType, RHSType;

  bool operator==(const SwappedEqualQualTypePair &Other) const {
    return (LHSType == Other.LHSType && RHSType == Other.RHSType) ||
           (LHSType == Other.RHSType && RHSType == Other.LHSType);
  }

  bool operator<(const SwappedEqualQualTypePair &Other) const {
    return LHSType < Other.LHSType && RHSType < Other.RHSType;
  }
};

struct TypeAliasDiagnosticTuple {
  QualType LHSType, RHSType, CommonType;

  bool operator==(const TypeAliasDiagnosticTuple &Other) const {
    return CommonType == Other.CommonType &&
           ((LHSType == Other.LHSType && RHSType == Other.RHSType) ||
            (LHSType == Other.RHSType && RHSType == Other.LHSType));
  }

  bool operator<(const TypeAliasDiagnosticTuple &Other) const {
    return CommonType < Other.CommonType && LHSType < Other.LHSType &&
           RHSType < Other.RHSType;
  }
};

/// Helper class to only emit a diagnostic related to MixFlags::TypeAlias once.
class UniqueTypeAliasDiagnosticHelper
    : public InsertOnce<TypeAliasDiagnosticTuple, 8> {
  using Base = InsertOnce<TypeAliasDiagnosticTuple, 8>;

public:
  /// Returns whether the diagnostic for LHSType and RHSType which are both
  /// referring to CommonType being the same has not been emitted already.
  bool operator()(QualType LHSType, QualType RHSType, QualType CommonType) {
    if (CommonType.isNull() || CommonType == LHSType || CommonType == RHSType)
      return Base::operator()({LHSType, RHSType, {}});

    TypeAliasDiagnosticTuple ThreeTuple{LHSType, RHSType, CommonType};
    if (!Base::operator()(ThreeTuple))
      return false;

    bool AlreadySaidLHSAndCommonIsSame = calledWith({LHSType, CommonType, {}});
    bool AlreadySaidRHSAndCommonIsSame = calledWith({RHSType, CommonType, {}});
    if (AlreadySaidLHSAndCommonIsSame && AlreadySaidRHSAndCommonIsSame) {
      // "SomeInt == int" && "SomeOtherInt == int" => "Common(SomeInt,
      // SomeOtherInt) == int", no need to diagnose it. Save the 3-tuple only
      // for shortcut if it ever appears again.
      return false;
    }

    return true;
  }
};

} // namespace

EasilySwappableParametersCheck::EasilySwappableParametersCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      MinimumLength(clampMinimumLength(
          Options.get("MinimumLength", DefaultMinimumLength))),
      IgnoredParameterNames(optutils::parseStringList(
          Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames))),
      IgnoredParameterTypeSuffixes(optutils::parseStringList(
          Options.get("IgnoredParameterTypeSuffixes",
                      DefaultIgnoredParameterTypeSuffixes))),
      QualifiersMix(Options.get("QualifiersMix", DefaultQualifiersMix)),
      ModelImplicitConversions(Options.get("ModelImplicitConversions",
                                           DefaultModelImplicitConversions)),
      SuppressParametersUsedTogether(
          Options.get("SuppressParametersUsedTogether",
                      DefaultSuppressParametersUsedTogether)),
      NamePrefixSuffixSilenceDissimilarityTreshold(
          Options.get("NamePrefixSuffixSilenceDissimilarityTreshold",
                      DefaultNamePrefixSuffixSilenceDissimilarityTreshold)) {}

void EasilySwappableParametersCheck::storeOptions(
    ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "MinimumLength", MinimumLength);
  Options.store(Opts, "IgnoredParameterNames",
                optutils::serializeStringList(IgnoredParameterNames));
  Options.store(Opts, "IgnoredParameterTypeSuffixes",
                optutils::serializeStringList(IgnoredParameterTypeSuffixes));
  Options.store(Opts, "QualifiersMix", QualifiersMix);
  Options.store(Opts, "ModelImplicitConversions", ModelImplicitConversions);
  Options.store(Opts, "SuppressParametersUsedTogether",
                SuppressParametersUsedTogether);
  Options.store(Opts, "NamePrefixSuffixSilenceDissimilarityTreshold",
                NamePrefixSuffixSilenceDissimilarityTreshold);
}

void EasilySwappableParametersCheck::registerMatchers(MatchFinder *Finder) {
  const auto BaseConstraints = functionDecl(
      // Only report for definition nodes, as fixing the issues reported
      // requires the user to be able to change code.
      isDefinition(), parameterCountGE(MinimumLength),
      unless(isOverloadedUnaryOrBinaryOperator()));

  Finder->addMatcher(
      functionDecl(BaseConstraints,
                   unless(ast_matchers::isTemplateInstantiation()))
          .bind("func"),
      this);
  Finder->addMatcher(
      functionDecl(BaseConstraints, isExplicitTemplateSpecialization())
          .bind("func"),
      this);
}

void EasilySwappableParametersCheck::check(
    const MatchFinder::MatchResult &Result) {
  using namespace model;
  using namespace filter;

  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("func");
  assert(FD);

  const PrintingPolicy &PP = FD->getASTContext().getPrintingPolicy();
  std::size_t NumParams = FD->getNumParams();
  std::size_t MixableRangeStartIndex = 0;

  // Spawn one suppressor and if the user requested, gather information from
  // the AST for the parameters' usages.
  filter::SimilarlyUsedParameterPairSuppressor UsageBasedSuppressor{
      FD, SuppressParametersUsedTogether};

  LLVM_DEBUG(llvm::dbgs() << "Begin analysis of " << getName(FD) << " with "
                          << NumParams << " parameters...\n");
  while (MixableRangeStartIndex < NumParams) {
    if (isIgnoredParameter(*this, FD->getParamDecl(MixableRangeStartIndex))) {
      LLVM_DEBUG(llvm::dbgs()
                 << "Parameter #" << MixableRangeStartIndex << " ignored.\n");
      ++MixableRangeStartIndex;
      continue;
    }

    MixableParameterRange R = modelMixingRange(
        *this, FD, MixableRangeStartIndex, UsageBasedSuppressor);
    assert(R.NumParamsChecked > 0 && "Ensure forward progress!");
    MixableRangeStartIndex += R.NumParamsChecked;
    if (R.NumParamsChecked < MinimumLength) {
      LLVM_DEBUG(llvm::dbgs() << "Ignoring range of " << R.NumParamsChecked
                              << " lower than limit.\n");
      continue;
    }

    bool NeedsAnyTypeNote = llvm::any_of(R.Mixes, needsToPrintTypeInDiagnostic);
    bool HasAnyImplicits =
        llvm::any_of(R.Mixes, needsToElaborateImplicitConversion);
    const ParmVarDecl *First = R.getFirstParam(), *Last = R.getLastParam();
    std::string FirstParamTypeAsWritten = First->getType().getAsString(PP);
    {
      StringRef DiagText;

      if (HasAnyImplicits)
        DiagText = "%0 adjacent parameters of %1 of convertible types are "
                   "easily swapped by mistake";
      else if (NeedsAnyTypeNote)
        DiagText = "%0 adjacent parameters of %1 of similar type are easily "
                   "swapped by mistake";
      else
        DiagText = "%0 adjacent parameters of %1 of similar type ('%2') are "
                   "easily swapped by mistake";

      auto Diag = diag(First->getOuterLocStart(), DiagText)
                  << static_cast<unsigned>(R.NumParamsChecked) << FD;
      if (!NeedsAnyTypeNote)
        Diag << FirstParamTypeAsWritten;

      CharSourceRange HighlightRange = CharSourceRange::getTokenRange(
          First->getBeginLoc(), Last->getEndLoc());
      Diag << HighlightRange;
    }

    // There is a chance that the previous highlight did not succeed, e.g. when
    // the two parameters are on different lines. For clarity, show the user
    // the involved variable explicitly.
    diag(First->getLocation(), "the first parameter in the range is '%0'",
         DiagnosticIDs::Note)
        << getNameOrUnnamed(First)
        << CharSourceRange::getTokenRange(First->getLocation(),
                                          First->getLocation());
    diag(Last->getLocation(), "the last parameter in the range is '%0'",
         DiagnosticIDs::Note)
        << getNameOrUnnamed(Last)
        << CharSourceRange::getTokenRange(Last->getLocation(),
                                          Last->getLocation());

    // Helper classes to silence elaborative diagnostic notes that would be
    // too verbose.
    UniqueTypeAliasDiagnosticHelper UniqueTypeAlias;
    InsertOnce<SwappedEqualQualTypePair, 8> UniqueBindPower;
    InsertOnce<SwappedEqualQualTypePair, 8> UniqueImplicitConversion;

    for (const model::Mix &M : R.Mixes) {
      assert(M.mixable() && "Sentinel or false mix in result.");
      if (!needsToPrintTypeInDiagnostic(M) &&
          !needsToElaborateImplicitConversion(M))
        continue;

      // Typedefs might result in the type of the variable needing to be
      // emitted to a note diagnostic, so prepare it.
      const ParmVarDecl *LVar = M.First;
      const ParmVarDecl *RVar = M.Second;
      QualType LType = LVar->getType();
      QualType RType = RVar->getType();
      QualType CommonType = M.commonUnderlyingType();
      std::string LTypeStr = LType.getAsString(PP);
      std::string RTypeStr = RType.getAsString(PP);
      std::string CommonTypeStr = CommonType.getAsString(PP);

      if (hasFlag(M.flags(), MixFlags::TypeAlias) &&
          UniqueTypeAlias(LType, RType, CommonType)) {
        StringRef DiagText;
        bool ExplicitlyPrintCommonType = false;
        if (LTypeStr == CommonTypeStr || RTypeStr == CommonTypeStr) {
          if (hasFlag(M.flags(), MixFlags::Qualifiers))
            DiagText = "after resolving type aliases, '%0' and '%1' share a "
                       "common type";
          else
            DiagText =
                "after resolving type aliases, '%0' and '%1' are the same";
        } else if (!CommonType.isNull()) {
          DiagText = "after resolving type aliases, the common type of '%0' "
                     "and '%1' is '%2'";
          ExplicitlyPrintCommonType = true;
        }

        auto Diag =
            diag(LVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note)
            << LTypeStr << RTypeStr;
        if (ExplicitlyPrintCommonType)
          Diag << CommonTypeStr;
      }

      if ((hasFlag(M.flags(), MixFlags::ReferenceBind) ||
           hasFlag(M.flags(), MixFlags::Qualifiers)) &&
          UniqueBindPower({LType, RType})) {
        StringRef DiagText = "'%0' and '%1' parameters accept and bind the "
                             "same kind of values";
        diag(RVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note)
            << LTypeStr << RTypeStr;
      }

      if (needsToElaborateImplicitConversion(M) &&
          UniqueImplicitConversion({LType, RType})) {
        const model::ConversionSequence &LTR =
            M.leftToRightConversionSequence();
        const model::ConversionSequence &RTL =
            M.rightToLeftConversionSequence();
        FormattedConversionSequence LTRFmt{PP, LTypeStr, LTR, RTypeStr};
        FormattedConversionSequence RTLFmt{PP, RTypeStr, RTL, LTypeStr};

        StringRef DiagText = "'%0' and '%1' may be implicitly converted";
        if (!LTRFmt.Trivial || !RTLFmt.Trivial)
          DiagText = "'%0' and '%1' may be implicitly converted: %2, %3";

        {
          auto Diag =
              diag(RVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note)
              << LTypeStr << RTypeStr;

          if (!LTRFmt.Trivial || !RTLFmt.Trivial)
            Diag << LTRFmt.DiagnosticText << RTLFmt.DiagnosticText;
        }

        StringRef ConversionFunctionDiagText =
            "the implicit conversion involves the "
            "%select{|converting constructor|conversion operator}0 "
            "declared here";
        if (const FunctionDecl *LFD = LTR.getUserDefinedConversionFunction())
          diag(LFD->getLocation(), ConversionFunctionDiagText,
               DiagnosticIDs::Note)
              << static_cast<unsigned>(LTR.UDConvKind)
              << LTR.getUserDefinedConversionHighlight();
        if (const FunctionDecl *RFD = RTL.getUserDefinedConversionFunction())
          diag(RFD->getLocation(), ConversionFunctionDiagText,
               DiagnosticIDs::Note)
              << static_cast<unsigned>(RTL.UDConvKind)
              << RTL.getUserDefinedConversionHighlight();
      }
    }
  }
}

} // namespace clang::tidy::bugprone
