//===- UnsafeBufferUsage.cpp - Replace pointers with modern C++ -----------===//
//
// 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 "clang/Analysis/Analyses/UnsafeBufferUsage.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/FormatString.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/LowLevelHelpers.h"
#include "clang/Analysis/Support/FixitUtil.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <cstddef>
#include <optional>
#include <queue>
#include <set>
#include <sstream>

using namespace clang;

#ifndef NDEBUG
namespace {
class StmtDebugPrinter
    : public ConstStmtVisitor<StmtDebugPrinter, std::string> {
public:
  std::string VisitStmt(const Stmt *S) { return S->getStmtClassName(); }

  std::string VisitBinaryOperator(const BinaryOperator *BO) {
    return "BinaryOperator(" + BO->getOpcodeStr().str() + ")";
  }

  std::string VisitUnaryOperator(const UnaryOperator *UO) {
    return "UnaryOperator(" + UO->getOpcodeStr(UO->getOpcode()).str() + ")";
  }

  std::string VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
    return "ImplicitCastExpr(" + std::string(ICE->getCastKindName()) + ")";
  }
};

// Returns a string of ancestor `Stmt`s of the given `DRE` in such a form:
// "DRE ==> parent-of-DRE ==> grandparent-of-DRE ==> ...".
static std::string getDREAncestorString(const DeclRefExpr *DRE,
                                        ASTContext &Ctx) {
  std::stringstream SS;
  const Stmt *St = DRE;
  StmtDebugPrinter StmtPriner;

  do {
    SS << StmtPriner.Visit(St);

    DynTypedNodeList StParents = Ctx.getParents(*St);

    if (StParents.size() > 1)
      return "unavailable due to multiple parents";
    if (StParents.empty())
      break;
    St = StParents.begin()->get<Stmt>();
    if (St)
      SS << " ==> ";
  } while (St);
  return SS.str();
}

} // namespace
#endif /* NDEBUG */

namespace {
// Using a custom `FastMatcher` instead of ASTMatchers to achieve better
// performance. FastMatcher uses simple function `matches` to find if a node
// is a match, avoiding the dependency on the ASTMatchers framework which
// provide a nice abstraction, but incur big performance costs.
class FastMatcher {
public:
  virtual bool matches(const DynTypedNode &DynNode, ASTContext &Ctx,
                       const UnsafeBufferUsageHandler &Handler) = 0;
  virtual ~FastMatcher() = default;
};

class MatchResult {

public:
  template <typename T> const T *getNodeAs(StringRef ID) const {
    auto It = Nodes.find(ID);
    if (It == Nodes.end()) {
      return nullptr;
    }
    return It->second.get<T>();
  }

  void addNode(StringRef ID, const DynTypedNode &Node) { Nodes[ID] = Node; }

private:
  llvm::StringMap<DynTypedNode> Nodes;
};
} // namespace

// A `RecursiveASTVisitor` that traverses all descendants of a given node "n"
// except for those belonging to a different callable of "n".
class MatchDescendantVisitor : public DynamicRecursiveASTVisitor {
public:
  // Creates an AST visitor that matches `Matcher` on all
  // descendants of a given node "n" except for the ones
  // belonging to a different callable of "n".
  MatchDescendantVisitor(ASTContext &Context, FastMatcher &Matcher,
                         bool FindAll, bool ignoreUnevaluatedContext,
                         const UnsafeBufferUsageHandler &NewHandler)
      : Matcher(&Matcher), FindAll(FindAll), Matches(false),
        ignoreUnevaluatedContext(ignoreUnevaluatedContext),
        ActiveASTContext(&Context), Handler(&NewHandler) {
    ShouldVisitTemplateInstantiations = true;
    ShouldVisitImplicitCode = false; // TODO: let's ignore implicit code for now
  }

  // Returns true if a match is found in a subtree of `DynNode`, which belongs
  // to the same callable of `DynNode`.
  bool findMatch(const DynTypedNode &DynNode) {
    Matches = false;
    if (const Stmt *StmtNode = DynNode.get<Stmt>()) {
      TraverseStmt(const_cast<Stmt *>(StmtNode));
      return Matches;
    }
    return false;
  }

  // The following are overriding methods from the base visitor class.
  // They are public only to allow CRTP to work. They are *not *part
  // of the public API of this class.

  // For the matchers so far used in safe buffers, we only need to match
  // `Stmt`s.  To override more as needed.

  bool TraverseDecl(Decl *Node) override {
    if (!Node)
      return true;
    if (!match(*Node))
      return false;
    // To skip callables:
    if (isa<FunctionDecl, BlockDecl, ObjCMethodDecl>(Node))
      return true;
    // Traverse descendants
    return DynamicRecursiveASTVisitor::TraverseDecl(Node);
  }

  bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override {
    // These are unevaluated, except the result expression.
    if (ignoreUnevaluatedContext)
      return TraverseStmt(Node->getResultExpr());
    return DynamicRecursiveASTVisitor::TraverseGenericSelectionExpr(Node);
  }

  bool
  TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override {
    // Unevaluated context.
    if (ignoreUnevaluatedContext)
      return true;
    return DynamicRecursiveASTVisitor::TraverseUnaryExprOrTypeTraitExpr(Node);
  }

  bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override {
    // Unevaluated context.
    if (ignoreUnevaluatedContext)
      return true;
    return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(Node);
  }

  bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override {
    // Unevaluated context.
    if (ignoreUnevaluatedContext)
      return true;
    return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(Node);
  }

  bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {
    // Unevaluated context.
    if (ignoreUnevaluatedContext)
      return true;
    return DynamicRecursiveASTVisitor::TraverseCXXNoexceptExpr(Node);
  }

  bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override {
    // Unevaluated context.
    if (ignoreUnevaluatedContext)
      return true;
    return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(Node);
  }

  bool TraverseCXXDefaultInitExpr(CXXDefaultInitExpr *Node) override {
    if (!TraverseStmt(Node->getExpr()))
      return false;
    return DynamicRecursiveASTVisitor::TraverseCXXDefaultInitExpr(Node);
  }

  bool TraverseStmt(Stmt *Node) override {
    if (!Node)
      return true;
    if (!match(*Node))
      return false;
    return DynamicRecursiveASTVisitor::TraverseStmt(Node);
  }

private:
  // Sets 'Matched' to true if 'Matcher' matches 'Node'
  //
  // Returns 'true' if traversal should continue after this function
  // returns, i.e. if no match is found or 'Bind' is 'BK_All'.
  template <typename T> bool match(const T &Node) {
    if (Matcher->matches(DynTypedNode::create(Node), *ActiveASTContext,
                         *Handler)) {
      Matches = true;
      if (!FindAll)
        return false; // Abort as soon as a match is found.
    }
    return true;
  }

  FastMatcher *const Matcher;
  // When true, finds all matches. When false, finds the first match and stops.
  const bool FindAll;
  bool Matches;
  bool ignoreUnevaluatedContext;
  ASTContext *ActiveASTContext;
  const UnsafeBufferUsageHandler *Handler;
};

// Because we're dealing with raw pointers, let's define what we mean by that.
static bool hasPointerType(const Expr &E) {
  return isa<PointerType>(E.getType().getCanonicalType());
}

static bool hasArrayType(const Expr &E) {
  return isa<ArrayType>(E.getType().getCanonicalType());
}

static void
forEachDescendantEvaluatedStmt(const Stmt *S, ASTContext &Ctx,
                               const UnsafeBufferUsageHandler &Handler,
                               FastMatcher &Matcher) {
  MatchDescendantVisitor Visitor(Ctx, Matcher, /*FindAll=*/true,
                                 /*ignoreUnevaluatedContext=*/true, Handler);
  Visitor.findMatch(DynTypedNode::create(*S));
}

static void forEachDescendantStmt(const Stmt *S, ASTContext &Ctx,
                                  const UnsafeBufferUsageHandler &Handler,
                                  FastMatcher &Matcher) {
  MatchDescendantVisitor Visitor(Ctx, Matcher, /*FindAll=*/true,
                                 /*ignoreUnevaluatedContext=*/false, Handler);
  Visitor.findMatch(DynTypedNode::create(*S));
}

// Matches a `Stmt` node iff the node is in a safe-buffer opt-out region
static bool notInSafeBufferOptOut(const Stmt &Node,
                                  const UnsafeBufferUsageHandler *Handler) {
  return !Handler->isSafeBufferOptOut(Node.getBeginLoc());
}

static bool
ignoreUnsafeBufferInContainer(const Stmt &Node,
                              const UnsafeBufferUsageHandler *Handler) {
  return Handler->ignoreUnsafeBufferInContainer(Node.getBeginLoc());
}

static bool ignoreUnsafeLibcCall(const ASTContext &Ctx, const Stmt &Node,
                                 const UnsafeBufferUsageHandler *Handler) {
  if (Ctx.getLangOpts().CPlusPlus)
    return Handler->ignoreUnsafeBufferInLibcCall(Node.getBeginLoc());
  return true; /* Only warn about libc calls for C++ */
}

// Finds any expression 'e' such that `OnResult`
// matches 'e' and 'e' is in an Unspecified Lvalue Context.
static void findStmtsInUnspecifiedLvalueContext(
    const Stmt *S, const llvm::function_ref<void(const Expr *)> OnResult) {
  if (const auto *CE = dyn_cast<ImplicitCastExpr>(S);
      CE && CE->getCastKind() == CastKind::CK_LValueToRValue)
    OnResult(CE->getSubExpr());
  if (const auto *BO = dyn_cast<BinaryOperator>(S);
      BO && BO->getOpcode() == BO_Assign)
    OnResult(BO->getLHS());
}

// Finds any expression `e` such that `InnerMatcher` matches `e` and
// `e` is in an Unspecified Pointer Context (UPC).
static void findStmtsInUnspecifiedPointerContext(
    const Stmt *S, llvm::function_ref<void(const Stmt *)> InnerMatcher) {
  // A UPC can be
  // 1. an argument of a function call (except the callee has [[unsafe_...]]
  //    attribute), or
  // 2. the operand of a pointer-to-(integer or bool) cast operation; or
  // 3. the operand of a comparator operation; or
  // 4. the operand of a pointer subtraction operation
  //    (i.e., computing the distance between two pointers); or ...

  if (auto *CE = dyn_cast<CallExpr>(S)) {
    if (const auto *FnDecl = CE->getDirectCallee();
        FnDecl && FnDecl->hasAttr<UnsafeBufferUsageAttr>())
      return;
    ast_matchers::matchEachArgumentWithParamType(
        *CE, [&InnerMatcher](QualType Type, const Expr *Arg) {
          if (Type->isAnyPointerType())
            InnerMatcher(Arg);
        });
  }

  if (auto *CE = dyn_cast<CastExpr>(S)) {
    if (CE->getCastKind() != CastKind::CK_PointerToIntegral &&
        CE->getCastKind() != CastKind::CK_PointerToBoolean)
      return;
    if (!hasPointerType(*CE->getSubExpr()))
      return;
    InnerMatcher(CE->getSubExpr());
  }

  // Pointer comparison operator.
  if (const auto *BO = dyn_cast<BinaryOperator>(S);
      BO && (BO->getOpcode() == BO_EQ || BO->getOpcode() == BO_NE ||
             BO->getOpcode() == BO_LT || BO->getOpcode() == BO_LE ||
             BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE)) {
    auto *LHS = BO->getLHS();
    if (hasPointerType(*LHS))
      InnerMatcher(LHS);

    auto *RHS = BO->getRHS();
    if (hasPointerType(*RHS))
      InnerMatcher(RHS);
  }

  // Pointer subtractions.
  if (const auto *BO = dyn_cast<BinaryOperator>(S);
      BO && BO->getOpcode() == BO_Sub && hasPointerType(*BO->getLHS()) &&
      hasPointerType(*BO->getRHS())) {
    // Note that here we need both LHS and RHS to be
    // pointer. Then the inner matcher can match any of
    // them:
    InnerMatcher(BO->getLHS());
    InnerMatcher(BO->getRHS());
  }
  // FIXME: any more cases? (UPC excludes the RHS of an assignment.  For now
  // we don't have to check that.)
}

// Finds statements in unspecified untyped context i.e. any expression 'e' such
// that `InnerMatcher` matches 'e' and 'e' is in an unspecified untyped context
// (i.e the expression 'e' isn't evaluated to an RValue). For example, consider
// the following code:
//    int *p = new int[4];
//    int *q = new int[4];
//    if ((p = q)) {}
//    p = q;
// The expression `p = q` in the conditional of the `if` statement
// `if ((p = q))` is evaluated as an RValue, whereas the expression `p = q;`
// in the assignment statement is in an untyped context.
static void findStmtsInUnspecifiedUntypedContext(
    const Stmt *S, llvm::function_ref<void(const Stmt *)> InnerMatcher) {
  // An unspecified context can be
  // 1. A compound statement,
  // 2. The body of an if statement
  // 3. Body of a loop
  if (auto *CS = dyn_cast<CompoundStmt>(S)) {
    for (auto *Child : CS->body())
      InnerMatcher(Child);
  }
  if (auto *IfS = dyn_cast<IfStmt>(S)) {
    if (IfS->getThen())
      InnerMatcher(IfS->getThen());
    if (IfS->getElse())
      InnerMatcher(IfS->getElse());
  }
  // FIXME: Handle loop bodies.
}

// Returns true iff integer E1 is equivalent to integer E2.
//
// For now we only support such expressions:
//    expr := DRE | const-value | expr BO expr
//    BO   := '*' | '+'
//
// FIXME: We can reuse the expression comparator of the interop analysis after
// it has been upstreamed.
static bool areEqualIntegers(const Expr *E1, const Expr *E2, ASTContext &Ctx);
static bool areEqualIntegralBinaryOperators(const BinaryOperator *E1,
                                            const Expr *E2_LHS,
                                            BinaryOperatorKind BOP,
                                            const Expr *E2_RHS,
                                            ASTContext &Ctx) {
  if (E1->getOpcode() == BOP) {
    switch (BOP) {
      // Commutative operators:
    case BO_Mul:
    case BO_Add:
      return (areEqualIntegers(E1->getLHS(), E2_LHS, Ctx) &&
              areEqualIntegers(E1->getRHS(), E2_RHS, Ctx)) ||
             (areEqualIntegers(E1->getLHS(), E2_RHS, Ctx) &&
              areEqualIntegers(E1->getRHS(), E2_LHS, Ctx));
    default:
      return false;
    }
  }
  return false;
}

static bool areEqualIntegers(const Expr *E1, const Expr *E2, ASTContext &Ctx) {
  E1 = E1->IgnoreParenImpCasts();
  E2 = E2->IgnoreParenImpCasts();
  if (!E1->getType()->isIntegerType() || E1->getType() != E2->getType())
    return false;

  Expr::EvalResult ER1, ER2;

  // If both are constants:
  if (E1->EvaluateAsInt(ER1, Ctx) && E2->EvaluateAsInt(ER2, Ctx))
    return ER1.Val.getInt() == ER2.Val.getInt();

  // Otherwise, they should have identical stmt kind:
  if (E1->getStmtClass() != E2->getStmtClass())
    return false;
  switch (E1->getStmtClass()) {
  case Stmt::DeclRefExprClass:
    return cast<DeclRefExpr>(E1)->getDecl() == cast<DeclRefExpr>(E2)->getDecl();
  case Stmt::BinaryOperatorClass: {
    auto BO2 = cast<BinaryOperator>(E2);
    return areEqualIntegralBinaryOperators(cast<BinaryOperator>(E1),
                                           BO2->getLHS(), BO2->getOpcode(),
                                           BO2->getRHS(), Ctx);
  }
  default:
    return false;
  }
}

// Given a two-param std::span construct call, matches iff the call has the
// following forms:
//   1. `std::span<T>{new T[n], n}`, where `n` is a literal or a DRE
//   2. `std::span<T>{new T, 1}`
//   3. `std::span<T>{&var, 1}` or `std::span<T>{std::addressof(...), 1}`
//   4. `std::span<T>{a, n}`, where `a` is of an array-of-T with constant size
//   `n`
//   5. `std::span<T>{any, 0}`
//   6. `std::span<T>{ (char *)f(args), args[N] * arg*[M]}`, where
//       `f` is a function with attribute `alloc_size(N, M)`;
//       `args` represents the list of arguments;
//       `N, M` are parameter indexes to the allocating element number and size.
//        Sometimes, there is only one parameter index representing the total
//        size.
static bool isSafeSpanTwoParamConstruct(const CXXConstructExpr &Node,
                                        ASTContext &Ctx) {
  assert(Node.getNumArgs() == 2 &&
         "expecting a two-parameter std::span constructor");
  const Expr *Arg0 = Node.getArg(0)->IgnoreParenImpCasts();
  const Expr *Arg1 = Node.getArg(1)->IgnoreParenImpCasts();
  auto HaveEqualConstantValues = [&Ctx](const Expr *E0, const Expr *E1) {
    if (auto E0CV = E0->getIntegerConstantExpr(Ctx))
      if (auto E1CV = E1->getIntegerConstantExpr(Ctx)) {
        return llvm::APSInt::compareValues(*E0CV, *E1CV) == 0;
      }
    return false;
  };
  auto AreSameDRE = [](const Expr *E0, const Expr *E1) {
    if (auto *DRE0 = dyn_cast<DeclRefExpr>(E0))
      if (auto *DRE1 = dyn_cast<DeclRefExpr>(E1)) {
        return DRE0->getDecl() == DRE1->getDecl();
      }
    return false;
  };
  std::optional<llvm::APSInt> Arg1CV = Arg1->getIntegerConstantExpr(Ctx);

  if (Arg1CV && Arg1CV->isZero())
    // Check form 5:
    return true;

  // Check forms 1-3:
  switch (Arg0->getStmtClass()) {
  case Stmt::CXXNewExprClass:
    if (auto Size = cast<CXXNewExpr>(Arg0)->getArraySize()) {
      // Check form 1:
      return AreSameDRE((*Size)->IgnoreImplicit(), Arg1) ||
             HaveEqualConstantValues(*Size, Arg1);
    }
    // TODO: what's placeholder type? avoid it for now.
    if (!cast<CXXNewExpr>(Arg0)->hasPlaceholderType()) {
      // Check form 2:
      return Arg1CV && Arg1CV->isOne();
    }
    break;
  case Stmt::UnaryOperatorClass:
    if (cast<UnaryOperator>(Arg0)->getOpcode() ==
        UnaryOperator::Opcode::UO_AddrOf)
      // Check form 3:
      return Arg1CV && Arg1CV->isOne();
    break;
  case Stmt::CallExprClass:
    // Check form 3:
    if (const auto *CE = dyn_cast<CallExpr>(Arg0)) {
      const auto FnDecl = CE->getDirectCallee();
      if (FnDecl && FnDecl->getNameAsString() == "addressof" &&
          FnDecl->isInStdNamespace()) {
        return Arg1CV && Arg1CV->isOne();
      }
    }
    break;
  default:
    break;
  }

  QualType Arg0Ty = Arg0->IgnoreImplicit()->getType();

  if (auto *ConstArrTy = Ctx.getAsConstantArrayType(Arg0Ty)) {
    const llvm::APSInt ConstArrSize = llvm::APSInt(ConstArrTy->getSize());

    // Check form 4:
    return Arg1CV && llvm::APSInt::compareValues(ConstArrSize, *Arg1CV) == 0;
  }
  // Check form 6:
  if (auto CCast = dyn_cast<CStyleCastExpr>(Arg0)) {
    if (!CCast->getType()->isPointerType())
      return false;

    QualType PteTy = CCast->getType()->getPointeeType();

    if (!(PteTy->isConstantSizeType() && Ctx.getTypeSizeInChars(PteTy).isOne()))
      return false;

    if (const auto *Call = dyn_cast<CallExpr>(CCast->getSubExpr())) {
      if (const FunctionDecl *FD = Call->getDirectCallee())
        if (auto *AllocAttr = FD->getAttr<AllocSizeAttr>()) {
          const Expr *EleSizeExpr =
              Call->getArg(AllocAttr->getElemSizeParam().getASTIndex());
          // NumElemIdx is invalid if AllocSizeAttr has 1 argument:
          ParamIdx NumElemIdx = AllocAttr->getNumElemsParam();

          if (!NumElemIdx.isValid())
            return areEqualIntegers(Arg1, EleSizeExpr, Ctx);

          const Expr *NumElesExpr = Call->getArg(NumElemIdx.getASTIndex());

          if (auto BO = dyn_cast<BinaryOperator>(Arg1))
            return areEqualIntegralBinaryOperators(BO, NumElesExpr, BO_Mul,
                                                   EleSizeExpr, Ctx);
        }
    }
  }
  return false;
}

static bool isSafeArraySubscript(const ArraySubscriptExpr &Node,
                                 const ASTContext &Ctx) {
  // FIXME: Proper solution:
  //  - refactor Sema::CheckArrayAccess
  //    - split safe/OOB/unknown decision logic from diagnostics emitting code
  //    -  e. g. "Try harder to find a NamedDecl to point at in the note."
  //    already duplicated
  //  - call both from Sema and from here

  uint64_t limit;
  if (const auto *CATy =
          dyn_cast<ConstantArrayType>(Node.getBase()
                                          ->IgnoreParenImpCasts()
                                          ->getType()
                                          ->getUnqualifiedDesugaredType())) {
    limit = CATy->getLimitedSize();
  } else if (const auto *SLiteral = dyn_cast<clang::StringLiteral>(
                 Node.getBase()->IgnoreParenImpCasts())) {
    limit = SLiteral->getLength() + 1;
  } else {
    return false;
  }

  Expr::EvalResult EVResult;
  const Expr *IndexExpr = Node.getIdx();
  if (!IndexExpr->isValueDependent() &&
      IndexExpr->EvaluateAsInt(EVResult, Ctx)) {
    llvm::APSInt ArrIdx = EVResult.Val.getInt();
    // FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a
    // bug
    if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < limit)
      return true;
  } else if (const auto *BE = dyn_cast<BinaryOperator>(IndexExpr)) {
    // For an integer expression `e` and an integer constant `n`, `e & n` and
    // `n & e` are bounded by `n`:
    if (BE->getOpcode() != BO_And && BE->getOpcode() != BO_Rem)
      return false;

    const Expr *LHS = BE->getLHS();
    const Expr *RHS = BE->getRHS();

    if (BE->getOpcode() == BO_Rem) {
      // If n is a negative number, then n % const can be greater than const
      if (!LHS->getType()->isUnsignedIntegerType()) {
        return false;
      }

      if (!RHS->isValueDependent() && RHS->EvaluateAsInt(EVResult, Ctx)) {
        llvm::APSInt result = EVResult.Val.getInt();
        if (result.isNonNegative() && result.getLimitedValue() <= limit)
          return true;
      }

      return false;
    }

    if ((!LHS->isValueDependent() &&
         LHS->EvaluateAsInt(EVResult, Ctx)) || // case: `n & e`
        (!RHS->isValueDependent() &&
         RHS->EvaluateAsInt(EVResult, Ctx))) { // `e & n`
      llvm::APSInt result = EVResult.Val.getInt();
      if (result.isNonNegative() && result.getLimitedValue() < limit)
        return true;
    }
    return false;
  }
  return false;
}

namespace libc_func_matchers {
// Under `libc_func_matchers`, define a set of matchers that match unsafe
// functions in libc and unsafe calls to them.

//  A tiny parser to strip off common prefix and suffix of libc function names
//  in real code.
//
//  Given a function name, `matchName` returns `CoreName` according to the
//  following grammar:
//
//  LibcName     := CoreName | CoreName + "_s"
//  MatchingName := "__builtin_" + LibcName              |
//                  "__builtin___" + LibcName + "_chk"   |
//                  "__asan_" + LibcName
//
struct LibcFunNamePrefixSuffixParser {
  StringRef matchName(StringRef FunName, bool isBuiltin) {
    // Try to match __builtin_:
    if (isBuiltin && FunName.starts_with("__builtin_"))
      // Then either it is __builtin_LibcName or __builtin___LibcName_chk or
      // no match:
      return matchLibcNameOrBuiltinChk(
          FunName.drop_front(10 /* truncate "__builtin_" */));
    // Try to match __asan_:
    if (FunName.starts_with("__asan_"))
      return matchLibcName(FunName.drop_front(7 /* truncate of "__asan_" */));
    return matchLibcName(FunName);
  }

  // Parameter `Name` is the substring after stripping off the prefix
  // "__builtin_".
  StringRef matchLibcNameOrBuiltinChk(StringRef Name) {
    if (Name.starts_with("__") && Name.ends_with("_chk"))
      return matchLibcName(
          Name.drop_front(2).drop_back(4) /* truncate "__" and "_chk" */);
    return matchLibcName(Name);
  }

  StringRef matchLibcName(StringRef Name) {
    if (Name.ends_with("_s"))
      return Name.drop_back(2 /* truncate "_s" */);
    return Name;
  }
};

// A pointer type expression is known to be null-terminated, if it has the
// form: E.c_str(), for any expression E of `std::string` type.
static bool isNullTermPointer(const Expr *Ptr) {
  if (isa<clang::StringLiteral>(Ptr->IgnoreParenImpCasts()))
    return true;
  if (isa<PredefinedExpr>(Ptr->IgnoreParenImpCasts()))
    return true;
  if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Ptr->IgnoreParenImpCasts())) {
    const CXXMethodDecl *MD = MCE->getMethodDecl();
    const CXXRecordDecl *RD = MCE->getRecordDecl()->getCanonicalDecl();

    if (MD && RD && RD->isInStdNamespace() && MD->getIdentifier())
      if (MD->getName() == "c_str" && RD->getName() == "basic_string")
        return true;
  }
  return false;
}

// Return true iff at least one of following cases holds:
//  1. Format string is a literal and there is an unsafe pointer argument
//     corresponding to an `s` specifier;
//  2. Format string is not a literal and there is least an unsafe pointer
//     argument (including the formatter argument).
//
// `UnsafeArg` is the output argument that will be set only if this function
// returns true.
static bool hasUnsafeFormatOrSArg(const CallExpr *Call, const Expr *&UnsafeArg,
                                  const unsigned FmtArgIdx, ASTContext &Ctx,
                                  bool isKprintf = false) {
  class StringFormatStringHandler
      : public analyze_format_string::FormatStringHandler {
    const CallExpr *Call;
    unsigned FmtArgIdx;
    const Expr *&UnsafeArg;

  public:
    StringFormatStringHandler(const CallExpr *Call, unsigned FmtArgIdx,
                              const Expr *&UnsafeArg)
        : Call(Call), FmtArgIdx(FmtArgIdx), UnsafeArg(UnsafeArg) {}

    bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
                               const char *startSpecifier,
                               unsigned specifierLen,
                               const TargetInfo &Target) override {
      if (FS.getConversionSpecifier().getKind() ==
          analyze_printf::PrintfConversionSpecifier::sArg) {
        unsigned ArgIdx = FS.getPositionalArgIndex() + FmtArgIdx;

        if (0 < ArgIdx && ArgIdx < Call->getNumArgs())
          if (!isNullTermPointer(Call->getArg(ArgIdx))) {
            UnsafeArg = Call->getArg(ArgIdx); // output
            // returning false stops parsing immediately
            return false;
          }
      }
      return true; // continue parsing
    }
  };

  const Expr *Fmt = Call->getArg(FmtArgIdx);

  if (auto *SL = dyn_cast<clang::StringLiteral>(Fmt->IgnoreParenImpCasts())) {
    StringRef FmtStr;

    if (SL->getCharByteWidth() == 1)
      FmtStr = SL->getString();
    else if (auto EvaledFmtStr = SL->tryEvaluateString(Ctx))
      FmtStr = *EvaledFmtStr;
    else
      goto CHECK_UNSAFE_PTR;

    StringFormatStringHandler Handler(Call, FmtArgIdx, UnsafeArg);

    return analyze_format_string::ParsePrintfString(
        Handler, FmtStr.begin(), FmtStr.end(), Ctx.getLangOpts(),
        Ctx.getTargetInfo(), isKprintf);
  }
CHECK_UNSAFE_PTR:
  // If format is not a string literal, we cannot analyze the format string.
  // In this case, this call is considered unsafe if at least one argument
  // (including the format argument) is unsafe pointer.
  return llvm::any_of(
      llvm::make_range(Call->arg_begin() + FmtArgIdx, Call->arg_end()),
      [&UnsafeArg](const Expr *Arg) -> bool {
        if (Arg->getType()->isPointerType() && !isNullTermPointer(Arg)) {
          UnsafeArg = Arg;
          return true;
        }
        return false;
      });
}

// Matches a FunctionDecl node such that
//  1. It's name, after stripping off predefined prefix and suffix, is
//     `CoreName`; and
//  2. `CoreName` or `CoreName[str/wcs]` is one of the `PredefinedNames`, which
//     is a set of libc function names.
//
//  Note: For predefined prefix and suffix, see `LibcFunNamePrefixSuffixParser`.
//  The notation `CoreName[str/wcs]` means a new name obtained from replace
//  string "wcs" with "str" in `CoreName`.
static bool isPredefinedUnsafeLibcFunc(const FunctionDecl &Node) {
  static std::unique_ptr<std::set<StringRef>> PredefinedNames = nullptr;
  if (!PredefinedNames)
    PredefinedNames =
        std::make_unique<std::set<StringRef>, std::set<StringRef>>({
            // numeric conversion:
            "atof",
            "atoi",
            "atol",
            "atoll",
            "strtol",
            "strtoll",
            "strtoul",
            "strtoull",
            "strtof",
            "strtod",
            "strtold",
            "strtoimax",
            "strtoumax",
            // "strfromf",  "strfromd", "strfroml", // C23?
            // string manipulation:
            "strcpy",
            "strncpy",
            "strlcpy",
            "strcat",
            "strncat",
            "strlcat",
            "strxfrm",
            "strdup",
            "strndup",
            // string examination:
            "strlen",
            "strnlen",
            "strcmp",
            "strncmp",
            "stricmp",
            "strcasecmp",
            "strcoll",
            "strchr",
            "strrchr",
            "strspn",
            "strcspn",
            "strpbrk",
            "strstr",
            "strtok",
            // "mem-" functions
            "memchr",
            "wmemchr",
            "memcmp",
            "wmemcmp",
            "memcpy",
            "memccpy",
            "mempcpy",
            "wmemcpy",
            "memmove",
            "wmemmove",
            "memset",
            "wmemset",
            // IO:
            "fread",
            "fwrite",
            "fgets",
            "fgetws",
            "gets",
            "fputs",
            "fputws",
            "puts",
            // others
            "strerror_s",
            "strerror_r",
            "bcopy",
            "bzero",
            "bsearch",
            "qsort",
        });

  auto *II = Node.getIdentifier();

  if (!II)
    return false;

  StringRef Name = LibcFunNamePrefixSuffixParser().matchName(
      II->getName(), Node.getBuiltinID());

  // Match predefined names:
  if (PredefinedNames->find(Name) != PredefinedNames->end())
    return true;

  std::string NameWCS = Name.str();
  size_t WcsPos = NameWCS.find("wcs");

  while (WcsPos != std::string::npos) {
    NameWCS[WcsPos++] = 's';
    NameWCS[WcsPos++] = 't';
    NameWCS[WcsPos++] = 'r';
    WcsPos = NameWCS.find("wcs", WcsPos);
  }
  if (PredefinedNames->find(NameWCS) != PredefinedNames->end())
    return true;
  // All `scanf` functions are unsafe (including `sscanf`, `vsscanf`, etc.. They
  // all should end with "scanf"):
  return Name.ends_with("scanf");
}

// Match a call to one of the `v*printf` functions taking `va_list`.  We cannot
// check safety for these functions so they should be changed to their
// non-va_list versions.
static bool isUnsafeVaListPrintfFunc(const FunctionDecl &Node) {
  auto *II = Node.getIdentifier();

  if (!II)
    return false;

  StringRef Name = LibcFunNamePrefixSuffixParser().matchName(
      II->getName(), Node.getBuiltinID());

  if (!Name.ends_with("printf"))
    return false; // neither printf nor scanf
  return Name.starts_with("v");
}

// Matches a call to one of the `sprintf` functions as they are always unsafe
// and should be changed to `snprintf`.
static bool isUnsafeSprintfFunc(const FunctionDecl &Node) {
  auto *II = Node.getIdentifier();

  if (!II)
    return false;

  StringRef Name = LibcFunNamePrefixSuffixParser().matchName(
      II->getName(), Node.getBuiltinID());

  if (!Name.ends_with("printf") ||
      // Let `isUnsafeVaListPrintfFunc` check for cases with va-list:
      Name.starts_with("v"))
    return false;

  StringRef Prefix = Name.drop_back(6);

  if (Prefix.ends_with("w"))
    Prefix = Prefix.drop_back(1);
  return Prefix == "s";
}

// Match function declarations of `printf`, `fprintf`, `snprintf` and their wide
// character versions.  Calls to these functions can be safe if their arguments
// are carefully made safe.
static bool isNormalPrintfFunc(const FunctionDecl &Node) {
  auto *II = Node.getIdentifier();

  if (!II)
    return false;

  StringRef Name = LibcFunNamePrefixSuffixParser().matchName(
      II->getName(), Node.getBuiltinID());

  if (!Name.ends_with("printf") || Name.starts_with("v"))
    return false;

  StringRef Prefix = Name.drop_back(6);

  if (Prefix.ends_with("w"))
    Prefix = Prefix.drop_back(1);

  return Prefix.empty() || Prefix == "k" || Prefix == "f" || Prefix == "sn";
}

// This matcher requires that it is known that the callee `isNormalPrintf`.
// Then if the format string is a string literal, this matcher matches when at
// least one string argument is unsafe. If the format is not a string literal,
// this matcher matches when at least one pointer type argument is unsafe.
static bool hasUnsafePrintfStringArg(const CallExpr &Node, ASTContext &Ctx,
                                     MatchResult &Result, llvm::StringRef Tag) {
  // Determine what printf it is by examining formal parameters:
  const FunctionDecl *FD = Node.getDirectCallee();

  assert(FD && "It should have been checked that FD is non-null.");

  unsigned NumParms = FD->getNumParams();

  if (NumParms < 1)
    return false; // possibly some user-defined printf function

  QualType FirstParmTy = FD->getParamDecl(0)->getType();

  if (!FirstParmTy->isPointerType())
    return false; // possibly some user-defined printf function

  QualType FirstPteTy = FirstParmTy->castAs<PointerType>()->getPointeeType();

  if (!Ctx.getFILEType()
           .isNull() && //`FILE *` must be in the context if it is fprintf
      FirstPteTy.getCanonicalType() == Ctx.getFILEType().getCanonicalType()) {
    // It is a fprintf:
    const Expr *UnsafeArg;

    if (hasUnsafeFormatOrSArg(&Node, UnsafeArg, 1, Ctx, false)) {
      Result.addNode(Tag, DynTypedNode::create(*UnsafeArg));
      return true;
    }
    return false;
  }

  if (FirstPteTy.isConstQualified()) {
    // If the first parameter is a `const char *`, it is a printf/kprintf:
    bool isKprintf = false;
    const Expr *UnsafeArg;

    if (auto *II = FD->getIdentifier())
      isKprintf = II->getName() == "kprintf";
    if (hasUnsafeFormatOrSArg(&Node, UnsafeArg, 0, Ctx, isKprintf)) {
      Result.addNode(Tag, DynTypedNode::create(*UnsafeArg));
      return true;
    }
    return false;
  }

  if (NumParms > 2) {
    QualType SecondParmTy = FD->getParamDecl(1)->getType();

    if (!FirstPteTy.isConstQualified() && SecondParmTy->isIntegerType()) {
      // If the first parameter type is non-const qualified `char *` and the
      // second is an integer, it is a snprintf:
      const Expr *UnsafeArg;

      if (hasUnsafeFormatOrSArg(&Node, UnsafeArg, 2, Ctx, false)) {
        Result.addNode(Tag, DynTypedNode::create(*UnsafeArg));
        return true;
      }
      return false;
    }
  }
  // We don't really recognize this "normal" printf, the only thing we
  // can do is to require all pointers to be null-terminated:
  for (const auto *Arg : Node.arguments())
    if (Arg->getType()->isPointerType() && !isNullTermPointer(Arg)) {
      Result.addNode(Tag, DynTypedNode::create(*Arg));
      return true;
    }
  return false;
}

// This matcher requires that it is known that the callee `isNormalPrintf`.
// Then it matches if the first two arguments of the call is a pointer and an
// integer and they are not in a safe pattern.
//
// For the first two arguments: `ptr` and `size`, they are safe if in the
// following patterns:
//
// Pattern 1:
//    ptr := DRE.data();
//    size:= DRE.size()/DRE.size_bytes()
// And DRE is a hardened container or view.
//
// Pattern 2:
//    ptr := Constant-Array-DRE;
//    size:= any expression that has compile-time constant value equivalent to
//           sizeof (Constant-Array-DRE)
static bool hasUnsafeSnprintfBuffer(const CallExpr &Node,
                                    const ASTContext &Ctx) {
  const FunctionDecl *FD = Node.getDirectCallee();

  assert(FD && "It should have been checked that FD is non-null.");

  if (FD->getNumParams() < 3)
    return false; // Not an snprint

  QualType FirstParmTy = FD->getParamDecl(0)->getType();

  if (!FirstParmTy->isPointerType())
    return false; // Not an snprint

  QualType FirstPteTy = FirstParmTy->castAs<PointerType>()->getPointeeType();
  const Expr *Buf = Node.getArg(0), *Size = Node.getArg(1);

  if (FirstPteTy.isConstQualified() || !Buf->getType()->isPointerType() ||
      !Size->getType()->isIntegerType())
    return false; // not an snprintf call

  // Pattern 1:
  static StringRef SizedObjs[] = {"span", "array", "vector",
                                  "basic_string_view", "basic_string"};
  Buf = Buf->IgnoreParenImpCasts();
  Size = Size->IgnoreParenImpCasts();
  if (auto *MCEPtr = dyn_cast<CXXMemberCallExpr>(Buf))
    if (auto *MCESize = dyn_cast<CXXMemberCallExpr>(Size)) {
      auto *DREOfPtr = dyn_cast<DeclRefExpr>(
          MCEPtr->getImplicitObjectArgument()->IgnoreParenImpCasts());
      auto *DREOfSize = dyn_cast<DeclRefExpr>(
          MCESize->getImplicitObjectArgument()->IgnoreParenImpCasts());

      if (!DREOfPtr || !DREOfSize)
        return true; // not in safe pattern
      if (DREOfPtr->getDecl() != DREOfSize->getDecl())
        return true; // not in safe pattern
      if (MCEPtr->getMethodDecl()->getName() != "data")
        return true; // not in safe pattern

      if (MCESize->getMethodDecl()->getName() == "size_bytes" ||
          // Note here the pointer must be a pointer-to-char type unless there
          // is explicit casting.  If there is explicit casting, this branch
          // is unreachable. Thus, at this branch "size" and "size_bytes" are
          // equivalent as the pointer is a char pointer:
          MCESize->getMethodDecl()->getName() == "size")
        for (StringRef SizedObj : SizedObjs)
          if (MCEPtr->getRecordDecl()->isInStdNamespace() &&
              MCEPtr->getRecordDecl()->getCanonicalDecl()->getName() ==
                  SizedObj)
            return false; // It is in fact safe
    }

  // Pattern 2:
  if (auto *DRE = dyn_cast<DeclRefExpr>(Buf->IgnoreParenImpCasts())) {
    if (auto *CAT = Ctx.getAsConstantArrayType(DRE->getType())) {
      Expr::EvalResult ER;
      // The array element type must be compatible with `char` otherwise an
      // explicit cast will be needed, which will make this check unreachable.
      // Therefore, the array extent is same as its' bytewise size.
      if (Size->EvaluateAsInt(ER, Ctx)) {
        llvm::APSInt EVal = ER.Val.getInt(); // Size must have integer type

        return llvm::APSInt::compareValues(
                   EVal, llvm::APSInt(CAT->getSize(), true)) != 0;
      }
    }
  }
  return true; // ptr and size are not in safe pattern
}
} // namespace libc_func_matchers

namespace {
// Because the analysis revolves around variables and their types, we'll need to
// track uses of variables (aka DeclRefExprs).
using DeclUseList = SmallVector<const DeclRefExpr *, 1>;

// Convenience typedef.
using FixItList = SmallVector<FixItHint, 4>;
} // namespace

namespace {
/// Gadget is an individual operation in the code that may be of interest to
/// this analysis. Each (non-abstract) subclass corresponds to a specific
/// rigid AST structure that constitutes an operation on a pointer-type object.
/// Discovery of a gadget in the code corresponds to claiming that we understand
/// what this part of code is doing well enough to potentially improve it.
/// Gadgets can be warning (immediately deserving a warning) or fixable (not
/// always deserving a warning per se, but requires our attention to identify
/// it warrants a fixit).
class Gadget {
public:
  enum class Kind {
#define GADGET(x) x,
#include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
  };

  Gadget(Kind K) : K(K) {}

  Kind getKind() const { return K; }

#ifndef NDEBUG
  StringRef getDebugName() const {
    switch (K) {
#define GADGET(x)                                                              \
  case Kind::x:                                                                \
    return #x;
#include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
    }
    llvm_unreachable("Unhandled Gadget::Kind enum");
  }
#endif

  virtual bool isWarningGadget() const = 0;
  // TODO remove this method from WarningGadget interface. It's only used for
  // debug prints in FixableGadget.
  virtual SourceLocation getSourceLoc() const = 0;

  /// Returns the list of pointer-type variables on which this gadget performs
  /// its operation. Typically, there's only one variable. This isn't a list
  /// of all DeclRefExprs in the gadget's AST!
  virtual DeclUseList getClaimedVarUseSites() const = 0;

  virtual ~Gadget() = default;

private:
  Kind K;
};

/// Warning gadgets correspond to unsafe code patterns that warrants
/// an immediate warning.
class WarningGadget : public Gadget {
public:
  WarningGadget(Kind K) : Gadget(K) {}

  static bool classof(const Gadget *G) { return G->isWarningGadget(); }
  bool isWarningGadget() const final { return true; }

  virtual void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                                     bool IsRelatedToDecl,
                                     ASTContext &Ctx) const = 0;

  virtual SmallVector<const Expr *, 1> getUnsafePtrs() const = 0;
};

/// Fixable gadgets correspond to code patterns that aren't always unsafe but
/// need to be properly recognized in order to emit fixes. For example, if a raw
/// pointer-type variable is replaced by a safe C++ container, every use of such
/// variable must be carefully considered and possibly updated.
class FixableGadget : public Gadget {
public:
  FixableGadget(Kind K) : Gadget(K) {}

  static bool classof(const Gadget *G) { return !G->isWarningGadget(); }
  bool isWarningGadget() const final { return false; }

  /// Returns a fixit that would fix the current gadget according to
  /// the current strategy. Returns std::nullopt if the fix cannot be produced;
  /// returns an empty list if no fixes are necessary.
  virtual std::optional<FixItList> getFixits(const FixitStrategy &) const {
    return std::nullopt;
  }

  /// Returns a list of two elements where the first element is the LHS of a
  /// pointer assignment statement and the second element is the RHS. This
  /// two-element list represents the fact that the LHS buffer gets its bounds
  /// information from the RHS buffer. This information will be used later to
  /// group all those variables whose types must be modified together to prevent
  /// type mismatches.
  virtual std::optional<std::pair<const VarDecl *, const VarDecl *>>
  getStrategyImplications() const {
    return std::nullopt;
  }
};

static bool isSupportedVariable(const DeclRefExpr &Node) {
  const Decl *D = Node.getDecl();
  return D != nullptr && isa<VarDecl>(D);
}

using FixableGadgetList = std::vector<std::unique_ptr<FixableGadget>>;
using WarningGadgetList = std::vector<std::unique_ptr<WarningGadget>>;

/// An increment of a pointer-type value is unsafe as it may run the pointer
/// out of bounds.
class IncrementGadget : public WarningGadget {
  static constexpr const char *const OpTag = "op";
  const UnaryOperator *Op;

public:
  IncrementGadget(const MatchResult &Result)
      : WarningGadget(Kind::Increment),
        Op(Result.getNodeAs<UnaryOperator>(OpTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::Increment;
  }

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {
    const auto *UO = dyn_cast<UnaryOperator>(S);
    if (!UO || !UO->isIncrementOp())
      return false;
    if (!hasPointerType(*UO->getSubExpr()->IgnoreParenImpCasts()))
      return false;
    Result.addNode(OpTag, DynTypedNode::create(*UO));
    return true;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override {
    SmallVector<const DeclRefExpr *, 2> Uses;
    if (const auto *DRE =
            dyn_cast<DeclRefExpr>(Op->getSubExpr()->IgnoreParenImpCasts())) {
      Uses.push_back(DRE);
    }

    return std::move(Uses);
  }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override {
    return {Op->getSubExpr()->IgnoreParenImpCasts()};
  }
};

/// A decrement of a pointer-type value is unsafe as it may run the pointer
/// out of bounds.
class DecrementGadget : public WarningGadget {
  static constexpr const char *const OpTag = "op";
  const UnaryOperator *Op;

public:
  DecrementGadget(const MatchResult &Result)
      : WarningGadget(Kind::Decrement),
        Op(Result.getNodeAs<UnaryOperator>(OpTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::Decrement;
  }

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {
    const auto *UO = dyn_cast<UnaryOperator>(S);
    if (!UO || !UO->isDecrementOp())
      return false;
    if (!hasPointerType(*UO->getSubExpr()->IgnoreParenImpCasts()))
      return false;
    Result.addNode(OpTag, DynTypedNode::create(*UO));
    return true;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override {
    if (const auto *DRE =
            dyn_cast<DeclRefExpr>(Op->getSubExpr()->IgnoreParenImpCasts())) {
      return {DRE};
    }

    return {};
  }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override {
    return {Op->getSubExpr()->IgnoreParenImpCasts()};
  }
};

/// Array subscript expressions on raw pointers as if they're arrays. Unsafe as
/// it doesn't have any bounds checks for the array.
class ArraySubscriptGadget : public WarningGadget {
  static constexpr const char *const ArraySubscrTag = "ArraySubscript";
  const ArraySubscriptExpr *ASE;

public:
  ArraySubscriptGadget(const MatchResult &Result)
      : WarningGadget(Kind::ArraySubscript),
        ASE(Result.getNodeAs<ArraySubscriptExpr>(ArraySubscrTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::ArraySubscript;
  }

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {
    const auto *ASE = dyn_cast<ArraySubscriptExpr>(S);
    if (!ASE)
      return false;
    const auto *const Base = ASE->getBase()->IgnoreParenImpCasts();
    if (!hasPointerType(*Base) && !hasArrayType(*Base))
      return false;
    const auto *Idx = dyn_cast<IntegerLiteral>(ASE->getIdx());
    bool IsSafeIndex = (Idx && Idx->getValue().isZero()) ||
                       isa<ArrayInitIndexExpr>(ASE->getIdx());
    if (IsSafeIndex || isSafeArraySubscript(*ASE, Ctx))
      return false;
    Result.addNode(ArraySubscrTag, DynTypedNode::create(*ASE));
    return true;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(ASE, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return ASE->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override {
    if (const auto *DRE =
            dyn_cast<DeclRefExpr>(ASE->getBase()->IgnoreParenImpCasts())) {
      return {DRE};
    }

    return {};
  }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override {
    return {ASE->getBase()->IgnoreParenImpCasts()};
  }
};

/// A pointer arithmetic expression of one of the forms:
///  \code
///  ptr + n | n + ptr | ptr - n | ptr += n | ptr -= n
///  \endcode
class PointerArithmeticGadget : public WarningGadget {
  static constexpr const char *const PointerArithmeticTag = "ptrAdd";
  static constexpr const char *const PointerArithmeticPointerTag = "ptrAddPtr";
  const BinaryOperator *PA; // pointer arithmetic expression
  const Expr *Ptr;          // the pointer expression in `PA`

public:
  PointerArithmeticGadget(const MatchResult &Result)
      : WarningGadget(Kind::PointerArithmetic),
        PA(Result.getNodeAs<BinaryOperator>(PointerArithmeticTag)),
        Ptr(Result.getNodeAs<Expr>(PointerArithmeticPointerTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::PointerArithmetic;
  }

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {
    const auto *BO = dyn_cast<BinaryOperator>(S);
    if (!BO)
      return false;
    const auto *LHS = BO->getLHS();
    const auto *RHS = BO->getRHS();
    // ptr at left
    if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub ||
        BO->getOpcode() == BO_AddAssign || BO->getOpcode() == BO_SubAssign) {
      if (hasPointerType(*LHS) && (RHS->getType()->isIntegerType() ||
                                   RHS->getType()->isEnumeralType())) {
        Result.addNode(PointerArithmeticPointerTag, DynTypedNode::create(*LHS));
        Result.addNode(PointerArithmeticTag, DynTypedNode::create(*BO));
        return true;
      }
    }
    // ptr at right
    if (BO->getOpcode() == BO_Add && hasPointerType(*RHS) &&
        (LHS->getType()->isIntegerType() || LHS->getType()->isEnumeralType())) {
      Result.addNode(PointerArithmeticPointerTag, DynTypedNode::create(*RHS));
      Result.addNode(PointerArithmeticTag, DynTypedNode::create(*BO));
      return true;
    }
    return false;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(PA, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return PA->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override {
    if (const auto *DRE = dyn_cast<DeclRefExpr>(Ptr->IgnoreParenImpCasts())) {
      return {DRE};
    }

    return {};
  }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override {
    return {Ptr->IgnoreParenImpCasts()};
  }

  // FIXME: pointer adding zero should be fine
  // FIXME: this gadge will need a fix-it
};

class SpanTwoParamConstructorGadget : public WarningGadget {
  static constexpr const char *const SpanTwoParamConstructorTag =
      "spanTwoParamConstructor";
  const CXXConstructExpr *Ctor; // the span constructor expression

public:
  SpanTwoParamConstructorGadget(const MatchResult &Result)
      : WarningGadget(Kind::SpanTwoParamConstructor),
        Ctor(Result.getNodeAs<CXXConstructExpr>(SpanTwoParamConstructorTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::SpanTwoParamConstructor;
  }

  static bool matches(const Stmt *S, ASTContext &Ctx, MatchResult &Result) {
    const auto *CE = dyn_cast<CXXConstructExpr>(S);
    if (!CE)
      return false;
    const auto *CDecl = CE->getConstructor();
    const auto *CRecordDecl = CDecl->getParent();
    auto HasTwoParamSpanCtorDecl =
        CRecordDecl->isInStdNamespace() &&
        CDecl->getDeclName().getAsString() == "span" && CE->getNumArgs() == 2;
    if (!HasTwoParamSpanCtorDecl || isSafeSpanTwoParamConstruct(*CE, Ctx))
      return false;
    Result.addNode(SpanTwoParamConstructorTag, DynTypedNode::create(*CE));
    return true;
  }

  static bool matches(const Stmt *S, ASTContext &Ctx,
                      const UnsafeBufferUsageHandler *Handler,
                      MatchResult &Result) {
    if (ignoreUnsafeBufferInContainer(*S, Handler))
      return false;
    return matches(S, Ctx, Result);
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperationInContainer(Ctor, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return Ctor->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override {
    // If the constructor call is of the form `std::span{var, n}`, `var` is
    // considered an unsafe variable.
    if (auto *DRE = dyn_cast<DeclRefExpr>(Ctor->getArg(0))) {
      if (isa<VarDecl>(DRE->getDecl()))
        return {DRE};
    }
    return {};
  }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
};

/// A pointer initialization expression of the form:
///  \code
///  int *p = q;
///  \endcode
class PointerInitGadget : public FixableGadget {
private:
  static constexpr const char *const PointerInitLHSTag = "ptrInitLHS";
  static constexpr const char *const PointerInitRHSTag = "ptrInitRHS";
  const VarDecl *PtrInitLHS;     // the LHS pointer expression in `PI`
  const DeclRefExpr *PtrInitRHS; // the RHS pointer expression in `PI`

public:
  PointerInitGadget(const MatchResult &Result)
      : FixableGadget(Kind::PointerInit),
        PtrInitLHS(Result.getNodeAs<VarDecl>(PointerInitLHSTag)),
        PtrInitRHS(Result.getNodeAs<DeclRefExpr>(PointerInitRHSTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::PointerInit;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    const DeclStmt *DS = dyn_cast<DeclStmt>(S);
    if (!DS || !DS->isSingleDecl())
      return false;
    const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
    if (!VD)
      return false;
    const Expr *Init = VD->getAnyInitializer();
    if (!Init)
      return false;
    const auto *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreImpCasts());
    if (!DRE || !hasPointerType(*DRE) || !isSupportedVariable(*DRE)) {
      return false;
    }
    MatchResult R;
    R.addNode(PointerInitLHSTag, DynTypedNode::create(*VD));
    R.addNode(PointerInitRHSTag, DynTypedNode::create(*DRE));
    Results.emplace_back(std::move(R));
    return true;
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override {
    return PtrInitRHS->getBeginLoc();
  }

  virtual DeclUseList getClaimedVarUseSites() const override {
    return DeclUseList{PtrInitRHS};
  }

  virtual std::optional<std::pair<const VarDecl *, const VarDecl *>>
  getStrategyImplications() const override {
    return std::make_pair(PtrInitLHS, cast<VarDecl>(PtrInitRHS->getDecl()));
  }
};

/// A pointer assignment expression of the form:
///  \code
///  p = q;
///  \endcode
/// where both `p` and `q` are pointers.
class PtrToPtrAssignmentGadget : public FixableGadget {
private:
  static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
  static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
  const DeclRefExpr *PtrLHS; // the LHS pointer expression in `PA`
  const DeclRefExpr *PtrRHS; // the RHS pointer expression in `PA`

public:
  PtrToPtrAssignmentGadget(const MatchResult &Result)
      : FixableGadget(Kind::PtrToPtrAssignment),
        PtrLHS(Result.getNodeAs<DeclRefExpr>(PointerAssignLHSTag)),
        PtrRHS(Result.getNodeAs<DeclRefExpr>(PointerAssignRHSTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::PtrToPtrAssignment;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedUntypedContext(S, [&Results](const Stmt *S) {
      const auto *BO = dyn_cast<BinaryOperator>(S);
      if (!BO || BO->getOpcode() != BO_Assign)
        return;
      const auto *RHS = BO->getRHS()->IgnoreParenImpCasts();
      if (const auto *RHSRef = dyn_cast<DeclRefExpr>(RHS);
          !RHSRef || !hasPointerType(*RHSRef) ||
          !isSupportedVariable(*RHSRef)) {
        return;
      }
      const auto *LHS = BO->getLHS();
      if (const auto *LHSRef = dyn_cast<DeclRefExpr>(LHS);
          !LHSRef || !hasPointerType(*LHSRef) ||
          !isSupportedVariable(*LHSRef)) {
        return;
      }
      MatchResult R;
      R.addNode(PointerAssignLHSTag, DynTypedNode::create(*LHS));
      R.addNode(PointerAssignRHSTag, DynTypedNode::create(*RHS));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return PtrLHS->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override {
    return DeclUseList{PtrLHS, PtrRHS};
  }

  virtual std::optional<std::pair<const VarDecl *, const VarDecl *>>
  getStrategyImplications() const override {
    return std::make_pair(cast<VarDecl>(PtrLHS->getDecl()),
                          cast<VarDecl>(PtrRHS->getDecl()));
  }
};

/// An assignment expression of the form:
///  \code
///  ptr = array;
///  \endcode
/// where `p` is a pointer and `array` is a constant size array.
class CArrayToPtrAssignmentGadget : public FixableGadget {
private:
  static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
  static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
  const DeclRefExpr *PtrLHS; // the LHS pointer expression in `PA`
  const DeclRefExpr *PtrRHS; // the RHS pointer expression in `PA`

public:
  CArrayToPtrAssignmentGadget(const MatchResult &Result)
      : FixableGadget(Kind::CArrayToPtrAssignment),
        PtrLHS(Result.getNodeAs<DeclRefExpr>(PointerAssignLHSTag)),
        PtrRHS(Result.getNodeAs<DeclRefExpr>(PointerAssignRHSTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::CArrayToPtrAssignment;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedUntypedContext(S, [&Results](const Stmt *S) {
      const auto *BO = dyn_cast<BinaryOperator>(S);
      if (!BO || BO->getOpcode() != BO_Assign)
        return;
      const auto *RHS = BO->getRHS()->IgnoreParenImpCasts();
      if (const auto *RHSRef = dyn_cast<DeclRefExpr>(RHS);
          !RHSRef ||
          !isa<ConstantArrayType>(RHSRef->getType().getCanonicalType()) ||
          !isSupportedVariable(*RHSRef)) {
        return;
      }
      const auto *LHS = BO->getLHS();
      if (const auto *LHSRef = dyn_cast<DeclRefExpr>(LHS);
          !LHSRef || !hasPointerType(*LHSRef) ||
          !isSupportedVariable(*LHSRef)) {
        return;
      }
      MatchResult R;
      R.addNode(PointerAssignLHSTag, DynTypedNode::create(*LHS));
      R.addNode(PointerAssignRHSTag, DynTypedNode::create(*RHS));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return PtrLHS->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override {
    return DeclUseList{PtrLHS, PtrRHS};
  }

  virtual std::optional<std::pair<const VarDecl *, const VarDecl *>>
  getStrategyImplications() const override {
    return {};
  }
};

/// A call of a function or method that performs unchecked buffer operations
/// over one of its pointer parameters.
class UnsafeBufferUsageAttrGadget : public WarningGadget {
  constexpr static const char *const OpTag = "attr_expr";
  const Expr *Op;

public:
  UnsafeBufferUsageAttrGadget(const MatchResult &Result)
      : WarningGadget(Kind::UnsafeBufferUsageAttr),
        Op(Result.getNodeAs<Expr>(OpTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::UnsafeBufferUsageAttr;
  }

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {
    if (auto *CE = dyn_cast<CallExpr>(S)) {
      if (CE->getDirectCallee() &&
          CE->getDirectCallee()->hasAttr<UnsafeBufferUsageAttr>()) {
        Result.addNode(OpTag, DynTypedNode::create(*CE));
        return true;
      }
    }
    if (auto *ME = dyn_cast<MemberExpr>(S)) {
      if (!isa<FieldDecl>(ME->getMemberDecl()))
        return false;
      if (ME->getMemberDecl()->hasAttr<UnsafeBufferUsageAttr>()) {
        Result.addNode(OpTag, DynTypedNode::create(*ME));
        return true;
      }
    }
    return false;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override { return {}; }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
};

/// A call of a constructor that performs unchecked buffer operations
/// over one of its pointer parameters, or constructs a class object that will
/// perform buffer operations that depend on the correctness of the parameters.
class UnsafeBufferUsageCtorAttrGadget : public WarningGadget {
  constexpr static const char *const OpTag = "cxx_construct_expr";
  const CXXConstructExpr *Op;

public:
  UnsafeBufferUsageCtorAttrGadget(const MatchResult &Result)
      : WarningGadget(Kind::UnsafeBufferUsageCtorAttr),
        Op(Result.getNodeAs<CXXConstructExpr>(OpTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::UnsafeBufferUsageCtorAttr;
  }

  static bool matches(const Stmt *S, ASTContext &Ctx, MatchResult &Result) {
    const auto *CE = dyn_cast<CXXConstructExpr>(S);
    if (!CE || !CE->getConstructor()->hasAttr<UnsafeBufferUsageAttr>())
      return false;
    // std::span(ptr, size) ctor is handled by SpanTwoParamConstructorGadget.
    MatchResult Tmp;
    if (SpanTwoParamConstructorGadget::matches(CE, Ctx, Tmp))
      return false;
    Result.addNode(OpTag, DynTypedNode::create(*CE));
    return true;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override { return {}; }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
};

// Warning gadget for unsafe invocation of span::data method.
// Triggers when the pointer returned by the invocation is immediately
// cast to a larger type.

class DataInvocationGadget : public WarningGadget {
  constexpr static const char *const OpTag = "data_invocation_expr";
  const ExplicitCastExpr *Op;

public:
  DataInvocationGadget(const MatchResult &Result)
      : WarningGadget(Kind::DataInvocation),
        Op(Result.getNodeAs<ExplicitCastExpr>(OpTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::DataInvocation;
  }

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {
    auto *CE = dyn_cast<ExplicitCastExpr>(S);
    if (!CE)
      return false;
    for (auto *Child : CE->children()) {
      if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Child);
          MCE && isDataFunction(MCE)) {
        Result.addNode(OpTag, DynTypedNode::create(*CE));
        return true;
      }
      if (auto *Paren = dyn_cast<ParenExpr>(Child)) {
        if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Paren->getSubExpr());
            MCE && isDataFunction(MCE)) {
          Result.addNode(OpTag, DynTypedNode::create(*CE));
          return true;
        }
      }
    }
    return false;
  }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeOperation(Op, IsRelatedToDecl, Ctx);
  }
  SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }

  DeclUseList getClaimedVarUseSites() const override { return {}; }

private:
  static bool isDataFunction(const CXXMemberCallExpr *call) {
    if (!call)
      return false;
    auto *callee = call->getDirectCallee();
    if (!callee || !isa<CXXMethodDecl>(callee))
      return false;
    auto *method = cast<CXXMethodDecl>(callee);
    if (method->getNameAsString() == "data" &&
        method->getParent()->isInStdNamespace() &&
        (method->getParent()->getName() == "span" ||
         method->getParent()->getName() == "array" ||
         method->getParent()->getName() == "vector"))
      return true;
    return false;
  }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
};

class UnsafeLibcFunctionCallGadget : public WarningGadget {
  const CallExpr *const Call;
  const Expr *UnsafeArg = nullptr;
  constexpr static const char *const Tag = "UnsafeLibcFunctionCall";
  // Extra tags for additional information:
  constexpr static const char *const UnsafeSprintfTag =
      "UnsafeLibcFunctionCall_sprintf";
  constexpr static const char *const UnsafeSizedByTag =
      "UnsafeLibcFunctionCall_sized_by";
  constexpr static const char *const UnsafeStringTag =
      "UnsafeLibcFunctionCall_string";
  constexpr static const char *const UnsafeVaListTag =
      "UnsafeLibcFunctionCall_va_list";

  enum UnsafeKind {
    OTHERS = 0,  // no specific information, the callee function is unsafe
    SPRINTF = 1, // never call `-sprintf`s, call `-snprintf`s instead.
    SIZED_BY =
        2, // the first two arguments of `snprintf` function have
           // "__sized_by" relation but they do not conform to safe patterns
    STRING = 3,  // an argument is a pointer-to-char-as-string but does not
                 // guarantee null-termination
    VA_LIST = 4, // one of the `-printf`s function that take va_list, which is
                 // considered unsafe as it is not compile-time check
  } WarnedFunKind = OTHERS;

public:
  UnsafeLibcFunctionCallGadget(const MatchResult &Result)
      : WarningGadget(Kind::UnsafeLibcFunctionCall),
        Call(Result.getNodeAs<CallExpr>(Tag)) {
    if (Result.getNodeAs<Decl>(UnsafeSprintfTag))
      WarnedFunKind = SPRINTF;
    else if (auto *E = Result.getNodeAs<Expr>(UnsafeStringTag)) {
      WarnedFunKind = STRING;
      UnsafeArg = E;
    } else if (Result.getNodeAs<CallExpr>(UnsafeSizedByTag)) {
      WarnedFunKind = SIZED_BY;
      UnsafeArg = Call->getArg(0);
    } else if (Result.getNodeAs<Decl>(UnsafeVaListTag))
      WarnedFunKind = VA_LIST;
  }

  static bool matches(const Stmt *S, ASTContext &Ctx,
                      const UnsafeBufferUsageHandler *Handler,
                      MatchResult &Result) {
    if (ignoreUnsafeLibcCall(Ctx, *S, Handler))
      return false;
    auto *CE = dyn_cast<CallExpr>(S);
    if (!CE || !CE->getDirectCallee())
      return false;
    const auto *FD = dyn_cast<FunctionDecl>(CE->getDirectCallee());
    if (!FD)
      return false;
    auto isSingleStringLiteralArg = false;
    if (CE->getNumArgs() == 1) {
      isSingleStringLiteralArg =
          isa<clang::StringLiteral>(CE->getArg(0)->IgnoreParenImpCasts());
    }
    if (!isSingleStringLiteralArg) {
      // (unless the call has a sole string literal argument):
      if (libc_func_matchers::isPredefinedUnsafeLibcFunc(*FD)) {
        Result.addNode(Tag, DynTypedNode::create(*CE));
        return true;
      }
      if (libc_func_matchers::isUnsafeVaListPrintfFunc(*FD)) {
        Result.addNode(Tag, DynTypedNode::create(*CE));
        Result.addNode(UnsafeVaListTag, DynTypedNode::create(*FD));
        return true;
      }
      if (libc_func_matchers::isUnsafeSprintfFunc(*FD)) {
        Result.addNode(Tag, DynTypedNode::create(*CE));
        Result.addNode(UnsafeSprintfTag, DynTypedNode::create(*FD));
        return true;
      }
    }
    if (libc_func_matchers::isNormalPrintfFunc(*FD)) {
      if (libc_func_matchers::hasUnsafeSnprintfBuffer(*CE, Ctx)) {
        Result.addNode(Tag, DynTypedNode::create(*CE));
        Result.addNode(UnsafeSizedByTag, DynTypedNode::create(*CE));
        return true;
      }
      if (libc_func_matchers::hasUnsafePrintfStringArg(*CE, Ctx, Result,
                                                       UnsafeStringTag)) {
        Result.addNode(Tag, DynTypedNode::create(*CE));
        return true;
      }
    }
    return false;
  }

  const Stmt *getBaseStmt() const { return Call; }

  SourceLocation getSourceLoc() const override { return Call->getBeginLoc(); }

  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeLibcCall(Call, WarnedFunKind, Ctx, UnsafeArg);
  }

  DeclUseList getClaimedVarUseSites() const override { return {}; }

  SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
};

// Represents expressions of the form `DRE[*]` in the Unspecified Lvalue
// Context (see `findStmtsInUnspecifiedLvalueContext`).
// Note here `[]` is the built-in subscript operator.
class ULCArraySubscriptGadget : public FixableGadget {
private:
  static constexpr const char *const ULCArraySubscriptTag =
      "ArraySubscriptUnderULC";
  const ArraySubscriptExpr *Node;

public:
  ULCArraySubscriptGadget(const MatchResult &Result)
      : FixableGadget(Kind::ULCArraySubscript),
        Node(Result.getNodeAs<ArraySubscriptExpr>(ULCArraySubscriptTag)) {
    assert(Node != nullptr && "Expecting a non-null matching result");
  }

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::ULCArraySubscript;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedLvalueContext(S, [&Results](const Expr *E) {
      const auto *ASE = dyn_cast<ArraySubscriptExpr>(E);
      if (!ASE)
        return;
      const auto *DRE =
          dyn_cast<DeclRefExpr>(ASE->getBase()->IgnoreParenImpCasts());
      if (!DRE || !(hasPointerType(*DRE) || hasArrayType(*DRE)) ||
          !isSupportedVariable(*DRE))
        return;
      MatchResult R;
      R.addNode(ULCArraySubscriptTag, DynTypedNode::create(*ASE));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override {
    if (const auto *DRE =
            dyn_cast<DeclRefExpr>(Node->getBase()->IgnoreImpCasts())) {
      return {DRE};
    }
    return {};
  }
};

// Fixable gadget to handle stand alone pointers of the form `UPC(DRE)` in the
// unspecified pointer context (findStmtsInUnspecifiedPointerContext). The
// gadget emits fixit of the form `UPC(DRE.data())`.
class UPCStandalonePointerGadget : public FixableGadget {
private:
  static constexpr const char *const DeclRefExprTag = "StandalonePointer";
  const DeclRefExpr *Node;

public:
  UPCStandalonePointerGadget(const MatchResult &Result)
      : FixableGadget(Kind::UPCStandalonePointer),
        Node(Result.getNodeAs<DeclRefExpr>(DeclRefExprTag)) {
    assert(Node != nullptr && "Expecting a non-null matching result");
  }

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::UPCStandalonePointer;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedPointerContext(S, [&Results](const Stmt *S) {
      auto *E = dyn_cast<Expr>(S);
      if (!E)
        return;
      const auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
      if (!DRE || (!hasPointerType(*DRE) && !hasArrayType(*DRE)) ||
          !isSupportedVariable(*DRE))
        return;
      MatchResult R;
      R.addNode(DeclRefExprTag, DynTypedNode::create(*DRE));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override { return {Node}; }
};

class PointerDereferenceGadget : public FixableGadget {
  static constexpr const char *const BaseDeclRefExprTag = "BaseDRE";
  static constexpr const char *const OperatorTag = "op";

  const DeclRefExpr *BaseDeclRefExpr = nullptr;
  const UnaryOperator *Op = nullptr;

public:
  PointerDereferenceGadget(const MatchResult &Result)
      : FixableGadget(Kind::PointerDereference),
        BaseDeclRefExpr(Result.getNodeAs<DeclRefExpr>(BaseDeclRefExprTag)),
        Op(Result.getNodeAs<UnaryOperator>(OperatorTag)) {}

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::PointerDereference;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedLvalueContext(S, [&Results](const Stmt *S) {
      const auto *UO = dyn_cast<UnaryOperator>(S);
      if (!UO || UO->getOpcode() != UO_Deref)
        return;
      const auto *CE = dyn_cast<Expr>(UO->getSubExpr());
      if (!CE)
        return;
      CE = CE->IgnoreParenImpCasts();
      const auto *DRE = dyn_cast<DeclRefExpr>(CE);
      if (!DRE || !isSupportedVariable(*DRE))
        return;
      MatchResult R;
      R.addNode(BaseDeclRefExprTag, DynTypedNode::create(*DRE));
      R.addNode(OperatorTag, DynTypedNode::create(*UO));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  DeclUseList getClaimedVarUseSites() const override {
    return {BaseDeclRefExpr};
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }
};

// Represents expressions of the form `&DRE[any]` in the Unspecified Pointer
// Context (see `findStmtsInUnspecifiedPointerContext`).
// Note here `[]` is the built-in subscript operator.
class UPCAddressofArraySubscriptGadget : public FixableGadget {
private:
  static constexpr const char *const UPCAddressofArraySubscriptTag =
      "AddressofArraySubscriptUnderUPC";
  const UnaryOperator *Node; // the `&DRE[any]` node

public:
  UPCAddressofArraySubscriptGadget(const MatchResult &Result)
      : FixableGadget(Kind::ULCArraySubscript),
        Node(Result.getNodeAs<UnaryOperator>(UPCAddressofArraySubscriptTag)) {
    assert(Node != nullptr && "Expecting a non-null matching result");
  }

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::UPCAddressofArraySubscript;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedPointerContext(S, [&Results](const Stmt *S) {
      auto *E = dyn_cast<Expr>(S);
      if (!E)
        return;
      const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreImpCasts());
      if (!UO || UO->getOpcode() != UO_AddrOf)
        return;
      const auto *ASE = dyn_cast<ArraySubscriptExpr>(UO->getSubExpr());
      if (!ASE)
        return;
      const auto *DRE =
          dyn_cast<DeclRefExpr>(ASE->getBase()->IgnoreParenImpCasts());
      if (!DRE || !isSupportedVariable(*DRE))
        return;
      MatchResult R;
      R.addNode(UPCAddressofArraySubscriptTag, DynTypedNode::create(*UO));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &) const override;
  SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override {
    const auto *ArraySubst = cast<ArraySubscriptExpr>(Node->getSubExpr());
    const auto *DRE =
        cast<DeclRefExpr>(ArraySubst->getBase()->IgnoreParenImpCasts());
    return {DRE};
  }
};
} // namespace

namespace {
// An auxiliary tracking facility for the fixit analysis. It helps connect
// declarations to its uses and make sure we've covered all uses with our
// analysis before we try to fix the declaration.
class DeclUseTracker {
  using UseSetTy = llvm::SmallSet<const DeclRefExpr *, 16>;
  using DefMapTy = llvm::DenseMap<const VarDecl *, const DeclStmt *>;

  // Allocate on the heap for easier move.
  std::unique_ptr<UseSetTy> Uses{std::make_unique<UseSetTy>()};
  DefMapTy Defs{};

public:
  DeclUseTracker() = default;
  DeclUseTracker(const DeclUseTracker &) = delete; // Let's avoid copies.
  DeclUseTracker &operator=(const DeclUseTracker &) = delete;
  DeclUseTracker(DeclUseTracker &&) = default;
  DeclUseTracker &operator=(DeclUseTracker &&) = default;

  // Start tracking a freshly discovered DRE.
  void discoverUse(const DeclRefExpr *DRE) { Uses->insert(DRE); }

  // Stop tracking the DRE as it's been fully figured out.
  void claimUse(const DeclRefExpr *DRE) {
    assert(Uses->count(DRE) &&
           "DRE not found or claimed by multiple matchers!");
    Uses->erase(DRE);
  }

  // A variable is unclaimed if at least one use is unclaimed.
  bool hasUnclaimedUses(const VarDecl *VD) const {
    // FIXME: Can this be less linear? Maybe maintain a map from VDs to DREs?
    return any_of(*Uses, [VD](const DeclRefExpr *DRE) {
      return DRE->getDecl()->getCanonicalDecl() == VD->getCanonicalDecl();
    });
  }

  UseSetTy getUnclaimedUses(const VarDecl *VD) const {
    UseSetTy ReturnSet;
    for (auto use : *Uses) {
      if (use->getDecl()->getCanonicalDecl() == VD->getCanonicalDecl()) {
        ReturnSet.insert(use);
      }
    }
    return ReturnSet;
  }

  void discoverDecl(const DeclStmt *DS) {
    for (const Decl *D : DS->decls()) {
      if (const auto *VD = dyn_cast<VarDecl>(D)) {
        // FIXME: Assertion temporarily disabled due to a bug in
        // ASTMatcher internal behavior in presence of GNU
        // statement-expressions. We need to properly investigate this
        // because it can screw up our algorithm in other ways.
        // assert(Defs.count(VD) == 0 && "Definition already discovered!");
        Defs[VD] = DS;
      }
    }
  }

  const DeclStmt *lookupDecl(const VarDecl *VD) const {
    return Defs.lookup(VD);
  }
};
} // namespace

// Representing a pointer type expression of the form `++Ptr` in an Unspecified
// Pointer Context (UPC):
class UPCPreIncrementGadget : public FixableGadget {
private:
  static constexpr const char *const UPCPreIncrementTag =
      "PointerPreIncrementUnderUPC";
  const UnaryOperator *Node; // the `++Ptr` node

public:
  UPCPreIncrementGadget(const MatchResult &Result)
      : FixableGadget(Kind::UPCPreIncrement),
        Node(Result.getNodeAs<UnaryOperator>(UPCPreIncrementTag)) {
    assert(Node != nullptr && "Expecting a non-null matching result");
  }

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::UPCPreIncrement;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    // Note here we match `++Ptr` for any expression `Ptr` of pointer type.
    // Although currently we can only provide fix-its when `Ptr` is a DRE, we
    // can have the matcher be general, so long as `getClaimedVarUseSites` does
    // things right.
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedPointerContext(S, [&Results](const Stmt *S) {
      auto *E = dyn_cast<Expr>(S);
      if (!E)
        return;
      const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreImpCasts());
      if (!UO || UO->getOpcode() != UO_PreInc)
        return;
      const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr());
      if (!DRE || !isSupportedVariable(*DRE))
        return;
      MatchResult R;
      R.addNode(UPCPreIncrementTag, DynTypedNode::create(*UO));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override {
    return {dyn_cast<DeclRefExpr>(Node->getSubExpr())};
  }
};

// Representing a pointer type expression of the form `Ptr += n` in an
// Unspecified Untyped Context (UUC):
class UUCAddAssignGadget : public FixableGadget {
private:
  static constexpr const char *const UUCAddAssignTag =
      "PointerAddAssignUnderUUC";
  static constexpr const char *const OffsetTag = "Offset";

  const BinaryOperator *Node; // the `Ptr += n` node
  const Expr *Offset = nullptr;

public:
  UUCAddAssignGadget(const MatchResult &Result)
      : FixableGadget(Kind::UUCAddAssign),
        Node(Result.getNodeAs<BinaryOperator>(UUCAddAssignTag)),
        Offset(Result.getNodeAs<Expr>(OffsetTag)) {
    assert(Node != nullptr && "Expecting a non-null matching result");
  }

  static bool classof(const Gadget *G) {
    return G->getKind() == Kind::UUCAddAssign;
  }

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    size_t SizeBefore = Results.size();
    findStmtsInUnspecifiedUntypedContext(S, [&Results](const Stmt *S) {
      const auto *E = dyn_cast<Expr>(S);
      if (!E)
        return;
      const auto *BO = dyn_cast<BinaryOperator>(E->IgnoreImpCasts());
      if (!BO || BO->getOpcode() != BO_AddAssign)
        return;
      const auto *DRE = dyn_cast<DeclRefExpr>(BO->getLHS());
      if (!DRE || !hasPointerType(*DRE) || !isSupportedVariable(*DRE))
        return;
      MatchResult R;
      R.addNode(UUCAddAssignTag, DynTypedNode::create(*BO));
      R.addNode(OffsetTag, DynTypedNode::create(*BO->getRHS()));
      Results.emplace_back(std::move(R));
    });
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &S) const override;
  SourceLocation getSourceLoc() const override { return Node->getBeginLoc(); }

  virtual DeclUseList getClaimedVarUseSites() const override {
    return {dyn_cast<DeclRefExpr>(Node->getLHS())};
  }
};

// Representing a fixable expression of the form `*(ptr + 123)` or `*(123 +
// ptr)`:
class DerefSimplePtrArithFixableGadget : public FixableGadget {
  static constexpr const char *const BaseDeclRefExprTag = "BaseDRE";
  static constexpr const char *const DerefOpTag = "DerefOp";
  static constexpr const char *const AddOpTag = "AddOp";
  static constexpr const char *const OffsetTag = "Offset";

  const DeclRefExpr *BaseDeclRefExpr = nullptr;
  const UnaryOperator *DerefOp = nullptr;
  const BinaryOperator *AddOp = nullptr;
  const IntegerLiteral *Offset = nullptr;

public:
  DerefSimplePtrArithFixableGadget(const MatchResult &Result)
      : FixableGadget(Kind::DerefSimplePtrArithFixable),
        BaseDeclRefExpr(Result.getNodeAs<DeclRefExpr>(BaseDeclRefExprTag)),
        DerefOp(Result.getNodeAs<UnaryOperator>(DerefOpTag)),
        AddOp(Result.getNodeAs<BinaryOperator>(AddOpTag)),
        Offset(Result.getNodeAs<IntegerLiteral>(OffsetTag)) {}

  static bool matches(const Stmt *S,
                      llvm::SmallVectorImpl<MatchResult> &Results) {
    auto IsPtr = [](const Expr *E, MatchResult &R) {
      if (!E || !hasPointerType(*E))
        return false;
      const auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreImpCasts());
      if (!DRE || !isSupportedVariable(*DRE))
        return false;
      R.addNode(BaseDeclRefExprTag, DynTypedNode::create(*DRE));
      return true;
    };
    const auto IsPlusOverPtrAndInteger = [&IsPtr](const Expr *E,
                                                  MatchResult &R) {
      const auto *BO = dyn_cast<BinaryOperator>(E);
      if (!BO || BO->getOpcode() != BO_Add)
        return false;

      const auto *LHS = BO->getLHS();
      const auto *RHS = BO->getRHS();
      if (isa<IntegerLiteral>(RHS) && IsPtr(LHS, R)) {
        R.addNode(OffsetTag, DynTypedNode::create(*RHS));
        R.addNode(AddOpTag, DynTypedNode::create(*BO));
        return true;
      }
      if (isa<IntegerLiteral>(LHS) && IsPtr(RHS, R)) {
        R.addNode(OffsetTag, DynTypedNode::create(*LHS));
        R.addNode(AddOpTag, DynTypedNode::create(*BO));
        return true;
      }
      return false;
    };
    size_t SizeBefore = Results.size();
    const auto InnerMatcher = [&IsPlusOverPtrAndInteger,
                               &Results](const Expr *E) {
      const auto *UO = dyn_cast<UnaryOperator>(E);
      if (!UO || UO->getOpcode() != UO_Deref)
        return;

      const auto *Operand = UO->getSubExpr()->IgnoreParens();
      MatchResult R;
      if (IsPlusOverPtrAndInteger(Operand, R)) {
        R.addNode(DerefOpTag, DynTypedNode::create(*UO));
        Results.emplace_back(std::move(R));
      }
    };
    findStmtsInUnspecifiedLvalueContext(S, InnerMatcher);
    return SizeBefore != Results.size();
  }

  virtual std::optional<FixItList>
  getFixits(const FixitStrategy &s) const final;
  SourceLocation getSourceLoc() const override {
    return DerefOp->getBeginLoc();
  }

  virtual DeclUseList getClaimedVarUseSites() const final {
    return {BaseDeclRefExpr};
  }
};

class WarningGadgetMatcher : public FastMatcher {

public:
  WarningGadgetMatcher(WarningGadgetList &WarningGadgets)
      : WarningGadgets(WarningGadgets) {}

  bool matches(const DynTypedNode &DynNode, ASTContext &Ctx,
               const UnsafeBufferUsageHandler &Handler) override {
    const Stmt *S = DynNode.get<Stmt>();
    if (!S)
      return false;

    MatchResult Result;
#define WARNING_GADGET(name)                                                   \
  if (name##Gadget::matches(S, Ctx, Result) &&                                 \
      notInSafeBufferOptOut(*S, &Handler)) {                                   \
    WarningGadgets.push_back(std::make_unique<name##Gadget>(Result));          \
    return true;                                                               \
  }
#define WARNING_OPTIONAL_GADGET(name)                                          \
  if (name##Gadget::matches(S, Ctx, &Handler, Result) &&                       \
      notInSafeBufferOptOut(*S, &Handler)) {                                   \
    WarningGadgets.push_back(std::make_unique<name##Gadget>(Result));          \
    return true;                                                               \
  }
#include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
    return false;
  }

private:
  WarningGadgetList &WarningGadgets;
};

class FixableGadgetMatcher : public FastMatcher {

public:
  FixableGadgetMatcher(FixableGadgetList &FixableGadgets,
                       DeclUseTracker &Tracker)
      : FixableGadgets(FixableGadgets), Tracker(Tracker) {}

  bool matches(const DynTypedNode &DynNode, ASTContext &Ctx,
               const UnsafeBufferUsageHandler &Handler) override {
    bool matchFound = false;
    const Stmt *S = DynNode.get<Stmt>();
    if (!S) {
      return matchFound;
    }

    llvm::SmallVector<MatchResult> Results;
#define FIXABLE_GADGET(name)                                                   \
  if (name##Gadget::matches(S, Results)) {                                     \
    for (const auto &R : Results) {                                            \
      FixableGadgets.push_back(std::make_unique<name##Gadget>(R));             \
      matchFound = true;                                                       \
    }                                                                          \
    Results = {};                                                              \
  }
#include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
    // In parallel, match all DeclRefExprs so that to find out
    // whether there are any uncovered by gadgets.
    if (auto *DRE = findDeclRefExpr(S); DRE) {
      Tracker.discoverUse(DRE);
      matchFound = true;
    }
    // Also match DeclStmts because we'll need them when fixing
    // their underlying VarDecls that otherwise don't have
    // any backreferences to DeclStmts.
    if (auto *DS = findDeclStmt(S); DS) {
      Tracker.discoverDecl(DS);
      matchFound = true;
    }
    return matchFound;
  }

private:
  const DeclRefExpr *findDeclRefExpr(const Stmt *S) {
    const auto *DRE = dyn_cast<DeclRefExpr>(S);
    if (!DRE || (!hasPointerType(*DRE) && !hasArrayType(*DRE)))
      return nullptr;
    const Decl *D = DRE->getDecl();
    if (!D || (!isa<VarDecl>(D) && !isa<BindingDecl>(D)))
      return nullptr;
    return DRE;
  }
  const DeclStmt *findDeclStmt(const Stmt *S) {
    const auto *DS = dyn_cast<DeclStmt>(S);
    if (!DS)
      return nullptr;
    return DS;
  }
  FixableGadgetList &FixableGadgets;
  DeclUseTracker &Tracker;
};

// Scan the function and return a list of gadgets found with provided kits.
static void findGadgets(const Stmt *S, ASTContext &Ctx,
                        const UnsafeBufferUsageHandler &Handler,
                        bool EmitSuggestions, FixableGadgetList &FixableGadgets,
                        WarningGadgetList &WarningGadgets,
                        DeclUseTracker &Tracker) {
  WarningGadgetMatcher WMatcher{WarningGadgets};
  forEachDescendantEvaluatedStmt(S, Ctx, Handler, WMatcher);
  if (EmitSuggestions) {
    FixableGadgetMatcher FMatcher{FixableGadgets, Tracker};
    forEachDescendantStmt(S, Ctx, Handler, FMatcher);
  }
}

// Compares AST nodes by source locations.
template <typename NodeTy> struct CompareNode {
  bool operator()(const NodeTy *N1, const NodeTy *N2) const {
    return N1->getBeginLoc().getRawEncoding() <
           N2->getBeginLoc().getRawEncoding();
  }
};

std::set<const Expr *> clang::findUnsafePointers(const FunctionDecl *FD) {
  class MockReporter : public UnsafeBufferUsageHandler {
  public:
    MockReporter() {}
    void handleUnsafeOperation(const Stmt *, bool, ASTContext &) override {}
    void handleUnsafeLibcCall(const CallExpr *, unsigned, ASTContext &,
                              const Expr *UnsafeArg = nullptr) override {}
    void handleUnsafeOperationInContainer(const Stmt *, bool,
                                          ASTContext &) override {}
    void handleUnsafeVariableGroup(const VarDecl *,
                                   const VariableGroupsManager &, FixItList &&,
                                   const Decl *,
                                   const FixitStrategy &) override {}
    bool isSafeBufferOptOut(const SourceLocation &) const override {
      return false;
    }
    bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
      return false;
    }
    bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override {
      return false;
    }
    std::string getUnsafeBufferUsageAttributeTextAt(
        SourceLocation, StringRef WSSuffix = "") const override {
      return "";
    }
  };

  FixableGadgetList FixableGadgets;
  WarningGadgetList WarningGadgets;
  DeclUseTracker Tracker;
  MockReporter IgnoreHandler;

  findGadgets(FD->getBody(), FD->getASTContext(), IgnoreHandler, false,
              FixableGadgets, WarningGadgets, Tracker);

  std::set<const Expr *> Result;
  for (auto &G : WarningGadgets) {
    for (const Expr *E : G->getUnsafePtrs()) {
      Result.insert(E);
    }
  }

  return Result;
}

struct WarningGadgetSets {
  std::map<const VarDecl *, std::set<const WarningGadget *>,
           // To keep keys sorted by their locations in the map so that the
           // order is deterministic:
           CompareNode<VarDecl>>
      byVar;
  // These Gadgets are not related to pointer variables (e. g. temporaries).
  llvm::SmallVector<const WarningGadget *, 16> noVar;
};

static WarningGadgetSets
groupWarningGadgetsByVar(const WarningGadgetList &AllUnsafeOperations) {
  WarningGadgetSets result;
  // If some gadgets cover more than one
  // variable, they'll appear more than once in the map.
  for (auto &G : AllUnsafeOperations) {
    DeclUseList ClaimedVarUseSites = G->getClaimedVarUseSites();

    bool AssociatedWithVarDecl = false;
    for (const DeclRefExpr *DRE : ClaimedVarUseSites) {
      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
        result.byVar[VD].insert(G.get());
        AssociatedWithVarDecl = true;
      }
    }

    if (!AssociatedWithVarDecl) {
      result.noVar.push_back(G.get());
      continue;
    }
  }
  return result;
}

struct FixableGadgetSets {
  std::map<const VarDecl *, std::set<const FixableGadget *>,
           // To keep keys sorted by their locations in the map so that the
           // order is deterministic:
           CompareNode<VarDecl>>
      byVar;
};

static FixableGadgetSets
groupFixablesByVar(FixableGadgetList &&AllFixableOperations) {
  FixableGadgetSets FixablesForUnsafeVars;
  for (auto &F : AllFixableOperations) {
    DeclUseList DREs = F->getClaimedVarUseSites();

    for (const DeclRefExpr *DRE : DREs) {
      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
        FixablesForUnsafeVars.byVar[VD].insert(F.get());
      }
    }
  }
  return FixablesForUnsafeVars;
}

bool clang::internal::anyConflict(const SmallVectorImpl<FixItHint> &FixIts,
                                  const SourceManager &SM) {
  // A simple interval overlap detection algorithm.  Sorts all ranges by their
  // begin location then finds the first overlap in one pass.
  std::vector<const FixItHint *> All; // a copy of `FixIts`

  for (const FixItHint &H : FixIts)
    All.push_back(&H);
  std::sort(All.begin(), All.end(),
            [&SM](const FixItHint *H1, const FixItHint *H2) {
              return SM.isBeforeInTranslationUnit(H1->RemoveRange.getBegin(),
                                                  H2->RemoveRange.getBegin());
            });

  const FixItHint *CurrHint = nullptr;

  for (const FixItHint *Hint : All) {
    if (!CurrHint ||
        SM.isBeforeInTranslationUnit(CurrHint->RemoveRange.getEnd(),
                                     Hint->RemoveRange.getBegin())) {
      // Either to initialize `CurrHint` or `CurrHint` does not
      // overlap with `Hint`:
      CurrHint = Hint;
    } else
      // In case `Hint` overlaps the `CurrHint`, we found at least one
      // conflict:
      return true;
  }
  return false;
}

std::optional<FixItList>
PtrToPtrAssignmentGadget::getFixits(const FixitStrategy &S) const {
  const auto *LeftVD = cast<VarDecl>(PtrLHS->getDecl());
  const auto *RightVD = cast<VarDecl>(PtrRHS->getDecl());
  switch (S.lookup(LeftVD)) {
  case FixitStrategy::Kind::Span:
    if (S.lookup(RightVD) == FixitStrategy::Kind::Span)
      return FixItList{};
    return std::nullopt;
  case FixitStrategy::Kind::Wontfix:
    return std::nullopt;
  case FixitStrategy::Kind::Iterator:
  case FixitStrategy::Kind::Array:
    return std::nullopt;
  case FixitStrategy::Kind::Vector:
    llvm_unreachable("unsupported strategies for FixableGadgets");
  }
  return std::nullopt;
}

/// \returns fixit that adds .data() call after \DRE.
static inline std::optional<FixItList> createDataFixit(const ASTContext &Ctx,
                                                       const DeclRefExpr *DRE);

std::optional<FixItList>
CArrayToPtrAssignmentGadget::getFixits(const FixitStrategy &S) const {
  const auto *LeftVD = cast<VarDecl>(PtrLHS->getDecl());
  const auto *RightVD = cast<VarDecl>(PtrRHS->getDecl());
  // TLDR: Implementing fixits for non-Wontfix strategy on both LHS and RHS is
  // non-trivial.
  //
  // CArrayToPtrAssignmentGadget doesn't have strategy implications because
  // constant size array propagates its bounds. Because of that LHS and RHS are
  // addressed by two different fixits.
  //
  // At the same time FixitStrategy S doesn't reflect what group a fixit belongs
  // to and can't be generally relied on in multi-variable Fixables!
  //
  // E. g. If an instance of this gadget is fixing variable on LHS then the
  // variable on RHS is fixed by a different fixit and its strategy for LHS
  // fixit is as if Wontfix.
  //
  // The only exception is Wontfix strategy for a given variable as that is
  // valid for any fixit produced for the given input source code.
  if (S.lookup(LeftVD) == FixitStrategy::Kind::Span) {
    if (S.lookup(RightVD) == FixitStrategy::Kind::Wontfix) {
      return FixItList{};
    }
  } else if (S.lookup(LeftVD) == FixitStrategy::Kind::Wontfix) {
    if (S.lookup(RightVD) == FixitStrategy::Kind::Array) {
      return createDataFixit(RightVD->getASTContext(), PtrRHS);
    }
  }
  return std::nullopt;
}

std::optional<FixItList>
PointerInitGadget::getFixits(const FixitStrategy &S) const {
  const auto *LeftVD = PtrInitLHS;
  const auto *RightVD = cast<VarDecl>(PtrInitRHS->getDecl());
  switch (S.lookup(LeftVD)) {
  case FixitStrategy::Kind::Span:
    if (S.lookup(RightVD) == FixitStrategy::Kind::Span)
      return FixItList{};
    return std::nullopt;
  case FixitStrategy::Kind::Wontfix:
    return std::nullopt;
  case FixitStrategy::Kind::Iterator:
  case FixitStrategy::Kind::Array:
    return std::nullopt;
  case FixitStrategy::Kind::Vector:
    llvm_unreachable("unsupported strategies for FixableGadgets");
  }
  return std::nullopt;
}

static bool isNonNegativeIntegerExpr(const Expr *Expr, const VarDecl *VD,
                                     const ASTContext &Ctx) {
  if (auto ConstVal = Expr->getIntegerConstantExpr(Ctx)) {
    if (ConstVal->isNegative())
      return false;
  } else if (!Expr->getType()->isUnsignedIntegerType())
    return false;
  return true;
}

std::optional<FixItList>
ULCArraySubscriptGadget::getFixits(const FixitStrategy &S) const {
  if (const auto *DRE =
          dyn_cast<DeclRefExpr>(Node->getBase()->IgnoreImpCasts()))
    if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
      switch (S.lookup(VD)) {
      case FixitStrategy::Kind::Span: {

        // If the index has a negative constant value, we give up as no valid
        // fix-it can be generated:
        const ASTContext &Ctx = // FIXME: we need ASTContext to be passed in!
            VD->getASTContext();
        if (!isNonNegativeIntegerExpr(Node->getIdx(), VD, Ctx))
          return std::nullopt;
        // no-op is a good fix-it, otherwise
        return FixItList{};
      }
      case FixitStrategy::Kind::Array:
        return FixItList{};
      case FixitStrategy::Kind::Wontfix:
      case FixitStrategy::Kind::Iterator:
      case FixitStrategy::Kind::Vector:
        llvm_unreachable("unsupported strategies for FixableGadgets");
      }
    }
  return std::nullopt;
}

static std::optional<FixItList> // forward declaration
fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node);

std::optional<FixItList>
UPCAddressofArraySubscriptGadget::getFixits(const FixitStrategy &S) const {
  auto DREs = getClaimedVarUseSites();
  const auto *VD = cast<VarDecl>(DREs.front()->getDecl());

  switch (S.lookup(VD)) {
  case FixitStrategy::Kind::Span:
    return fixUPCAddressofArraySubscriptWithSpan(Node);
  case FixitStrategy::Kind::Wontfix:
  case FixitStrategy::Kind::Iterator:
  case FixitStrategy::Kind::Array:
    return std::nullopt;
  case FixitStrategy::Kind::Vector:
    llvm_unreachable("unsupported strategies for FixableGadgets");
  }
  return std::nullopt; // something went wrong, no fix-it
}

// FIXME: this function should be customizable through format
static StringRef getEndOfLine() {
  static const char *const EOL = "\n";
  return EOL;
}

// Returns the text indicating that the user needs to provide input there:
static std::string
getUserFillPlaceHolder(StringRef HintTextToUser = "placeholder") {
  std::string s = std::string("<# ");
  s += HintTextToUser;
  s += " #>";
  return s;
}

// Return the source location of the last character of the AST `Node`.
template <typename NodeTy>
static std::optional<SourceLocation>
getEndCharLoc(const NodeTy *Node, const SourceManager &SM,
              const LangOptions &LangOpts) {
  if (unsigned TkLen =
          Lexer::MeasureTokenLength(Node->getEndLoc(), SM, LangOpts)) {
    SourceLocation Loc = Node->getEndLoc().getLocWithOffset(TkLen - 1);

    if (Loc.isValid())
      return Loc;
  }
  return std::nullopt;
}

// We cannot fix a variable declaration if it has some other specifiers than the
// type specifier.  Because the source ranges of those specifiers could overlap
// with the source range that is being replaced using fix-its.  Especially when
// we often cannot obtain accurate source ranges of cv-qualified type
// specifiers.
// FIXME: also deal with type attributes
static bool hasUnsupportedSpecifiers(const VarDecl *VD,
                                     const SourceManager &SM) {
  // AttrRangeOverlapping: true if at least one attribute of `VD` overlaps the
  // source range of `VD`:
  bool AttrRangeOverlapping = llvm::any_of(VD->attrs(), [&](Attr *At) -> bool {
    return !(SM.isBeforeInTranslationUnit(At->getRange().getEnd(),
                                          VD->getBeginLoc())) &&
           !(SM.isBeforeInTranslationUnit(VD->getEndLoc(),
                                          At->getRange().getBegin()));
  });
  return VD->isInlineSpecified() || VD->isConstexpr() ||
         VD->hasConstantInitialization() || !VD->hasLocalStorage() ||
         AttrRangeOverlapping;
}

// Returns the `SourceRange` of `D`.  The reason why this function exists is
// that `D->getSourceRange()` may return a range where the end location is the
// starting location of the last token.  The end location of the source range
// returned by this function is the last location of the last token.
static SourceRange getSourceRangeToTokenEnd(const Decl *D,
                                            const SourceManager &SM,
                                            const LangOptions &LangOpts) {
  SourceLocation Begin = D->getBeginLoc();
  SourceLocation
      End = // `D->getEndLoc` should always return the starting location of the
      // last token, so we should get the end of the token
      Lexer::getLocForEndOfToken(D->getEndLoc(), 0, SM, LangOpts);

  return SourceRange(Begin, End);
}

// Returns the text of the name (with qualifiers) of a `FunctionDecl`.
static std::optional<StringRef> getFunNameText(const FunctionDecl *FD,
                                               const SourceManager &SM,
                                               const LangOptions &LangOpts) {
  SourceLocation BeginLoc = FD->getQualifier()
                                ? FD->getQualifierLoc().getBeginLoc()
                                : FD->getNameInfo().getBeginLoc();
  // Note that `FD->getNameInfo().getEndLoc()` returns the begin location of the
  // last token:
  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
      FD->getNameInfo().getEndLoc(), 0, SM, LangOpts);
  SourceRange NameRange{BeginLoc, EndLoc};

  return getRangeText(NameRange, SM, LangOpts);
}

// Returns the text representing a `std::span` type where the element type is
// represented by `EltTyText`.
//
// Note the optional parameter `Qualifiers`: one needs to pass qualifiers
// explicitly if the element type needs to be qualified.
static std::string
getSpanTypeText(StringRef EltTyText,
                std::optional<Qualifiers> Quals = std::nullopt) {
  const char *const SpanOpen = "std::span<";

  if (Quals)
    return SpanOpen + EltTyText.str() + ' ' + Quals->getAsString() + '>';
  return SpanOpen + EltTyText.str() + '>';
}

std::optional<FixItList>
DerefSimplePtrArithFixableGadget::getFixits(const FixitStrategy &s) const {
  const VarDecl *VD = dyn_cast<VarDecl>(BaseDeclRefExpr->getDecl());

  if (VD && s.lookup(VD) == FixitStrategy::Kind::Span) {
    ASTContext &Ctx = VD->getASTContext();
    // std::span can't represent elements before its begin()
    if (auto ConstVal = Offset->getIntegerConstantExpr(Ctx))
      if (ConstVal->isNegative())
        return std::nullopt;

    // note that the expr may (oddly) has multiple layers of parens
    // example:
    //   *((..(pointer + 123)..))
    // goal:
    //   pointer[123]
    // Fix-It:
    //   remove '*('
    //   replace ' + ' with '['
    //   replace ')' with ']'

    // example:
    //   *((..(123 + pointer)..))
    // goal:
    //   123[pointer]
    // Fix-It:
    //   remove '*('
    //   replace ' + ' with '['
    //   replace ')' with ']'

    const Expr *LHS = AddOp->getLHS(), *RHS = AddOp->getRHS();
    const SourceManager &SM = Ctx.getSourceManager();
    const LangOptions &LangOpts = Ctx.getLangOpts();
    CharSourceRange StarWithTrailWhitespace =
        clang::CharSourceRange::getCharRange(DerefOp->getOperatorLoc(),
                                             LHS->getBeginLoc());

    std::optional<SourceLocation> LHSLocation = getPastLoc(LHS, SM, LangOpts);
    if (!LHSLocation)
      return std::nullopt;

    CharSourceRange PlusWithSurroundingWhitespace =
        clang::CharSourceRange::getCharRange(*LHSLocation, RHS->getBeginLoc());

    std::optional<SourceLocation> AddOpLocation =
        getPastLoc(AddOp, SM, LangOpts);
    std::optional<SourceLocation> DerefOpLocation =
        getPastLoc(DerefOp, SM, LangOpts);

    if (!AddOpLocation || !DerefOpLocation)
      return std::nullopt;

    CharSourceRange ClosingParenWithPrecWhitespace =
        clang::CharSourceRange::getCharRange(*AddOpLocation, *DerefOpLocation);

    return FixItList{
        {FixItHint::CreateRemoval(StarWithTrailWhitespace),
         FixItHint::CreateReplacement(PlusWithSurroundingWhitespace, "["),
         FixItHint::CreateReplacement(ClosingParenWithPrecWhitespace, "]")}};
  }
  return std::nullopt; // something wrong or unsupported, give up
}

std::optional<FixItList>
PointerDereferenceGadget::getFixits(const FixitStrategy &S) const {
  const VarDecl *VD = cast<VarDecl>(BaseDeclRefExpr->getDecl());
  switch (S.lookup(VD)) {
  case FixitStrategy::Kind::Span: {
    ASTContext &Ctx = VD->getASTContext();
    SourceManager &SM = Ctx.getSourceManager();
    // Required changes: *(ptr); => (ptr[0]); and *ptr; => ptr[0]
    // Deletes the *operand
    CharSourceRange derefRange = clang::CharSourceRange::getCharRange(
        Op->getBeginLoc(), Op->getBeginLoc().getLocWithOffset(1));
    // Inserts the [0]
    if (auto LocPastOperand =
            getPastLoc(BaseDeclRefExpr, SM, Ctx.getLangOpts())) {
      return FixItList{{FixItHint::CreateRemoval(derefRange),
                        FixItHint::CreateInsertion(*LocPastOperand, "[0]")}};
    }
    break;
  }
  case FixitStrategy::Kind::Iterator:
  case FixitStrategy::Kind::Array:
    return std::nullopt;
  case FixitStrategy::Kind::Vector:
    llvm_unreachable("FixitStrategy not implemented yet!");
  case FixitStrategy::Kind::Wontfix:
    llvm_unreachable("Invalid strategy!");
  }

  return std::nullopt;
}

static inline std::optional<FixItList> createDataFixit(const ASTContext &Ctx,
                                                       const DeclRefExpr *DRE) {
  const SourceManager &SM = Ctx.getSourceManager();
  // Inserts the .data() after the DRE
  std::optional<SourceLocation> EndOfOperand =
      getPastLoc(DRE, SM, Ctx.getLangOpts());

  if (EndOfOperand)
    return FixItList{{FixItHint::CreateInsertion(*EndOfOperand, ".data()")}};

  return std::nullopt;
}

// Generates fix-its replacing an expression of the form UPC(DRE) with
// `DRE.data()`
std::optional<FixItList>
UPCStandalonePointerGadget::getFixits(const FixitStrategy &S) const {
  const auto VD = cast<VarDecl>(Node->getDecl());
  switch (S.lookup(VD)) {
  case FixitStrategy::Kind::Array:
  case FixitStrategy::Kind::Span: {
    return createDataFixit(VD->getASTContext(), Node);
    // FIXME: Points inside a macro expansion.
    break;
  }
  case FixitStrategy::Kind::Wontfix:
  case FixitStrategy::Kind::Iterator:
    return std::nullopt;
  case FixitStrategy::Kind::Vector:
    llvm_unreachable("unsupported strategies for FixableGadgets");
  }

  return std::nullopt;
}

// Generates fix-its replacing an expression of the form `&DRE[e]` with
// `&DRE.data()[e]`:
static std::optional<FixItList>
fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) {
  const auto *ArraySub = cast<ArraySubscriptExpr>(Node->getSubExpr());
  const auto *DRE = cast<DeclRefExpr>(ArraySub->getBase()->IgnoreImpCasts());
  // FIXME: this `getASTContext` call is costly, we should pass the
  // ASTContext in:
  const ASTContext &Ctx = DRE->getDecl()->getASTContext();
  const Expr *Idx = ArraySub->getIdx();
  const SourceManager &SM = Ctx.getSourceManager();
  const LangOptions &LangOpts = Ctx.getLangOpts();
  std::stringstream SS;
  bool IdxIsLitZero = false;

  if (auto ICE = Idx->getIntegerConstantExpr(Ctx))
    if ((*ICE).isZero())
      IdxIsLitZero = true;
  std::optional<StringRef> DreString = getExprText(DRE, SM, LangOpts);
  if (!DreString)
    return std::nullopt;

  if (IdxIsLitZero) {
    // If the index is literal zero, we produce the most concise fix-it:
    SS << (*DreString).str() << ".data()";
  } else {
    std::optional<StringRef> IndexString = getExprText(Idx, SM, LangOpts);
    if (!IndexString)
      return std::nullopt;

    SS << "&" << (*DreString).str() << ".data()"
       << "[" << (*IndexString).str() << "]";
  }
  return FixItList{
      FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())};
}

std::optional<FixItList>
UUCAddAssignGadget::getFixits(const FixitStrategy &S) const {
  DeclUseList DREs = getClaimedVarUseSites();

  if (DREs.size() != 1)
    return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we
                         // give up
  if (const VarDecl *VD = dyn_cast<VarDecl>(DREs.front()->getDecl())) {
    if (S.lookup(VD) == FixitStrategy::Kind::Span) {
      FixItList Fixes;

      const Stmt *AddAssignNode = Node;
      StringRef varName = VD->getName();
      const ASTContext &Ctx = VD->getASTContext();

      if (!isNonNegativeIntegerExpr(Offset, VD, Ctx))
        return std::nullopt;

      // To transform UUC(p += n) to UUC(p = p.subspan(..)):
      bool NotParenExpr =
          (Offset->IgnoreParens()->getBeginLoc() == Offset->getBeginLoc());
      std::string SS = varName.str() + " = " + varName.str() + ".subspan";
      if (NotParenExpr)
        SS += "(";

      std::optional<SourceLocation> AddAssignLocation = getEndCharLoc(
          AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts());
      if (!AddAssignLocation)
        return std::nullopt;

      Fixes.push_back(FixItHint::CreateReplacement(
          SourceRange(AddAssignNode->getBeginLoc(), Node->getOperatorLoc()),
          SS));
      if (NotParenExpr)
        Fixes.push_back(FixItHint::CreateInsertion(
            Offset->getEndLoc().getLocWithOffset(1), ")"));
      return Fixes;
    }
  }
  return std::nullopt; // Not in the cases that we can handle for now, give up.
}

std::optional<FixItList>
UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const {
  DeclUseList DREs = getClaimedVarUseSites();

  if (DREs.size() != 1)
    return std::nullopt; // In cases of `++Ptr` where `Ptr` is not a DRE, we
                         // give up
  if (const VarDecl *VD = dyn_cast<VarDecl>(DREs.front()->getDecl())) {
    if (S.lookup(VD) == FixitStrategy::Kind::Span) {
      FixItList Fixes;
      std::stringstream SS;
      StringRef varName = VD->getName();
      const ASTContext &Ctx = VD->getASTContext();

      // To transform UPC(++p) to UPC((p = p.subspan(1)).data()):
      SS << "(" << varName.data() << " = " << varName.data()
         << ".subspan(1)).data()";
      std::optional<SourceLocation> PreIncLocation =
          getEndCharLoc(Node, Ctx.getSourceManager(), Ctx.getLangOpts());
      if (!PreIncLocation)
        return std::nullopt;

      Fixes.push_back(FixItHint::CreateReplacement(
          SourceRange(Node->getBeginLoc(), *PreIncLocation), SS.str()));
      return Fixes;
    }
  }
  return std::nullopt; // Not in the cases that we can handle for now, give up.
}

// For a non-null initializer `Init` of `T *` type, this function returns
// `FixItHint`s producing a list initializer `{Init,  S}` as a part of a fix-it
// to output stream.
// In many cases, this function cannot figure out the actual extent `S`.  It
// then will use a place holder to replace `S` to ask users to fill `S` in.  The
// initializer shall be used to initialize a variable of type `std::span<T>`.
// In some cases (e. g. constant size array) the initializer should remain
// unchanged and the function returns empty list. In case the function can't
// provide the right fixit it will return nullopt.
//
// FIXME: Support multi-level pointers
//
// Parameters:
//   `Init` a pointer to the initializer expression
//   `Ctx` a reference to the ASTContext
static std::optional<FixItList>
FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
                          const StringRef UserFillPlaceHolder) {
  const SourceManager &SM = Ctx.getSourceManager();
  const LangOptions &LangOpts = Ctx.getLangOpts();

  // If `Init` has a constant value that is (or equivalent to) a
  // NULL pointer, we use the default constructor to initialize the span
  // object, i.e., a `std:span` variable declaration with no initializer.
  // So the fix-it is just to remove the initializer.
  if (Init->isNullPointerConstant(
          Ctx,
          // FIXME: Why does this function not ask for `const ASTContext
          // &`? It should. Maybe worth an NFC patch later.
          Expr::NullPointerConstantValueDependence::
              NPC_ValueDependentIsNotNull)) {
    std::optional<SourceLocation> InitLocation =
        getEndCharLoc(Init, SM, LangOpts);
    if (!InitLocation)
      return std::nullopt;

    SourceRange SR(Init->getBeginLoc(), *InitLocation);

    return FixItList{FixItHint::CreateRemoval(SR)};
  }

  FixItList FixIts{};
  std::string ExtentText = UserFillPlaceHolder.data();
  StringRef One = "1";

  // Insert `{` before `Init`:
  FixIts.push_back(FixItHint::CreateInsertion(Init->getBeginLoc(), "{"));
  // Try to get the data extent. Break into different cases:
  if (auto CxxNew = dyn_cast<CXXNewExpr>(Init->IgnoreImpCasts())) {
    // In cases `Init` is `new T[n]` and there is no explicit cast over
    // `Init`, we know that `Init` must evaluates to a pointer to `n` objects
    // of `T`. So the extent is `n` unless `n` has side effects.  Similar but
    // simpler for the case where `Init` is `new T`.
    if (const Expr *Ext = CxxNew->getArraySize().value_or(nullptr)) {
      if (!Ext->HasSideEffects(Ctx)) {
        std::optional<StringRef> ExtentString = getExprText(Ext, SM, LangOpts);
        if (!ExtentString)
          return std::nullopt;
        ExtentText = *ExtentString;
      }
    } else if (!CxxNew->isArray())
      // Although the initializer is not allocating a buffer, the pointer
      // variable could still be used in buffer access operations.
      ExtentText = One;
  } else if (Ctx.getAsConstantArrayType(Init->IgnoreImpCasts()->getType())) {
    // std::span has a single parameter constructor for initialization with
    // constant size array. The size is auto-deduced as the constructor is a
    // function template. The correct fixit is empty - no changes should happen.
    return FixItList{};
  } else {
    // In cases `Init` is of the form `&Var` after stripping of implicit
    // casts, where `&` is the built-in operator, the extent is 1.
    if (auto AddrOfExpr = dyn_cast<UnaryOperator>(Init->IgnoreImpCasts()))
      if (AddrOfExpr->getOpcode() == UnaryOperatorKind::UO_AddrOf &&
          isa_and_present<DeclRefExpr>(AddrOfExpr->getSubExpr()))
        ExtentText = One;
    // TODO: we can handle more cases, e.g., `&a[0]`, `&a`, `std::addressof`,
    // and explicit casting, etc. etc.
  }

  SmallString<32> StrBuffer{};
  std::optional<SourceLocation> LocPassInit = getPastLoc(Init, SM, LangOpts);

  if (!LocPassInit)
    return std::nullopt;

  StrBuffer.append(", ");
  StrBuffer.append(ExtentText);
  StrBuffer.append("}");
  FixIts.push_back(FixItHint::CreateInsertion(*LocPassInit, StrBuffer.str()));
  return FixIts;
}

#ifndef NDEBUG
#define DEBUG_NOTE_DECL_FAIL(D, Msg)                                           \
  Handler.addDebugNoteForVar((D), (D)->getBeginLoc(),                          \
                             "failed to produce fixit for declaration '" +     \
                                 (D)->getNameAsString() + "'" + (Msg))
#else
#define DEBUG_NOTE_DECL_FAIL(D, Msg)
#endif

// For the given variable declaration with a pointer-to-T type, returns the text
// `std::span<T>`.  If it is unable to generate the text, returns
// `std::nullopt`.
static std::optional<std::string>
createSpanTypeForVarDecl(const VarDecl *VD, const ASTContext &Ctx) {
  assert(VD->getType()->isPointerType());

  std::optional<Qualifiers> PteTyQualifiers = std::nullopt;
  std::optional<std::string> PteTyText = getPointeeTypeText(
      VD, Ctx.getSourceManager(), Ctx.getLangOpts(), &PteTyQualifiers);

  if (!PteTyText)
    return std::nullopt;

  std::string SpanTyText = "std::span<";

  SpanTyText.append(*PteTyText);
  // Append qualifiers to span element type if any:
  if (PteTyQualifiers) {
    SpanTyText.append(" ");
    SpanTyText.append(PteTyQualifiers->getAsString());
  }
  SpanTyText.append(">");
  return SpanTyText;
}

// For a `VarDecl` of the form `T  * var (= Init)?`, this
// function generates fix-its that
//  1) replace `T * var` with `std::span<T> var`; and
//  2) change `Init` accordingly to a span constructor, if it exists.
//
// FIXME: support Multi-level pointers
//
// Parameters:
//   `D` a pointer the variable declaration node
//   `Ctx` a reference to the ASTContext
//   `UserFillPlaceHolder` the user-input placeholder text
// Returns:
//    the non-empty fix-it list, if fix-its are successfuly generated; empty
//    list otherwise.
static FixItList fixLocalVarDeclWithSpan(const VarDecl *D, ASTContext &Ctx,
                                         const StringRef UserFillPlaceHolder,
                                         UnsafeBufferUsageHandler &Handler) {
  if (hasUnsupportedSpecifiers(D, Ctx.getSourceManager()))
    return {};

  FixItList FixIts{};
  std::optional<std::string> SpanTyText = createSpanTypeForVarDecl(D, Ctx);

  if (!SpanTyText) {
    DEBUG_NOTE_DECL_FAIL(D, " : failed to generate 'std::span' type");
    return {};
  }

  // Will hold the text for `std::span<T> Ident`:
  std::stringstream SS;

  SS << *SpanTyText;
  // Fix the initializer if it exists:
  if (const Expr *Init = D->getInit()) {
    std::optional<FixItList> InitFixIts =
        FixVarInitializerWithSpan(Init, Ctx, UserFillPlaceHolder);
    if (!InitFixIts)
      return {};
    FixIts.insert(FixIts.end(), std::make_move_iterator(InitFixIts->begin()),
                  std::make_move_iterator(InitFixIts->end()));
  }
  // For declaration of the form `T * ident = init;`, we want to replace
  // `T * ` with `std::span<T>`.
  // We ignore CV-qualifiers so for `T * const ident;` we also want to replace
  // just `T *` with `std::span<T>`.
  const SourceLocation EndLocForReplacement = D->getTypeSpecEndLoc();
  if (!EndLocForReplacement.isValid()) {
    DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the end of the declaration");
    return {};
  }
  // The only exception is that for `T *ident` we'll add a single space between
  // "std::span<T>" and "ident".
  // FIXME: The condition is false for identifiers expended from macros.
  if (EndLocForReplacement.getLocWithOffset(1) == getVarDeclIdentifierLoc(D))
    SS << " ";

  FixIts.push_back(FixItHint::CreateReplacement(
      SourceRange(D->getBeginLoc(), EndLocForReplacement), SS.str()));
  return FixIts;
}

static bool hasConflictingOverload(const FunctionDecl *FD) {
  return !FD->getDeclContext()->lookup(FD->getDeclName()).isSingleResult();
}

// For a `FunctionDecl`, whose `ParmVarDecl`s are being changed to have new
// types, this function produces fix-its to make the change self-contained.  Let
// 'F' be the entity defined by the original `FunctionDecl` and "NewF" be the
// entity defined by the `FunctionDecl` after the change to the parameters.
// Fix-its produced by this function are
//   1. Add the `[[clang::unsafe_buffer_usage]]` attribute to each declaration
//   of 'F';
//   2. Create a declaration of "NewF" next to each declaration of `F`;
//   3. Create a definition of "F" (as its' original definition is now belongs
//      to "NewF") next to its original definition.  The body of the creating
//      definition calls to "NewF".
//
// Example:
//
// void f(int *p);  // original declaration
// void f(int *p) { // original definition
//    p[5];
// }
//
// To change the parameter `p` to be of `std::span<int>` type, we
// also add overloads:
//
// [[clang::unsafe_buffer_usage]] void f(int *p); // original decl
// void f(std::span<int> p);                      // added overload decl
// void f(std::span<int> p) {     // original def where param is changed
//    p[5];
// }
// [[clang::unsafe_buffer_usage]] void f(int *p) {  // added def
//   return f(std::span(p, <# size #>));
// }
//
static std::optional<FixItList>
createOverloadsForFixedParams(const FixitStrategy &S, const FunctionDecl *FD,
                              const ASTContext &Ctx,
                              UnsafeBufferUsageHandler &Handler) {
  // FIXME: need to make this conflict checking better:
  if (hasConflictingOverload(FD))
    return std::nullopt;

  const SourceManager &SM = Ctx.getSourceManager();
  const LangOptions &LangOpts = Ctx.getLangOpts();
  const unsigned NumParms = FD->getNumParams();
  std::vector<std::string> NewTysTexts(NumParms);
  std::vector<bool> ParmsMask(NumParms, false);
  bool AtLeastOneParmToFix = false;

  for (unsigned i = 0; i < NumParms; i++) {
    const ParmVarDecl *PVD = FD->getParamDecl(i);

    if (S.lookup(PVD) == FixitStrategy::Kind::Wontfix)
      continue;
    if (S.lookup(PVD) != FixitStrategy::Kind::Span)
      // Not supported, not suppose to happen:
      return std::nullopt;

    std::optional<Qualifiers> PteTyQuals = std::nullopt;
    std::optional<std::string> PteTyText =
        getPointeeTypeText(PVD, SM, LangOpts, &PteTyQuals);

    if (!PteTyText)
      // something wrong in obtaining the text of the pointee type, give up
      return std::nullopt;
    // FIXME: whether we should create std::span type depends on the
    // FixitStrategy.
    NewTysTexts[i] = getSpanTypeText(*PteTyText, PteTyQuals);
    ParmsMask[i] = true;
    AtLeastOneParmToFix = true;
  }
  if (!AtLeastOneParmToFix)
    // No need to create function overloads:
    return {};
  // FIXME Respect indentation of the original code.

  // A lambda that creates the text representation of a function declaration
  // with the new type signatures:
  const auto NewOverloadSignatureCreator =
      [&SM, &LangOpts, &NewTysTexts,
       &ParmsMask](const FunctionDecl *FD) -> std::optional<std::string> {
    std::stringstream SS;

    SS << ";";
    SS << getEndOfLine().str();
    // Append: ret-type func-name "("
    if (auto Prefix = getRangeText(
            SourceRange(FD->getBeginLoc(), (*FD->param_begin())->getBeginLoc()),
            SM, LangOpts))
      SS << Prefix->str();
    else
      return std::nullopt; // give up
    // Append: parameter-type-list
    const unsigned NumParms = FD->getNumParams();

    for (unsigned i = 0; i < NumParms; i++) {
      const ParmVarDecl *Parm = FD->getParamDecl(i);

      if (Parm->isImplicit())
        continue;
      if (ParmsMask[i]) {
        // This `i`-th parameter will be fixed with `NewTysTexts[i]` being its
        // new type:
        SS << NewTysTexts[i];
        // print parameter name if provided:
        if (IdentifierInfo *II = Parm->getIdentifier())
          SS << ' ' << II->getName().str();
      } else if (auto ParmTypeText =
                     getRangeText(getSourceRangeToTokenEnd(Parm, SM, LangOpts),
                                  SM, LangOpts)) {
        // print the whole `Parm` without modification:
        SS << ParmTypeText->str();
      } else
        return std::nullopt; // something wrong, give up
      if (i != NumParms - 1)
        SS << ", ";
    }
    SS << ")";
    return SS.str();
  };

  // A lambda that creates the text representation of a function definition with
  // the original signature:
  const auto OldOverloadDefCreator =
      [&Handler, &SM, &LangOpts, &NewTysTexts,
       &ParmsMask](const FunctionDecl *FD) -> std::optional<std::string> {
    std::stringstream SS;

    SS << getEndOfLine().str();
    // Append: attr-name ret-type func-name "(" param-list ")" "{"
    if (auto FDPrefix = getRangeText(
            SourceRange(FD->getBeginLoc(), FD->getBody()->getBeginLoc()), SM,
            LangOpts))
      SS << Handler.getUnsafeBufferUsageAttributeTextAt(FD->getBeginLoc(), " ")
         << FDPrefix->str() << "{";
    else
      return std::nullopt;
    // Append: "return" func-name "("
    if (auto FunQualName = getFunNameText(FD, SM, LangOpts))
      SS << "return " << FunQualName->str() << "(";
    else
      return std::nullopt;

    // Append: arg-list
    const unsigned NumParms = FD->getNumParams();
    for (unsigned i = 0; i < NumParms; i++) {
      const ParmVarDecl *Parm = FD->getParamDecl(i);

      if (Parm->isImplicit())
        continue;
      // FIXME: If a parameter has no name, it is unused in the
      // definition. So we could just leave it as it is.
      if (!Parm->getIdentifier())
        // If a parameter of a function definition has no name:
        return std::nullopt;
      if (ParmsMask[i])
        // This is our spanified paramter!
        SS << NewTysTexts[i] << "(" << Parm->getIdentifier()->getName().str()
           << ", " << getUserFillPlaceHolder("size") << ")";
      else
        SS << Parm->getIdentifier()->getName().str();
      if (i != NumParms - 1)
        SS << ", ";
    }
    // finish call and the body
    SS << ");}" << getEndOfLine().str();
    // FIXME: 80-char line formatting?
    return SS.str();
  };

  FixItList FixIts{};
  for (FunctionDecl *FReDecl : FD->redecls()) {
    std::optional<SourceLocation> Loc = getPastLoc(FReDecl, SM, LangOpts);

    if (!Loc)
      return {};
    if (FReDecl->isThisDeclarationADefinition()) {
      assert(FReDecl == FD && "inconsistent function definition");
      // Inserts a definition with the old signature to the end of
      // `FReDecl`:
      if (auto OldOverloadDef = OldOverloadDefCreator(FReDecl))
        FixIts.emplace_back(FixItHint::CreateInsertion(*Loc, *OldOverloadDef));
      else
        return {}; // give up
    } else {
      // Adds the unsafe-buffer attribute (if not already there) to `FReDecl`:
      if (!FReDecl->hasAttr<UnsafeBufferUsageAttr>()) {
        FixIts.emplace_back(FixItHint::CreateInsertion(
            FReDecl->getBeginLoc(), Handler.getUnsafeBufferUsageAttributeTextAt(
                                        FReDecl->getBeginLoc(), " ")));
      }
      // Inserts a declaration with the new signature to the end of `FReDecl`:
      if (auto NewOverloadDecl = NewOverloadSignatureCreator(FReDecl))
        FixIts.emplace_back(FixItHint::CreateInsertion(*Loc, *NewOverloadDecl));
      else
        return {};
    }
  }
  return FixIts;
}

// To fix a `ParmVarDecl` to be of `std::span` type.
static FixItList fixParamWithSpan(const ParmVarDecl *PVD, const ASTContext &Ctx,
                                  UnsafeBufferUsageHandler &Handler) {
  if (hasUnsupportedSpecifiers(PVD, Ctx.getSourceManager())) {
    DEBUG_NOTE_DECL_FAIL(PVD, " : has unsupport specifier(s)");
    return {};
  }
  if (PVD->hasDefaultArg()) {
    // FIXME: generate fix-its for default values:
    DEBUG_NOTE_DECL_FAIL(PVD, " : has default arg");
    return {};
  }

  std::optional<Qualifiers> PteTyQualifiers = std::nullopt;
  std::optional<std::string> PteTyText = getPointeeTypeText(
      PVD, Ctx.getSourceManager(), Ctx.getLangOpts(), &PteTyQualifiers);

  if (!PteTyText) {
    DEBUG_NOTE_DECL_FAIL(PVD, " : invalid pointee type");
    return {};
  }

  std::optional<StringRef> PVDNameText = PVD->getIdentifier()->getName();

  if (!PVDNameText) {
    DEBUG_NOTE_DECL_FAIL(PVD, " : invalid identifier name");
    return {};
  }

  std::stringstream SS;
  std::optional<std::string> SpanTyText = createSpanTypeForVarDecl(PVD, Ctx);

  if (PteTyQualifiers)
    // Append qualifiers if they exist:
    SS << getSpanTypeText(*PteTyText, PteTyQualifiers);
  else
    SS << getSpanTypeText(*PteTyText);
  // Append qualifiers to the type of the parameter:
  if (PVD->getType().hasQualifiers())
    SS << ' ' << PVD->getType().getQualifiers().getAsString();
  // Append parameter's name:
  SS << ' ' << PVDNameText->str();
  // Add replacement fix-it:
  return {FixItHint::CreateReplacement(PVD->getSourceRange(), SS.str())};
}

static FixItList fixVariableWithSpan(const VarDecl *VD,
                                     const DeclUseTracker &Tracker,
                                     ASTContext &Ctx,
                                     UnsafeBufferUsageHandler &Handler) {
  const DeclStmt *DS = Tracker.lookupDecl(VD);
  if (!DS) {
    DEBUG_NOTE_DECL_FAIL(VD,
                         " : variables declared this way not implemented yet");
    return {};
  }
  if (!DS->isSingleDecl()) {
    // FIXME: to support handling multiple `VarDecl`s in a single `DeclStmt`
    DEBUG_NOTE_DECL_FAIL(VD, " : multiple VarDecls");
    return {};
  }
  // Currently DS is an unused variable but we'll need it when
  // non-single decls are implemented, where the pointee type name
  // and the '*' are spread around the place.
  (void)DS;

  // FIXME: handle cases where DS has multiple declarations
  return fixLocalVarDeclWithSpan(VD, Ctx, getUserFillPlaceHolder(), Handler);
}

static FixItList fixVarDeclWithArray(const VarDecl *D, const ASTContext &Ctx,
                                     UnsafeBufferUsageHandler &Handler) {
  FixItList FixIts{};

  // Note: the code below expects the declaration to not use any type sugar like
  // typedef.
  if (auto CAT = Ctx.getAsConstantArrayType(D->getType())) {
    const QualType &ArrayEltT = CAT->getElementType();
    assert(!ArrayEltT.isNull() && "Trying to fix a non-array type variable!");
    // FIXME: support multi-dimensional arrays
    if (isa<clang::ArrayType>(ArrayEltT.getCanonicalType()))
      return {};

    const SourceLocation IdentifierLoc = getVarDeclIdentifierLoc(D);

    // Get the spelling of the element type as written in the source file
    // (including macros, etc.).
    auto MaybeElemTypeTxt =
        getRangeText({D->getBeginLoc(), IdentifierLoc}, Ctx.getSourceManager(),
                     Ctx.getLangOpts());
    if (!MaybeElemTypeTxt)
      return {};
    const llvm::StringRef ElemTypeTxt = MaybeElemTypeTxt->trim();

    // Find the '[' token.
    std::optional<Token> NextTok = Lexer::findNextToken(
        IdentifierLoc, Ctx.getSourceManager(), Ctx.getLangOpts());
    while (NextTok && !NextTok->is(tok::l_square) &&
           NextTok->getLocation() <= D->getSourceRange().getEnd())
      NextTok = Lexer::findNextToken(NextTok->getLocation(),
                                     Ctx.getSourceManager(), Ctx.getLangOpts());
    if (!NextTok)
      return {};
    const SourceLocation LSqBracketLoc = NextTok->getLocation();

    // Get the spelling of the array size as written in the source file
    // (including macros, etc.).
    auto MaybeArraySizeTxt = getRangeText(
        {LSqBracketLoc.getLocWithOffset(1), D->getTypeSpecEndLoc()},
        Ctx.getSourceManager(), Ctx.getLangOpts());
    if (!MaybeArraySizeTxt)
      return {};
    const llvm::StringRef ArraySizeTxt = MaybeArraySizeTxt->trim();
    if (ArraySizeTxt.empty()) {
      // FIXME: Support array size getting determined from the initializer.
      // Examples:
      //    int arr1[] = {0, 1, 2};
      //    int arr2{3, 4, 5};
      // We might be able to preserve the non-specified size with `auto` and
      // `std::to_array`:
      //    auto arr1 = std::to_array<int>({0, 1, 2});
      return {};
    }

    std::optional<StringRef> IdentText =
        getVarDeclIdentifierText(D, Ctx.getSourceManager(), Ctx.getLangOpts());

    if (!IdentText) {
      DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the identifier");
      return {};
    }

    SmallString<32> Replacement;
    llvm::raw_svector_ostream OS(Replacement);
    OS << "std::array<" << ElemTypeTxt << ", " << ArraySizeTxt << "> "
       << IdentText->str();

    FixIts.push_back(FixItHint::CreateReplacement(
        SourceRange{D->getBeginLoc(), D->getTypeSpecEndLoc()}, OS.str()));
  }

  return FixIts;
}

static FixItList fixVariableWithArray(const VarDecl *VD,
                                      const DeclUseTracker &Tracker,
                                      const ASTContext &Ctx,
                                      UnsafeBufferUsageHandler &Handler) {
  const DeclStmt *DS = Tracker.lookupDecl(VD);
  assert(DS && "Fixing non-local variables not implemented yet!");
  if (!DS->isSingleDecl()) {
    // FIXME: to support handling multiple `VarDecl`s in a single `DeclStmt`
    return {};
  }
  // Currently DS is an unused variable but we'll need it when
  // non-single decls are implemented, where the pointee type name
  // and the '*' are spread around the place.
  (void)DS;

  // FIXME: handle cases where DS has multiple declarations
  return fixVarDeclWithArray(VD, Ctx, Handler);
}

// TODO: we should be consistent to use `std::nullopt` to represent no-fix due
// to any unexpected problem.
static FixItList
fixVariable(const VarDecl *VD, FixitStrategy::Kind K,
            /* The function decl under analysis */ const Decl *D,
            const DeclUseTracker &Tracker, ASTContext &Ctx,
            UnsafeBufferUsageHandler &Handler) {
  if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
    auto *FD = dyn_cast<clang::FunctionDecl>(PVD->getDeclContext());
    if (!FD || FD != D) {
      // `FD != D` means that `PVD` belongs to a function that is not being
      // analyzed currently.  Thus `FD` may not be complete.
      DEBUG_NOTE_DECL_FAIL(VD, " : function not currently analyzed");
      return {};
    }

    // TODO If function has a try block we can't change params unless we check
    // also its catch block for their use.
    // FIXME We might support static class methods, some select methods,
    // operators and possibly lamdas.
    if (FD->isMain() || FD->isConstexpr() ||
        FD->getTemplatedKind() != FunctionDecl::TemplatedKind::TK_NonTemplate ||
        FD->isVariadic() ||
        // also covers call-operator of lamdas
        isa<CXXMethodDecl>(FD) ||
        // skip when the function body is a try-block
        (FD->hasBody() && isa<CXXTryStmt>(FD->getBody())) ||
        FD->isOverloadedOperator()) {
      DEBUG_NOTE_DECL_FAIL(VD, " : unsupported function decl");
      return {}; // TODO test all these cases
    }
  }

  switch (K) {
  case FixitStrategy::Kind::Span: {
    if (VD->getType()->isPointerType()) {
      if (const auto *PVD = dyn_cast<ParmVarDecl>(VD))
        return fixParamWithSpan(PVD, Ctx, Handler);

      if (VD->isLocalVarDecl())
        return fixVariableWithSpan(VD, Tracker, Ctx, Handler);
    }
    DEBUG_NOTE_DECL_FAIL(VD, " : not a pointer");
    return {};
  }
  case FixitStrategy::Kind::Array: {
    if (VD->isLocalVarDecl() && Ctx.getAsConstantArrayType(VD->getType()))
      return fixVariableWithArray(VD, Tracker, Ctx, Handler);

    DEBUG_NOTE_DECL_FAIL(VD, " : not a local const-size array");
    return {};
  }
  case FixitStrategy::Kind::Iterator:
  case FixitStrategy::Kind::Vector:
    llvm_unreachable("FixitStrategy not implemented yet!");
  case FixitStrategy::Kind::Wontfix:
    llvm_unreachable("Invalid strategy!");
  }
  llvm_unreachable("Unknown strategy!");
}

// Returns true iff there exists a `FixItHint` 'h' in `FixIts` such that the
// `RemoveRange` of 'h' overlaps with a macro use.
static bool overlapWithMacro(const FixItList &FixIts) {
  // FIXME: For now we only check if the range (or the first token) is (part of)
  // a macro expansion.  Ideally, we want to check for all tokens in the range.
  return llvm::any_of(FixIts, [](const FixItHint &Hint) {
    auto Range = Hint.RemoveRange;
    if (Range.getBegin().isMacroID() || Range.getEnd().isMacroID())
      // If the range (or the first token) is (part of) a macro expansion:
      return true;
    return false;
  });
}

// Returns true iff `VD` is a parameter of the declaration `D`:
static bool isParameterOf(const VarDecl *VD, const Decl *D) {
  return isa<ParmVarDecl>(VD) &&
         VD->getDeclContext() == dyn_cast<DeclContext>(D);
}

// Erases variables in `FixItsForVariable`, if such a variable has an unfixable
// group mate.  A variable `v` is unfixable iff `FixItsForVariable` does not
// contain `v`.
static void eraseVarsForUnfixableGroupMates(
    std::map<const VarDecl *, FixItList> &FixItsForVariable,
    const VariableGroupsManager &VarGrpMgr) {
  // Variables will be removed from `FixItsForVariable`:
  SmallVector<const VarDecl *, 8> ToErase;

  for (const auto &[VD, Ignore] : FixItsForVariable) {
    VarGrpRef Grp = VarGrpMgr.getGroupOfVar(VD);
    if (llvm::any_of(Grp,
                     [&FixItsForVariable](const VarDecl *GrpMember) -> bool {
                       return !FixItsForVariable.count(GrpMember);
                     })) {
      // At least one group member cannot be fixed, so we have to erase the
      // whole group:
      for (const VarDecl *Member : Grp)
        ToErase.push_back(Member);
    }
  }
  for (auto *VarToErase : ToErase)
    FixItsForVariable.erase(VarToErase);
}

// Returns the fix-its that create bounds-safe function overloads for the
// function `D`, if `D`'s parameters will be changed to safe-types through
// fix-its in `FixItsForVariable`.
//
// NOTE: In case `D`'s parameters will be changed but bounds-safe function
// overloads cannot created, the whole group that contains the parameters will
// be erased from `FixItsForVariable`.
static FixItList createFunctionOverloadsForParms(
    std::map<const VarDecl *, FixItList> &FixItsForVariable /* mutable */,
    const VariableGroupsManager &VarGrpMgr, const FunctionDecl *FD,
    const FixitStrategy &S, ASTContext &Ctx,
    UnsafeBufferUsageHandler &Handler) {
  FixItList FixItsSharedByParms{};

  std::optional<FixItList> OverloadFixes =
      createOverloadsForFixedParams(S, FD, Ctx, Handler);

  if (OverloadFixes) {
    FixItsSharedByParms.append(*OverloadFixes);
  } else {
    // Something wrong in generating `OverloadFixes`, need to remove the
    // whole group, where parameters are in, from `FixItsForVariable` (Note
    // that all parameters should be in the same group):
    for (auto *Member : VarGrpMgr.getGroupOfParms())
      FixItsForVariable.erase(Member);
  }
  return FixItsSharedByParms;
}

// Constructs self-contained fix-its for each variable in `FixablesForAllVars`.
static std::map<const VarDecl *, FixItList>
getFixIts(FixableGadgetSets &FixablesForAllVars, const FixitStrategy &S,
          ASTContext &Ctx,
          /* The function decl under analysis */ const Decl *D,
          const DeclUseTracker &Tracker, UnsafeBufferUsageHandler &Handler,
          const VariableGroupsManager &VarGrpMgr) {
  // `FixItsForVariable` will map each variable to a set of fix-its directly
  // associated to the variable itself.  Fix-its of distinct variables in
  // `FixItsForVariable` are disjoint.
  std::map<const VarDecl *, FixItList> FixItsForVariable;

  // Populate `FixItsForVariable` with fix-its directly associated with each
  // variable.  Fix-its directly associated to a variable 'v' are the ones
  // produced by the `FixableGadget`s whose claimed variable is 'v'.
  for (const auto &[VD, Fixables] : FixablesForAllVars.byVar) {
    FixItsForVariable[VD] =
        fixVariable(VD, S.lookup(VD), D, Tracker, Ctx, Handler);
    // If we fail to produce Fix-It for the declaration we have to skip the
    // variable entirely.
    if (FixItsForVariable[VD].empty()) {
      FixItsForVariable.erase(VD);
      continue;
    }
    for (const auto &F : Fixables) {
      std::optional<FixItList> Fixits = F->getFixits(S);

      if (Fixits) {
        FixItsForVariable[VD].insert(FixItsForVariable[VD].end(),
                                     Fixits->begin(), Fixits->end());
        continue;
      }
#ifndef NDEBUG
      Handler.addDebugNoteForVar(
          VD, F->getSourceLoc(),
          ("gadget '" + F->getDebugName() + "' refused to produce a fix")
              .str());
#endif
      FixItsForVariable.erase(VD);
      break;
    }
  }

  // `FixItsForVariable` now contains only variables that can be
  // fixed. A variable can be fixed if its' declaration and all Fixables
  // associated to it can all be fixed.

  // To further remove from `FixItsForVariable` variables whose group mates
  // cannot be fixed...
  eraseVarsForUnfixableGroupMates(FixItsForVariable, VarGrpMgr);
  // Now `FixItsForVariable` gets further reduced: a variable is in
  // `FixItsForVariable` iff it can be fixed and all its group mates can be
  // fixed.

  // Fix-its of bounds-safe overloads of `D` are shared by parameters of `D`.
  // That is,  when fixing multiple parameters in one step,  these fix-its will
  // be applied only once (instead of being applied per parameter).
  FixItList FixItsSharedByParms{};

  if (auto *FD = dyn_cast<FunctionDecl>(D))
    FixItsSharedByParms = createFunctionOverloadsForParms(
        FixItsForVariable, VarGrpMgr, FD, S, Ctx, Handler);

  // The map that maps each variable `v` to fix-its for the whole group where
  // `v` is in:
  std::map<const VarDecl *, FixItList> FinalFixItsForVariable{
      FixItsForVariable};

  for (auto &[Var, Ignore] : FixItsForVariable) {
    bool AnyParm = false;
    const auto VarGroupForVD = VarGrpMgr.getGroupOfVar(Var, &AnyParm);

    for (const VarDecl *GrpMate : VarGroupForVD) {
      if (Var == GrpMate)
        continue;
      if (FixItsForVariable.count(GrpMate))
        FinalFixItsForVariable[Var].append(FixItsForVariable[GrpMate]);
    }
    if (AnyParm) {
      // This assertion should never fail.  Otherwise we have a bug.
      assert(!FixItsSharedByParms.empty() &&
             "Should not try to fix a parameter that does not belong to a "
             "FunctionDecl");
      FinalFixItsForVariable[Var].append(FixItsSharedByParms);
    }
  }
  // Fix-its that will be applied in one step shall NOT:
  // 1. overlap with macros or/and templates; or
  // 2. conflict with each other.
  // Otherwise, the fix-its will be dropped.
  for (auto Iter = FinalFixItsForVariable.begin();
       Iter != FinalFixItsForVariable.end();)
    if (overlapWithMacro(Iter->second) ||
        clang::internal::anyConflict(Iter->second, Ctx.getSourceManager())) {
      Iter = FinalFixItsForVariable.erase(Iter);
    } else
      Iter++;
  return FinalFixItsForVariable;
}

template <typename VarDeclIterTy>
static FixitStrategy
getNaiveStrategy(llvm::iterator_range<VarDeclIterTy> UnsafeVars) {
  FixitStrategy S;
  for (const VarDecl *VD : UnsafeVars) {
    if (isa<ConstantArrayType>(VD->getType().getCanonicalType()))
      S.set(VD, FixitStrategy::Kind::Array);
    else
      S.set(VD, FixitStrategy::Kind::Span);
  }
  return S;
}

//  Manages variable groups:
class VariableGroupsManagerImpl : public VariableGroupsManager {
  const std::vector<VarGrpTy> Groups;
  const std::map<const VarDecl *, unsigned> &VarGrpMap;
  const llvm::SetVector<const VarDecl *> &GrpsUnionForParms;

public:
  VariableGroupsManagerImpl(
      const std::vector<VarGrpTy> &Groups,
      const std::map<const VarDecl *, unsigned> &VarGrpMap,
      const llvm::SetVector<const VarDecl *> &GrpsUnionForParms)
      : Groups(Groups), VarGrpMap(VarGrpMap),
        GrpsUnionForParms(GrpsUnionForParms) {}

  VarGrpRef getGroupOfVar(const VarDecl *Var, bool *HasParm) const override {
    if (GrpsUnionForParms.contains(Var)) {
      if (HasParm)
        *HasParm = true;
      return GrpsUnionForParms.getArrayRef();
    }
    if (HasParm)
      *HasParm = false;

    auto It = VarGrpMap.find(Var);

    if (It == VarGrpMap.end())
      return {};
    return Groups[It->second];
  }

  VarGrpRef getGroupOfParms() const override {
    return GrpsUnionForParms.getArrayRef();
  }
};

static void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets,
                         WarningGadgetList WarningGadgets,
                         DeclUseTracker Tracker,
                         UnsafeBufferUsageHandler &Handler,
                         bool EmitSuggestions) {
  if (!EmitSuggestions) {
    // Our job is very easy without suggestions. Just warn about
    // every problematic operation and consider it done. No need to deal
    // with fixable gadgets, no need to group operations by variable.
    for (const auto &G : WarningGadgets) {
      G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/false,
                               D->getASTContext());
    }

    // This return guarantees that most of the machine doesn't run when
    // suggestions aren't requested.
    assert(FixableGadgets.empty() &&
           "Fixable gadgets found but suggestions not requested!");
    return;
  }

  // If no `WarningGadget`s ever matched, there is no unsafe operations in the
  //  function under the analysis. No need to fix any Fixables.
  if (!WarningGadgets.empty()) {
    // Gadgets "claim" variables they're responsible for. Once this loop
    // finishes, the tracker will only track DREs that weren't claimed by any
    // gadgets, i.e. not understood by the analysis.
    for (const auto &G : FixableGadgets) {
      for (const auto *DRE : G->getClaimedVarUseSites()) {
        Tracker.claimUse(DRE);
      }
    }
  }

  // If no `WarningGadget`s ever matched, there is no unsafe operations in the
  // function under the analysis.  Thus, it early returns here as there is
  // nothing needs to be fixed.
  //
  // Note this claim is based on the assumption that there is no unsafe
  // variable whose declaration is invisible from the analyzing function.
  // Otherwise, we need to consider if the uses of those unsafe varuables needs
  // fix.
  // So far, we are not fixing any global variables or class members. And,
  // lambdas will be analyzed along with the enclosing function. So this early
  // return is correct for now.
  if (WarningGadgets.empty())
    return;

  WarningGadgetSets UnsafeOps =
      groupWarningGadgetsByVar(std::move(WarningGadgets));
  FixableGadgetSets FixablesForAllVars =
      groupFixablesByVar(std::move(FixableGadgets));

  std::map<const VarDecl *, FixItList> FixItsForVariableGroup;

  // Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
  for (auto it = FixablesForAllVars.byVar.cbegin();
       it != FixablesForAllVars.byVar.cend();) {
    // FIXME: need to deal with global variables later
    if ((!it->first->isLocalVarDecl() && !isa<ParmVarDecl>(it->first))) {
#ifndef NDEBUG
      Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
                                 ("failed to produce fixit for '" +
                                  it->first->getNameAsString() +
                                  "' : neither local nor a parameter"));
#endif
      it = FixablesForAllVars.byVar.erase(it);
    } else if (it->first->getType().getCanonicalType()->isReferenceType()) {
#ifndef NDEBUG
      Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
                                 ("failed to produce fixit for '" +
                                  it->first->getNameAsString() +
                                  "' : has a reference type"));
#endif
      it = FixablesForAllVars.byVar.erase(it);
    } else if (Tracker.hasUnclaimedUses(it->first)) {
      it = FixablesForAllVars.byVar.erase(it);
    } else if (it->first->isInitCapture()) {
#ifndef NDEBUG
      Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
                                 ("failed to produce fixit for '" +
                                  it->first->getNameAsString() +
                                  "' : init capture"));
#endif
      it = FixablesForAllVars.byVar.erase(it);
    } else {
      ++it;
    }
  }

#ifndef NDEBUG
  for (const auto &it : UnsafeOps.byVar) {
    const VarDecl *const UnsafeVD = it.first;
    auto UnclaimedDREs = Tracker.getUnclaimedUses(UnsafeVD);
    if (UnclaimedDREs.empty())
      continue;
    const auto UnfixedVDName = UnsafeVD->getNameAsString();
    for (const clang::DeclRefExpr *UnclaimedDRE : UnclaimedDREs) {
      std::string UnclaimedUseTrace =
          getDREAncestorString(UnclaimedDRE, D->getASTContext());

      Handler.addDebugNoteForVar(
          UnsafeVD, UnclaimedDRE->getBeginLoc(),
          ("failed to produce fixit for '" + UnfixedVDName +
           "' : has an unclaimed use\nThe unclaimed DRE trace: " +
           UnclaimedUseTrace));
    }
  }
#endif

  // Fixpoint iteration for pointer assignments
  using DepMapTy =
      llvm::DenseMap<const VarDecl *, llvm::SetVector<const VarDecl *>>;
  DepMapTy DependenciesMap{};
  DepMapTy PtrAssignmentGraph{};

  for (const auto &it : FixablesForAllVars.byVar) {
    for (const FixableGadget *fixable : it.second) {
      std::optional<std::pair<const VarDecl *, const VarDecl *>> ImplPair =
          fixable->getStrategyImplications();
      if (ImplPair) {
        std::pair<const VarDecl *, const VarDecl *> Impl = std::move(*ImplPair);
        PtrAssignmentGraph[Impl.first].insert(Impl.second);
      }
    }
  }

  /*
   The following code does a BFS traversal of the `PtrAssignmentGraph`
   considering all unsafe vars as starting nodes and constructs an undirected
   graph `DependenciesMap`. Constructing the `DependenciesMap` in this manner
   elimiates all variables that are unreachable from any unsafe var. In other
   words, this removes all dependencies that don't include any unsafe variable
   and consequently don't need any fixit generation.
   Note: A careful reader would observe that the code traverses
   `PtrAssignmentGraph` using `CurrentVar` but adds edges between `Var` and
   `Adj` and not between `CurrentVar` and `Adj`. Both approaches would
   achieve the same result but the one used here dramatically cuts the
   amount of hoops the second part of the algorithm needs to jump, given that
   a lot of these connections become "direct". The reader is advised not to
   imagine how the graph is transformed because of using `Var` instead of
   `CurrentVar`. The reader can continue reading as if `CurrentVar` was used,
   and think about why it's equivalent later.
   */
  std::set<const VarDecl *> VisitedVarsDirected{};
  for (const auto &[Var, ignore] : UnsafeOps.byVar) {
    if (VisitedVarsDirected.find(Var) == VisitedVarsDirected.end()) {

      std::queue<const VarDecl *> QueueDirected{};
      QueueDirected.push(Var);
      while (!QueueDirected.empty()) {
        const VarDecl *CurrentVar = QueueDirected.front();
        QueueDirected.pop();
        VisitedVarsDirected.insert(CurrentVar);
        auto AdjacentNodes = PtrAssignmentGraph[CurrentVar];
        for (const VarDecl *Adj : AdjacentNodes) {
          if (VisitedVarsDirected.find(Adj) == VisitedVarsDirected.end()) {
            QueueDirected.push(Adj);
          }
          DependenciesMap[Var].insert(Adj);
          DependenciesMap[Adj].insert(Var);
        }
      }
    }
  }

  // `Groups` stores the set of Connected Components in the graph.
  std::vector<VarGrpTy> Groups;
  // `VarGrpMap` maps variables that need fix to the groups (indexes) that the
  // variables belong to.  Group indexes refer to the elements in `Groups`.
  // `VarGrpMap` is complete in that every variable that needs fix is in it.
  std::map<const VarDecl *, unsigned> VarGrpMap;
  // The union group over the ones in "Groups" that contain parameters of `D`:
  llvm::SetVector<const VarDecl *>
      GrpsUnionForParms; // these variables need to be fixed in one step

  // Group Connected Components for Unsafe Vars
  // (Dependencies based on pointer assignments)
  std::set<const VarDecl *> VisitedVars{};
  for (const auto &[Var, ignore] : UnsafeOps.byVar) {
    if (VisitedVars.find(Var) == VisitedVars.end()) {
      VarGrpTy &VarGroup = Groups.emplace_back();
      std::queue<const VarDecl *> Queue{};

      Queue.push(Var);
      while (!Queue.empty()) {
        const VarDecl *CurrentVar = Queue.front();
        Queue.pop();
        VisitedVars.insert(CurrentVar);
        VarGroup.push_back(CurrentVar);
        auto AdjacentNodes = DependenciesMap[CurrentVar];
        for (const VarDecl *Adj : AdjacentNodes) {
          if (VisitedVars.find(Adj) == VisitedVars.end()) {
            Queue.push(Adj);
          }
        }
      }

      bool HasParm = false;
      unsigned GrpIdx = Groups.size() - 1;

      for (const VarDecl *V : VarGroup) {
        VarGrpMap[V] = GrpIdx;
        if (!HasParm && isParameterOf(V, D))
          HasParm = true;
      }
      if (HasParm)
        GrpsUnionForParms.insert_range(VarGroup);
    }
  }

  // Remove a `FixableGadget` if the associated variable is not in the graph
  // computed above.  We do not want to generate fix-its for such variables,
  // since they are neither warned nor reachable from a warned one.
  //
  // Note a variable is not warned if it is not directly used in any unsafe
  // operation. A variable `v` is NOT reachable from an unsafe variable, if it
  // does not exist another variable `u` such that `u` is warned and fixing `u`
  // (transitively) implicates fixing `v`.
  //
  // For example,
  // ```
  // void f(int * p) {
  //   int * a = p; *p = 0;
  // }
  // ```
  // `*p = 0` is a fixable gadget associated with a variable `p` that is neither
  // warned nor reachable from a warned one.  If we add `a[5] = 0` to the end of
  // the function above, `p` becomes reachable from a warned variable.
  for (auto I = FixablesForAllVars.byVar.begin();
       I != FixablesForAllVars.byVar.end();) {
    // Note `VisitedVars` contain all the variables in the graph:
    if (!VisitedVars.count((*I).first)) {
      // no such var in graph:
      I = FixablesForAllVars.byVar.erase(I);
    } else
      ++I;
  }

  // We assign strategies to variables that are 1) in the graph and 2) can be
  // fixed. Other variables have the default "Won't fix" strategy.
  FixitStrategy NaiveStrategy = getNaiveStrategy(llvm::make_filter_range(
      VisitedVars, [&FixablesForAllVars](const VarDecl *V) {
        // If a warned variable has no "Fixable", it is considered unfixable:
        return FixablesForAllVars.byVar.count(V);
      }));
  VariableGroupsManagerImpl VarGrpMgr(Groups, VarGrpMap, GrpsUnionForParms);

  if (isa<NamedDecl>(D))
    // The only case where `D` is not a `NamedDecl` is when `D` is a
    // `BlockDecl`. Let's not fix variables in blocks for now
    FixItsForVariableGroup =
        getFixIts(FixablesForAllVars, NaiveStrategy, D->getASTContext(), D,
                  Tracker, Handler, VarGrpMgr);

  for (const auto &G : UnsafeOps.noVar) {
    G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/false,
                             D->getASTContext());
  }

  for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) {
    auto FixItsIt = FixItsForVariableGroup.find(VD);
    Handler.handleUnsafeVariableGroup(VD, VarGrpMgr,
                                      FixItsIt != FixItsForVariableGroup.end()
                                          ? std::move(FixItsIt->second)
                                          : FixItList{},
                                      D, NaiveStrategy);
    for (const auto &G : WarningGadgets) {
      G->handleUnsafeOperation(Handler, /*IsRelatedToDecl=*/true,
                               D->getASTContext());
    }
  }
}

void clang::checkUnsafeBufferUsage(const Decl *D,
                                   UnsafeBufferUsageHandler &Handler,
                                   bool EmitSuggestions) {
#ifndef NDEBUG
  Handler.clearDebugNotes();
#endif

  assert(D);

  SmallVector<Stmt *> Stmts;

  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
    // We do not want to visit a Lambda expression defined inside a method
    // independently. Instead, it should be visited along with the outer method.
    // FIXME: do we want to do the same thing for `BlockDecl`s?
    if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
      if (MD->getParent()->isLambda() && MD->getParent()->isLocalClass())
        return;
    }

    for (FunctionDecl *FReDecl : FD->redecls()) {
      if (FReDecl->isExternC()) {
        // Do not emit fixit suggestions for functions declared in an
        // extern "C" block.
        EmitSuggestions = false;
        break;
      }
    }

    Stmts.push_back(FD->getBody());

    if (const auto *ID = dyn_cast<CXXConstructorDecl>(D)) {
      for (const CXXCtorInitializer *CI : ID->inits()) {
        Stmts.push_back(CI->getInit());
      }
    }
  } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
    Stmts.push_back(D->getBody());
  }

  assert(!Stmts.empty());

  FixableGadgetList FixableGadgets;
  WarningGadgetList WarningGadgets;
  DeclUseTracker Tracker;
  for (Stmt *S : Stmts) {
    findGadgets(S, D->getASTContext(), Handler, EmitSuggestions, FixableGadgets,
                WarningGadgets, Tracker);
  }
  applyGadgets(D, std::move(FixableGadgets), std::move(WarningGadgets),
               std::move(Tracker), Handler, EmitSuggestions);
}
