//===- 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/DeclTemplate.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/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <cstddef>
#include <optional>
#include <queue>
#include <set>
#include <sstream>
#include <vector>

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

#define SIZED_CONTAINER_OR_VIEW_LIST                                           \
  "span", "array", "vector", "basic_string_view", "basic_string",              \
      "initializer_list",

// 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,
                                 bool TraverseQualifier) override {
    // Unevaluated context.
    if (IgnoreUnevaluatedContext)
      return true;
    return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(
        Node, TraverseQualifier);
  }

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

  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 an expression like `&X` or `std::addressof(X)`, returns the `Expr`
// corresponding to `X` (after removing parens and implicit casts).
// Returns null if the input expression `E` is not an address-of expression.
static const Expr *getSubExprInAddressOfExpr(const Expr &E) {
  if (!E.getType()->isPointerType())
    return nullptr;
  const Expr *Ptr = E.IgnoreParenImpCasts();

  // `&X` where `X` is an `Expr`.
  if (const auto *UO = dyn_cast<UnaryOperator>(Ptr)) {
    if (UO->getOpcode() != UnaryOperator::Opcode::UO_AddrOf)
      return nullptr;
    return UO->getSubExpr()->IgnoreParenImpCasts();
  }

  // `std::addressof(X)` where `X` is an `Expr`.
  if (const auto *CE = dyn_cast<CallExpr>(Ptr)) {
    const FunctionDecl *FnDecl = CE->getDirectCallee();
    if (!FnDecl || !FnDecl->isInStdNamespace() ||
        FnDecl->getNameAsString() != "addressof" || CE->getNumArgs() != 1)
      return nullptr;
    return CE->getArg(0)->IgnoreParenImpCasts();
  }

  return nullptr;
}

// Given an expression like `sizeof(X)`, returns the `Expr` corresponding to `X`
// (after removing parens and implicit casts). Returns null if the expression
// `E` is not a `sizeof` expression or is `sizeof(T)` for a type `T`.
static const Expr *getSubExprInSizeOfExpr(const Expr &E) {
  const auto *SizeOfExpr =
      dyn_cast<UnaryExprOrTypeTraitExpr>(E.IgnoreParenImpCasts());
  if (!SizeOfExpr || SizeOfExpr->getKind() != UETT_SizeOf)
    return nullptr;
  if (SizeOfExpr->isArgumentType())
    return nullptr;
  return SizeOfExpr->getArgumentExpr()->IgnoreParenImpCasts();
}

// Providing that `Ptr` is a pointer and `Size` is an unsigned-integral
// expression, returns true iff they follow one of the following safe
// patterns:
//  1. Ptr is `DRE.data()` and Size is `DRE.size()`, where DRE is a hardened
//     container or view;
//
//  2. Ptr is `a` and Size is `n`, where `a` is of an array-of-T with constant
//     size `n`;
//
//  3. Ptr is `&var` and Size is `1`; or
//     Ptr is `std::addressof(...)` and Size is `1`;
//
//  4. Size is `0`;
static bool isPtrBufferSafe(const Expr *Ptr, const Expr *Size,
                            ASTContext &Ctx) {
  // Pattern 1:
  if (auto *MCEPtr = dyn_cast<CXXMemberCallExpr>(Ptr->IgnoreParenImpCasts()))
    if (auto *MCESize =
            dyn_cast<CXXMemberCallExpr>(Size->IgnoreParenImpCasts())) {
      auto *DREOfPtr = dyn_cast<DeclRefExpr>(
          MCEPtr->getImplicitObjectArgument()->IgnoreParenImpCasts());
      auto *DREOfSize = dyn_cast<DeclRefExpr>(
          MCESize->getImplicitObjectArgument()->IgnoreParenImpCasts());

      if (!DREOfPtr || !DREOfSize)
        return false; // not in safe pattern
      // We need to make sure 'a' is identical to 'b' for 'a.data()' and
      // 'b.size()' otherwise we do not know they match:
      if (DREOfPtr->getDecl() != DREOfSize->getDecl())
        return false;
      if (MCEPtr->getMethodDecl()->getName() != "data")
        return false;
      // `MCEPtr->getRecordDecl()` must be non-null as `DREOfPtr` is non-null:
      if (!MCEPtr->getRecordDecl()->isInStdNamespace())
        return false;

      auto *ObjII = MCEPtr->getRecordDecl()->getIdentifier();

      if (!ObjII)
        return false;

      bool AcceptSizeBytes = Ptr->getType()->getPointeeType()->isCharType();

      if (!((AcceptSizeBytes &&
             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"))
        return false;

      return llvm::is_contained({SIZED_CONTAINER_OR_VIEW_LIST},
                                ObjII->getName());
    }

  Expr::EvalResult ER;

  // Pattern 2-4:
  if (Size->EvaluateAsInt(ER, Ctx)) {
    // Pattern 2:
    if (auto *DRE = dyn_cast<DeclRefExpr>(Ptr->IgnoreParenImpCasts())) {
      if (auto *CAT = Ctx.getAsConstantArrayType(DRE->getType())) {
        llvm::APSInt SizeInt = ER.Val.getInt();

        return llvm::APSInt::compareValues(
                   SizeInt, llvm::APSInt(CAT->getSize(), true)) == 0;
      }
      return false;
    }

    // Pattern 3:
    if (ER.Val.getInt().isOne() && getSubExprInAddressOfExpr(*Ptr) != nullptr)
      return true;

    // Pattern 4:
    if (ER.Val.getInt().isZero())
      return true;
  }

  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>{ (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.
//   4. `std::span<T>{x.begin(), x.end()}` where `x` is an object in the
//      SIZED_CONTAINER_OR_VIEW_LIST.
//   5. `isPtrBufferSafe` returns true for the two arguments of the span
//      constructor
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-2:
  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;
  default:
    break;
  }

  // Check form 3:
  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);
        }
    }
  }
  // Check form 4:
  auto IsMethodCallToSizedObject = [](const Stmt *Node, StringRef MethodName) {
    if (const auto *MC = dyn_cast<CXXMemberCallExpr>(Node)) {
      const auto *MD = MC->getMethodDecl();
      const auto *RD = MC->getRecordDecl();

      if (RD && MD)
        if (auto *II = RD->getDeclName().getAsIdentifierInfo();
            II && RD->isInStdNamespace())
          return llvm::is_contained({SIZED_CONTAINER_OR_VIEW_LIST},
                                    II->getName()) &&
                 MD->getName() == MethodName;
    }
    return false;
  };

  if (IsMethodCallToSizedObject(Arg0, "begin") &&
      IsMethodCallToSizedObject(Arg1, "end"))
    return AreSameDRE(
        // We know Arg0 and Arg1 are `CXXMemberCallExpr`s:
        cast<CXXMemberCallExpr>(Arg0)
            ->getImplicitObjectArgument()
            ->IgnoreParenImpCasts(),
        cast<CXXMemberCallExpr>(Arg1)
            ->getImplicitObjectArgument()
            ->IgnoreParenImpCasts());

  // Check 5:
  return isPtrBufferSafe(Arg0, Arg1, Ctx);
}

static bool isSafeStringViewTwoParamConstruct(const CXXConstructExpr &Node,
                                              ASTContext &Ctx) {
  const Expr *Arg0 = Node.getArg(0)->IgnoreParenImpCasts();
  const Expr *Arg1 = Node.getArg(1)->IgnoreParenImpCasts();

  // Pattern 1: String Literals
  if (const auto *SL = dyn_cast<StringLiteral>(Arg0)) {
    if (auto ArgSize = Arg1->getIntegerConstantExpr(Ctx)) {
      if (llvm::APSInt::compareValues(
              llvm::APSInt::getUnsigned(SL->getLength()), *ArgSize) >= 0)
        return true;
      return false; // Explicitly unsafe if size > length
    }
  }

  // Pattern 2: Constant Arrays
  if (const auto *CAT = Ctx.getAsConstantArrayType(Arg0->getType())) {
    if (auto ArgSize = Arg1->getIntegerConstantExpr(Ctx)) {
      if (llvm::APSInt::compareValues(llvm::APSInt(CAT->getSize(), true),
                                      *ArgSize) >= 0)
        return true;
      return false; // Explicitly unsafe if size > ArraySize
    }
  }

  // Pattern 3: Zero length
  if (auto Val = Arg1->getIntegerConstantExpr(Ctx)) {
    if (Val->isZero())
      return true;
  }

  // Pattern 4: string_view(it, it) - Only safe if it's .begin() and .end() of
  // the SAME object
  auto GetContainerObj = [](const Expr *E) -> const Expr * {
    E = E->IgnoreParenImpCasts();
    if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(E)) {
      const auto *MD = MCE->getMethodDecl();
      if (MD && MD->getIdentifier())
        if (MD->getName() == "begin" || MD->getName() == "end")
          return MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
    }
    return nullptr;
  };

  const Expr *Obj0 = GetContainerObj(Arg0);
  const Expr *Obj1 = GetContainerObj(Arg1);

  if (Obj0 && Obj1) {
    const auto *DRE0 = dyn_cast<DeclRefExpr>(Obj0);
    const auto *DRE1 = dyn_cast<DeclRefExpr>(Obj1);

    // If both are references to variables, they MUST point to the same
    // declaration.
    if (DRE0 && DRE1) {
      if (DRE0->getDecl()->getCanonicalDecl() ==
          DRE1->getDecl()->getCanonicalDecl())
        return true;
    }

    // If they aren't both DeclRefExprs or don't match, we DO NOT return true.
    // This ensures v1.begin(), v2.end() triggers a warning.
  }

  return false; // Default to unsafe
}

static bool isSafeArraySubscript(const ArraySubscriptExpr &Node,
                                 const ASTContext &Ctx,
                                 const bool IgnoreStaticSizedArrays) {
  // 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;
  }

  if (IgnoreStaticSizedArrays) {
    // If we made it here, it means a size was found for the var being accessed
    // (either string literal or array). If it's fixed size, we can ignore it.
    return true;
  }

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

static bool isSafePointerArithmetic(const Expr *Ptr, const Expr *OffsetExpr,
                                    BinaryOperatorKind Opcode,
                                    const ASTContext &Ctx) {
  Expr::EvalResult EVResult;

  if (OffsetExpr->isValueDependent() ||
      !OffsetExpr->EvaluateAsInt(EVResult, Ctx)) {
    // Dynamic offsets are not safe.
    return false;
  }

  uint64_t limit = 0;
  const Expr *Base = Ptr->IgnoreParenImpCasts();

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

  llvm::APSInt OffsetVal = EVResult.Val.getInt();
  if (Opcode == BO_Sub)
    OffsetVal = -OffsetVal;

  // If the offset is a constant, and it is within the bounds of the
  // array, then it is safe.
  return OffsetVal.isNonNegative() && OffsetVal.getLimitedValue() < limit;
}

// Constant fold a conditional expression 'cond ? A : B' to
// - 'A', if 'cond' has constant true value;
// - 'B', if 'cond' has constant false value.
static const Expr *tryConstantFoldConditionalExpr(const Expr *E,
                                                  const ASTContext &Ctx) {
  // FIXME: more places can use this function
  if (const auto *CE = dyn_cast<ConditionalOperator>(E)) {
    bool CondEval;
    const auto *Cond = CE->getCond();

    if (!Cond->isValueDependent() &&
        Cond->EvaluateAsBooleanCondition(CondEval, Ctx))
      return CondEval ? CE->getLHS() : CE->getRHS();
  }
  return E;
}

// 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, ASTContext &Ctx) {
  // Strip CXXDefaultArgExpr before check:
  Ptr = Ptr->IgnoreParenImpCasts();
  if (const auto *DefaultArgE = dyn_cast<CXXDefaultArgExpr>(Ptr))
    Ptr = DefaultArgE->getExpr()->IgnoreParenImpCasts();
  // Try to perform constant fold recursively:
  if (const auto *NewPtr = tryConstantFoldConditionalExpr(Ptr, Ctx);
      NewPtr != Ptr)
    return isNullTermPointer(NewPtr, Ctx);
  // Split the analysis for conditional expressions that cannot be
  // constant-folded:
  if (const auto *CondE = dyn_cast<ConditionalOperator>(Ptr)) {
    return isNullTermPointer(CondE->getLHS(), Ctx) &&
           isNullTermPointer(CondE->getRHS(), Ctx);
  }

  if (isa<clang::StringLiteral>(Ptr))
    return true;
  if (isa<PredefinedExpr>(Ptr))
    return true;
  if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Ptr)) {
    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;
  }

  // Functions known to return properly null terminated strings.
  static const llvm::StringSet<> NullTermFunctions = {"strerror"};
  if (auto *CE = dyn_cast<CallExpr>(Ptr)) {
    const FunctionDecl *F = CE->getDirectCallee();
    if (F && F->getIdentifier() && NullTermFunctions.contains(F->getName()))
      return true;
  }
  return false;
}

// Under `libc_func_matchers`, define a set of matchers that match unsafe
// functions in libc and unsafe calls to them.
namespace libc_func_matchers {
//  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
//
static StringRef matchLibcName(StringRef Name) {
  if (Name.ends_with("_s"))
    return Name.drop_back(2 /* truncate "_s" */);
  return Name;
}

// Parameter `Name` is the substring after stripping off the prefix
// "__builtin_".
static 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);
}

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

// 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.
//
// Format arguments start at `FmtIdx` + 1, if `FmtArgIdx` is insignificant.
static bool
hasUnsafeFormatOrSArg(ASTContext &Ctx, const CallExpr *Call,
                      const Expr *&UnsafeArg, const unsigned FmtIdx,
                      std::optional<const unsigned> FmtArgIdx = std::nullopt,
                      bool isKprintf = false) {
  class StringFormatStringHandler
      : public analyze_format_string::FormatStringHandler {
    const CallExpr *Call;
    unsigned FmtArgIdx;
    const Expr *&UnsafeArg;
    ASTContext &Ctx;
    bool UnsafeArgSet;

    // Returns an `Expr` representing the precision if specified, null
    // otherwise.
    // The parameter `Call` is a printf call and the parameter `Precision` is
    // the precision of a format specifier of the `Call`.
    //
    // For example, for the `printf("%d, %.10s", 10, p)` call
    // `Precision` can be the precision of either "%d" or "%.10s". The former
    // one will have `NotSpecified` kind.
    const Expr *
    getPrecisionAsExpr(const analyze_printf::OptionalAmount &Precision,
                       const CallExpr *Call) {
      if (Precision.hasDataArgument()) {
        unsigned PArgIdx = Precision.getArgIndex() + FmtArgIdx;

        if (PArgIdx < Call->getNumArgs()) {
          const Expr *PArg = Call->getArg(PArgIdx);

          // Strip the cast if `PArg` is a cast-to-int expression:
          if (auto *CE = dyn_cast<CastExpr>(PArg);
              CE && CE->getType()->isSignedIntegerType())
            PArg = CE->getSubExpr();
          return PArg;
        }
      }
      if (Precision.getHowSpecified() ==
          analyze_printf::OptionalAmount::HowSpecified::Constant) {
        auto SizeTy = Ctx.getSizeType();
        llvm::APSInt PArgVal = llvm::APSInt(
            llvm::APInt(Ctx.getTypeSize(SizeTy), Precision.getConstantAmount()),
            true);

        return IntegerLiteral::Create(Ctx, PArgVal, Ctx.getSizeType(), {});
      }
      return nullptr;
    }

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

    bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
                               const char *startSpecifier,
                               unsigned specifierLen,
                               const TargetInfo &Target) override {
      if (FS.getConversionSpecifier().getKind() !=
          analyze_printf::PrintfConversionSpecifier::sArg)
        return true; // continue parsing

      unsigned ArgIdx = FS.getArgIndex() + FmtArgIdx;

      if (ArgIdx >= Call->getNumArgs())
        // If the `ArgIdx` is invalid, give up.
        return true; // continue parsing

      const Expr *Arg = Call->getArg(ArgIdx);

      if (isNullTermPointer(Arg, Ctx))
        // If Arg is a null-terminated pointer, it is safe anyway.
        return true; // continue parsing

      // Otherwise, check if the specifier has a precision and if the character
      // pointer is safely bound by the precision:
      auto LengthModifier = FS.getLengthModifier();
      QualType ArgType = Arg->getType();
      bool IsArgTypeValid = // Is ArgType a character pointer type?
          ArgType->isPointerType() &&
          (LengthModifier.getKind() == LengthModifier.AsWideChar
               ? ArgType->getPointeeType()->isWideCharType()
               : ArgType->getPointeeType()->isCharType());

      if (auto *Precision = getPrecisionAsExpr(FS.getPrecision(), Call);
          Precision && IsArgTypeValid)
        if (isPtrBufferSafe(Arg, Precision, Ctx))
          return true;
      // Handle unsafe case:
      UnsafeArg = Call->getArg(ArgIdx); // output
      UnsafeArgSet = true;
      return false; // returning false stops parsing immediately
    }

    bool isUnsafeArgSet() { return UnsafeArgSet; }
  };

  const Expr *Fmt = Call->getArg(FmtIdx);
  unsigned FmtArgStartingIdx =
      FmtArgIdx.has_value() ? static_cast<unsigned>(*FmtArgIdx) : FmtIdx + 1;

  if (auto *SL = dyn_cast<clang::StringLiteral>(Fmt->IgnoreParenImpCasts())) {
    if (SL->getCharByteWidth() == 1) {
      StringRef FmtStr = SL->getString();
      StringFormatStringHandler Handler(Call, FmtArgStartingIdx, UnsafeArg,
                                        Ctx);

      return analyze_format_string::ParsePrintfString(
                 Handler, FmtStr.begin(), FmtStr.end(), Ctx.getLangOpts(),
                 Ctx.getTargetInfo(), isKprintf) &&
             Handler.isUnsafeArgSet();
    }

    if (auto FmtStr = SL->tryEvaluateString(Ctx)) {
      StringFormatStringHandler Handler(Call, FmtArgStartingIdx, UnsafeArg,
                                        Ctx);
      return analyze_format_string::ParsePrintfString(
                 Handler, FmtStr->data(), FmtStr->data() + FmtStr->size(),
                 Ctx.getLangOpts(), Ctx.getTargetInfo(), isKprintf) &&
             Handler.isUnsafeArgSet();
    }
  }
  // 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() + FmtIdx, Call->arg_end()),
      [&UnsafeArg, &Ctx](const Expr *Arg) -> bool {
        if (Arg->getType()->isPointerType() && !isNullTermPointer(Arg, Ctx)) {
          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 `matchName()`.
//  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 const std::set<StringRef> PredefinedNames = {
      // 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",
      "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 = matchName(II->getName(), Node.getBuiltinID());

  // Match predefined names:
  if (PredefinedNames.count(Name))
    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.count(NameWCS))
    return true;
  // All `scanf` functions are unsafe (including `sscanf`, `vsscanf`, etc.. They
  // all should end with "scanf"):
  return Name.ends_with("scanf");
}

// Returns true if this is an unsafe call to `memset`.
// The only call we currently consider safe is of the form
// `memset(&x, 0, sizeof(x))`, with possible variations in parentheses.
static bool isUnsafeMemset(const CallExpr &Node, ASTContext &Ctx) {
  const FunctionDecl *FD = Node.getDirectCallee();
  assert(FD && "It should have been checked that FD is non-null.");

  const IdentifierInfo *II = FD->getIdentifier();
  if (!II)
    return false;

  StringRef Name = matchName(II->getName(), FD->getBuiltinID());
  if (Name != "memset")
    return false;

  // We currently only handle the basic forms of `memset` with 3 parameters.
  // There is also `__builtin___memset_chk()` which takes a 4th `destlen`
  // parameter for bounds checking, but we don't consider its safe forms yet.
  // https://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/libc---memset-chk-1.html
  if (FD->getNumParams() != 3)
    return true;

  // Now we have a known version of `memset`, consider it unsafe unless it's in
  // the form `memset(&x, 0, sizeof(x))`.
  const auto *AddressOfVar = dyn_cast_if_present<DeclRefExpr>(
      getSubExprInAddressOfExpr(*Node.getArg(0)));
  if (!AddressOfVar)
    return true;

  const auto *SizeOfVar =
      dyn_cast_if_present<DeclRefExpr>(getSubExprInSizeOfExpr(*Node.getArg(2)));
  if (!SizeOfVar)
    return true;

  return AddressOfVar->getDecl() != SizeOfVar->getDecl();
}

// 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 = matchName(II->getName(), Node.getBuiltinID());

  return Name.starts_with("v") && Name.ends_with("printf");
}

// 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 = matchName(II->getName(), Node.getBuiltinID());

  return Name == "sprintf" || Name == "swprintf";
}

// 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 = matchName(II->getName(), Node.getBuiltinID());

  if (!Name.ends_with("printf"))
    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(Ctx, &Node, UnsafeArg, /* FmtIdx= */ 1)) {
      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(Ctx, &Node, UnsafeArg, /* FmtIdx= */ 0,
                              /* FmtArgIdx= */ std::nullopt, 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(Ctx, &Node, UnsafeArg, /* FmtIdx= */ 2)) {
        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, Ctx)) {
      Result.addNode(Tag, DynTypedNode::create(*Arg));
      return true;
    }
  return false;
}

// This function requires that it is known that the callee `isNormalPrintf`.
// It returns true iff the first two arguments of the call is a pointer
// `Ptr` and an unsigned integer `Size` and they are NOT safe, i.e.,
// `!isPtrBufferSafe(Ptr, Size)`.
static bool hasUnsafeSnprintfBuffer(const CallExpr &Node, 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() || !FirstPteTy->isAnyCharacterType() ||
      !Buf->getType()->isPointerType() ||
      !Size->getType()->isUnsignedIntegerType())
    return false; // not an snprintf call

  return !isPtrBufferSafe(Buf, Size, Ctx);
}
} // 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);
}

// Returns true for RecordDecl of type std::unique_ptr<T[]>
static bool isUniquePtrArray(const CXXRecordDecl *RecordDecl) {
  if (!RecordDecl || !RecordDecl->isInStdNamespace() ||
      RecordDecl->getNameAsString() != "unique_ptr")
    return false;

  const ClassTemplateSpecializationDecl *class_template_specialization_decl =
      dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
  if (!class_template_specialization_decl)
    return false;

  const TemplateArgumentList &template_args =
      class_template_specialization_decl->getTemplateArgs();
  if (template_args.size() == 0)
    return false;

  const TemplateArgument &first_arg = template_args[0];
  if (first_arg.getKind() != TemplateArgument::Type)
    return false;

  QualType referred_type = first_arg.getAsType();
  return referred_type->isArrayType();
}

class UniquePtrArrayAccessGadget : public WarningGadget {
private:
  static constexpr const char *const AccessorTag = "unique_ptr_array_access";
  const CXXOperatorCallExpr *AccessorExpr;

public:
  UniquePtrArrayAccessGadget(const MatchResult &Result)
      : WarningGadget(Kind::UniquePtrArrayAccess),
        AccessorExpr(Result.getNodeAs<CXXOperatorCallExpr>(AccessorTag)) {
    assert(AccessorExpr &&
           "UniquePtrArrayAccessGadget requires a matched CXXOperatorCallExpr");
  }

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

  static bool matches(const Stmt *S, const ASTContext &Ctx,
                      MatchResult &Result) {

    const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(S);
    if (!OpCall || OpCall->getOperator() != OO_Subscript)
      return false;

    const Expr *Callee = OpCall->getCallee()->IgnoreParenImpCasts();
    if (!Callee)
      return false;

    const CXXMethodDecl *Method =
        dyn_cast_or_null<CXXMethodDecl>(OpCall->getDirectCallee());
    if (!Method)
      return false;

    if (Method->getOverloadedOperator() != OO_Subscript)
      return false;

    const CXXRecordDecl *RecordDecl = Method->getParent();
    if (!isUniquePtrArray(RecordDecl))
      return false;

    const Expr *IndexExpr = OpCall->getArg(1);
    clang::Expr::EvalResult Eval;

    // Allow [0]
    if (IndexExpr->EvaluateAsInt(Eval, Ctx) && Eval.Val.getInt().isZero())
      return false;

    Result.addNode(AccessorTag, DynTypedNode::create(*OpCall));
    return true;
  }
  void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
                             bool IsRelatedToDecl,
                             ASTContext &Ctx) const override {
    Handler.handleUnsafeUniquePtrArrayAccess(
        DynTypedNode::create(*AccessorExpr), IsRelatedToDecl, Ctx);
  }

  SourceLocation getSourceLoc() const override {
    if (AccessorExpr)
      return AccessorExpr->getOperatorLoc();
    return SourceLocation();
  }

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

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,
                      const UnsafeBufferUsageHandler *Handler,
                      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,
            Handler->ignoreUnsafeBufferInStaticSizedArray(S->getBeginLoc())))
      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,
                      const UnsafeBufferUsageHandler *Handler,
                      MatchResult &Result) {
    const auto *BO = dyn_cast<BinaryOperator>(S);
    if (!BO)
      return false;
    const auto *LHS = BO->getLHS();
    const auto *RHS = BO->getRHS();

    const Expr *Ptr = nullptr;
    const Expr *OffsetExpr = nullptr;

    // 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())) {
        Ptr = LHS;
        OffsetExpr = RHS;
      }
    }
    // ptr at right
    if (BO->getOpcode() == BO_Add && hasPointerType(*RHS) &&
        (LHS->getType()->isIntegerType() || LHS->getType()->isEnumeralType())) {
      Ptr = RHS;
      OffsetExpr = LHS;
    }

    if (!Ptr || !OffsetExpr)
      return false;

    // If -Wno-unsafe-buffer-usage-in-static-sized-array is used, suppress
    // warnings for guaranteed safe pointer arithmetic.
    if (Handler->ignoreUnsafeBufferInStaticSizedArray(S->getBeginLoc()) &&
        isSafePointerArithmetic(Ptr, OffsetExpr, BO->getOpcode(), Ctx)) {
      return false;
    }

    // Default: warn on all pointer arithmetic
    Result.addNode(PointerArithmeticPointerTag, DynTypedNode::create(*Ptr));
    Result.addNode(PointerArithmeticTag, DynTypedNode::create(*BO));
    return true;
  }

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

class StringViewTwoParamConstructorGadget : public WarningGadget {
  static constexpr const char *const StringViewTwoParamConstructorTag =
      "stringViewTwoParamConstructor";
  const CXXConstructExpr *Ctor; // the string_view constructor expression

public:
  StringViewTwoParamConstructorGadget(const MatchResult &Result)
      : WarningGadget(Kind::StringViewTwoParamConstructor),
        Ctor(Result.getNodeAs<CXXConstructExpr>(
            StringViewTwoParamConstructorTag)) {}

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

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

    // MATCH: std::basic_string_view
    bool IsStringView =
        CRecordDecl->isInStdNamespace() &&
        CDecl->getDeclName().getAsString() == "basic_string_view" &&
        CE->getNumArgs() == 2;

    if (!IsStringView || isSafeStringViewTwoParamConstruct(*CE, Ctx))
      return false;

    Result.addNode(StringViewTwoParamConstructorTag, 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.handleUnsafeOperationInStringView(Ctor, IsRelatedToDecl, Ctx);
  }

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

  DeclUseList getClaimedVarUseSites() const override {
    // If the constructor call is of the form `std::string_view{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() &&
        llvm::is_contained({SIZED_CONTAINER_OR_VIEW_LIST},
                           method->getParent()->getName()))
      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";

public:
  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
    FORMAT_ATTR = 8, // flag: the callee has the format attribute
  } WarnedFunKind = OTHERS;

  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;
    const auto *CE = dyn_cast<CallExpr>(S);
    if (!CE)
      return false;
    const auto *FD = CE->getDirectCallee();
    if (!FD)
      return false;

    const bool IsGlobalAndNotInAnyNamespace =
        FD->isGlobal() && !FD->getEnclosingNamespaceContext()->isNamespace();

    // A libc function must either be in the std:: namespace or a global
    // function that is not in any namespace:
    if (!FD->isInStdNamespace() && !IsGlobalAndNotInAnyNamespace)
      return false;
    // If the call has a sole null-terminated argument, e.g., strlen,
    //  printf, atoi, we consider it safe:
    if (CE->getNumArgs() == 1 && isNullTermPointer(CE->getArg(0), Ctx))
      return false;

    const bool isSingleStringLiteralArg =
        CE->getNumArgs() == 1 &&
        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::isUnsafeMemset(*CE, Ctx)) {
        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 {}; }
};

class UnsafeFormatAttributedFunctionCallGadget : public WarningGadget {
  const CallExpr *const Call;
  const Expr *UnsafeArg = nullptr;
  constexpr static const char *const Tag = "UnsafeFormatAttributedFunctionCall";
  constexpr static const char *const UnsafeStringTag =
      "UnsafeFormatAttributedFunctionCall_string";

public:
  UnsafeFormatAttributedFunctionCallGadget(const MatchResult &Result)
      : WarningGadget(Kind::UnsafeLibcFunctionCall),
        Call(Result.getNodeAs<CallExpr>(Tag)),
        UnsafeArg(Result.getNodeAs<Expr>(UnsafeStringTag)) {}

  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 FunctionDecl *FD = CE->getDirectCallee();
    if (!FD)
      return false;

    const FormatAttr *Attr = nullptr;
    bool IsPrintf = false;
    bool AnyAttr = llvm::any_of(
        FD->specific_attrs<FormatAttr>(),
        [&Attr, &IsPrintf](const FormatAttr *FA) -> bool {
          if (const auto *II = FA->getType()) {
            if (II->getName() == "printf" || II->getName() == "scanf") {
              Attr = FA;
              IsPrintf = II->getName() == "printf";
              return true;
            }
          }
          return false;
        });
    const Expr *UnsafeArg;

    if (!AnyAttr)
      return false;

    // FormatAttribute indexes are 1-based:
    unsigned FmtIdx = Attr->getFormatIdx() - 1;
    std::optional<unsigned> FmtArgIdx = Attr->getFirstArg() - 1;

    if (isa<CXXMemberCallExpr>(CE)) {
      // For CXX member calls, attribute parameters are specified as if there is
      // an implicit "this".  The implicit "this" is invisible through CallExpr
      // `CE`. (What makes it even less ergonomic is that the
      //  implicit "this" is visible through CallExpr `CE` for CXX operator
      //  calls!)
      --FmtIdx;
      --*FmtArgIdx;
    } else if (CE->getStmtClass() != Stmt::CallExprClass &&
               !isa<CXXOperatorCallExpr>(CE))
      return false; // Ignore unsupported CallExpr subclasses
    if (*FmtArgIdx >= CE->getNumArgs())
      // Format arguments are allowed to be absent when variadic parameter is
      // used.  So we need to check if those arguments exist. Moreover, when
      // variadic parameter is NOT used, `Attr->getFirstArg()` could be an
      // out-of-bound value. E.g.,
      // clang does not complain about `__attribute__((__format__(__printf__, 2,
      // 99))) void f(int, char *);`.
      FmtArgIdx = std::nullopt;

    if (AnyAttr && !IsPrintf && FmtArgIdx) {
      // For scanf-like functions, any format argument is considered unsafe:
      Result.addNode(Tag, DynTypedNode::create(*CE));
      return true;
    }
    // For printf-like functions:
    if (AnyAttr && libc_func_matchers::hasUnsafeFormatOrSArg(
                       Ctx, CE, UnsafeArg, FmtIdx, FmtArgIdx)) {
      Result.addNode(Tag, DynTypedNode::create(*CE));
      Result.addNode(UnsafeStringTag, DynTypedNode::create(*UnsafeArg));
      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 {
    if (UnsafeArg)
      Handler.handleUnsafeLibcCall(
          Call,
          UnsafeLibcFunctionCallGadget::UnsafeKind::STRING |
              UnsafeLibcFunctionCallGadget::UnsafeKind::FORMAT_ATTR,
          Ctx, UnsafeArg);
    else
      Handler.handleUnsafeLibcCall(
          Call,
          UnsafeLibcFunctionCallGadget::UnsafeKind::OTHERS |
              UnsafeLibcFunctionCallGadget::UnsafeKind::FORMAT_ATTR,
          Ctx);
  }

  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 Expr *CE = 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::SmallPtrSet<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();
  }
};

// Populate `Stmts` with the body/initializer Stmt of `D`, if `D` is one of the
// followings:
//   VarDecl
//   FieldDecl
//   FunctionDecl
//   BlockDecl
//   ObjCMethodDecl
static void populateStmtsForFindingGadgets(SmallVector<const Stmt *> &Stmts,
                                           const Decl *D) {
  auto AddStmt = [&Stmts](const Stmt *S) {
    if (S)
      Stmts.push_back(S);
  };
  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
    AddStmt(FD->getBody());
    for (const auto *PD : FD->parameters())
      if (PD->hasDefaultArg() && !PD->hasUninstantiatedDefaultArg())
        AddStmt(PD->getDefaultArg());
    if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(FD))
      llvm::append_range(
          Stmts, llvm::map_range(CtorD->inits(),
                                 std::mem_fn(&CXXCtorInitializer::getInit)));
  } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
    AddStmt(D->getBody());
  } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
    AddStmt(VD->getInit()); // FIXME: default arg for ParmVarDecl?
  } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
    AddStmt(FD->getInClassInitializer());
  }
}

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);
  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
    // Consteval functions are free of UB by the spec, so we don't need to
    // visit them or produce diagnostics.
    if (FD->isConsteval())
      return;
    // 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;
      }
    }
  }

  SmallVector<const Stmt *> Stmts;

  populateStmtsForFindingGadgets(Stmts, D);

  assert(!Stmts.empty());

  FixableGadgetList FixableGadgets;
  WarningGadgetList WarningGadgets;
  DeclUseTracker Tracker;
  for (const 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);
}

bool clang::matchUnsafePointers(const DynTypedNode &N, ASTContext &Ctx,
                                std::set<const Expr *> &UnsafePointers) {
  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 handleUnsafeOperationInStringView(const Stmt *, bool,
                                           ASTContext &) override {}
    void handleUnsafeVariableGroup(const VarDecl *,
                                   const VariableGroupsManager &, FixItList &&,
                                   const Decl *,
                                   const FixitStrategy &) override {}
    void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node,
                                          bool IsRelatedToDecl,
                                          ASTContext &Ctx) override {}
    bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
      return false;
    }
    bool isSafeBufferOptOut(const SourceLocation &) const override {
      return false;
    }
    bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override {
      return false;
    }
    bool ignoreUnsafeBufferInStaticSizedArray(
        const SourceLocation &Loc) const override {
      return false;
    }
    std::string getUnsafeBufferUsageAttributeTextAt(
        SourceLocation, StringRef WSSuffix = "") const override {
      return "";
    }
  } Handler;

  const Stmt *S = N.get<Stmt>();
  if (!S)
    return false;

  MatchResult Result;
  WarningGadgetList WarningGadgets;
  bool Matched = false;

  // FIXME: By design, we don't need MockReporter, and we are supposed to
  // only define WARNING_GADGET when we want to treat WARNING_OPTIONAL_GADGET
  // the same as WARNING_GADGET. The reason we have to do it this way now is
  // that some WARNING_OPTIONAL_GADGETs do not have the 3-argument `matches`
  // overload. We need to fix this problem in a separate patch.

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

  for (auto &WG : WarningGadgets)
    for (auto *E : WG->getUnsafePtrs()) {
      UnsafePointers.insert(E);
      Matched = true;
    }
  return Matched;
}
