//=== SemaFunctionEffects.cpp - Sema handling of function effects ---------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements Sema handling of function effects.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/SemaInternal.h"

#define DEBUG_TYPE "effectanalysis"

using namespace clang;

namespace {

enum class ViolationID : uint8_t {
  None = 0, // Sentinel for an empty Violation.
  // These first 5 map to a %select{} in one of several FunctionEffects
  // diagnostics, e.g. warn_func_effect_violation.
  BaseDiagnosticIndex,
  AllocatesMemory = BaseDiagnosticIndex,
  ThrowsOrCatchesExceptions,
  HasStaticLocalVariable,
  AccessesThreadLocalVariable,
  AccessesObjCMethodOrProperty,

  // These only apply to callees, where the analysis stops at the Decl.
  DeclDisallowsInference,

  // These both apply to indirect calls. The difference is that sometimes
  // we have an actual Decl (generally a variable) which is the function
  // pointer being called, and sometimes, typically due to a cast, we only
  // have an expression.
  CallsDeclWithoutEffect,
  CallsExprWithoutEffect,
};

// Information about the AST context in which a violation was found, so
// that diagnostics can point to the correct source.
class ViolationSite {
public:
  enum class Kind : uint8_t {
    Default, // Function body.
    MemberInitializer,
    DefaultArgExpr
  };

private:
  llvm::PointerIntPair<CXXDefaultArgExpr *, 2, Kind> Impl;

public:
  ViolationSite() = default;

  explicit ViolationSite(CXXDefaultArgExpr *E)
      : Impl(E, Kind::DefaultArgExpr) {}

  Kind kind() const { return static_cast<Kind>(Impl.getInt()); }
  CXXDefaultArgExpr *defaultArgExpr() const { return Impl.getPointer(); }

  void setKind(Kind K) { Impl.setPointerAndInt(nullptr, K); }
};

// Represents a violation of the rules, potentially for the entire duration of
// the analysis phase, in order to refer to it when explaining why a caller has
// been made unsafe by a callee. Can be transformed into either a Diagnostic
// (warning or a note), depending on whether the violation pertains to a
// function failing to be verifed as holding an effect vs. a function failing to
// be inferred as holding that effect.
struct Violation {
  FunctionEffect Effect;
  std::optional<FunctionEffect>
      CalleeEffectPreventingInference; // Only for certain IDs; can be nullopt.
  ViolationID ID = ViolationID::None;
  ViolationSite Site;
  SourceLocation Loc;
  const Decl *Callee =
      nullptr; // Only valid for ViolationIDs Calls{Decl,Expr}WithoutEffect.

  Violation(FunctionEffect Effect, ViolationID ID, ViolationSite VS,
            SourceLocation Loc, const Decl *Callee = nullptr,
            std::optional<FunctionEffect> CalleeEffect = std::nullopt)
      : Effect(Effect), CalleeEffectPreventingInference(CalleeEffect), ID(ID),
        Site(VS), Loc(Loc), Callee(Callee) {}

  unsigned diagnosticSelectIndex() const {
    return unsigned(ID) - unsigned(ViolationID::BaseDiagnosticIndex);
  }
};

enum class SpecialFuncType : uint8_t { None, OperatorNew, OperatorDelete };
enum class CallableType : uint8_t {
  // Unknown: probably function pointer.
  Unknown,
  Function,
  Virtual,
  Block
};

// Return whether a function's effects CAN be verified.
// The question of whether it SHOULD be verified is independent.
static bool functionIsVerifiable(const FunctionDecl *FD) {
  if (FD->isTrivial()) {
    // Otherwise `struct x { int a; };` would have an unverifiable default
    // constructor.
    return true;
  }
  return FD->hasBody();
}

static bool isNoexcept(const FunctionDecl *FD) {
  const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
  return FPT && (FPT->isNothrow() || FD->hasAttr<NoThrowAttr>());
}

// This list is probably incomplete.
// FIXME: Investigate:
// __builtin_eh_return?
// __builtin_allow_runtime_check?
// __builtin_unwind_init and other similar things that sound exception-related.
// va_copy?
// coroutines?
static FunctionEffectKindSet getBuiltinFunctionEffects(unsigned BuiltinID) {
  FunctionEffectKindSet Result;

  switch (BuiltinID) {
  case 0:  // Not builtin.
  default: // By default, builtins have no known effects.
    break;

  // These allocate/deallocate heap memory.
  case Builtin::ID::BI__builtin_calloc:
  case Builtin::ID::BI__builtin_malloc:
  case Builtin::ID::BI__builtin_realloc:
  case Builtin::ID::BI__builtin_free:
  case Builtin::ID::BI__builtin_operator_delete:
  case Builtin::ID::BI__builtin_operator_new:
  case Builtin::ID::BIaligned_alloc:
  case Builtin::ID::BIcalloc:
  case Builtin::ID::BImalloc:
  case Builtin::ID::BImemalign:
  case Builtin::ID::BIrealloc:
  case Builtin::ID::BIfree:

  case Builtin::ID::BIfopen:
  case Builtin::ID::BIpthread_create:
  case Builtin::ID::BI_Block_object_dispose:
    Result.insert(FunctionEffect(FunctionEffect::Kind::Allocating));
    break;

  // These block in some other way than allocating memory.
  // longjmp() and friends are presumed unsafe because they are the moral
  // equivalent of throwing a C++ exception, which is unsafe.
  case Builtin::ID::BIlongjmp:
  case Builtin::ID::BI_longjmp:
  case Builtin::ID::BIsiglongjmp:
  case Builtin::ID::BI__builtin_longjmp:
  case Builtin::ID::BIobjc_exception_throw:

  // Objective-C runtime.
  case Builtin::ID::BIobjc_msgSend:
  case Builtin::ID::BIobjc_msgSend_fpret:
  case Builtin::ID::BIobjc_msgSend_fp2ret:
  case Builtin::ID::BIobjc_msgSend_stret:
  case Builtin::ID::BIobjc_msgSendSuper:
  case Builtin::ID::BIobjc_getClass:
  case Builtin::ID::BIobjc_getMetaClass:
  case Builtin::ID::BIobjc_enumerationMutation:
  case Builtin::ID::BIobjc_assign_ivar:
  case Builtin::ID::BIobjc_assign_global:
  case Builtin::ID::BIobjc_sync_enter:
  case Builtin::ID::BIobjc_sync_exit:
  case Builtin::ID::BINSLog:
  case Builtin::ID::BINSLogv:

  // stdio.h
  case Builtin::ID::BIfread:
  case Builtin::ID::BIfwrite:

  // stdio.h: printf family.
  case Builtin::ID::BIprintf:
  case Builtin::ID::BI__builtin_printf:
  case Builtin::ID::BIfprintf:
  case Builtin::ID::BIsnprintf:
  case Builtin::ID::BIsprintf:
  case Builtin::ID::BIvprintf:
  case Builtin::ID::BIvfprintf:
  case Builtin::ID::BIvsnprintf:
  case Builtin::ID::BIvsprintf:

  // stdio.h: scanf family.
  case Builtin::ID::BIscanf:
  case Builtin::ID::BIfscanf:
  case Builtin::ID::BIsscanf:
  case Builtin::ID::BIvscanf:
  case Builtin::ID::BIvfscanf:
  case Builtin::ID::BIvsscanf:
    Result.insert(FunctionEffect(FunctionEffect::Kind::Blocking));
    break;
  }

  return Result;
}

// Transitory, more extended information about a callable, which can be a
// function, block, or function pointer.
struct CallableInfo {
  // CDecl holds the function's definition, if any.
  // FunctionDecl if CallableType::Function or Virtual
  // BlockDecl if CallableType::Block
  const Decl *CDecl;

  // Remember whether the callable is a function, block, virtual method,
  // or (presumed) function pointer.
  CallableType CType = CallableType::Unknown;

  // Remember whether the callable is an operator new or delete function,
  // so that calls to them are reported more meaningfully, as memory
  // allocations.
  SpecialFuncType FuncType = SpecialFuncType::None;

  // We inevitably want to know the callable's declared effects, so cache them.
  FunctionEffectKindSet Effects;

  CallableInfo(const Decl &CD, SpecialFuncType FT = SpecialFuncType::None)
      : CDecl(&CD), FuncType(FT) {
    FunctionEffectsRef DeclEffects;
    if (auto *FD = dyn_cast<FunctionDecl>(CDecl)) {
      // Use the function's definition, if any.
      if (const FunctionDecl *Def = FD->getDefinition())
        CDecl = FD = Def;
      CType = CallableType::Function;
      if (auto *Method = dyn_cast<CXXMethodDecl>(FD);
          Method && Method->isVirtual())
        CType = CallableType::Virtual;
      DeclEffects = FD->getFunctionEffects();
    } else if (auto *BD = dyn_cast<BlockDecl>(CDecl)) {
      CType = CallableType::Block;
      DeclEffects = BD->getFunctionEffects();
    } else if (auto *VD = dyn_cast<ValueDecl>(CDecl)) {
      // ValueDecl is function, enum, or variable, so just look at its type.
      DeclEffects = FunctionEffectsRef::get(VD->getType());
    }
    Effects = FunctionEffectKindSet(DeclEffects);
  }

  CallableType type() const { return CType; }

  bool isCalledDirectly() const {
    return CType == CallableType::Function || CType == CallableType::Block;
  }

  bool isVerifiable() const {
    switch (CType) {
    case CallableType::Unknown:
    case CallableType::Virtual:
      return false;
    case CallableType::Block:
      return true;
    case CallableType::Function:
      return functionIsVerifiable(dyn_cast<FunctionDecl>(CDecl));
    }
    llvm_unreachable("undefined CallableType");
  }

  /// Generate a name for logging and diagnostics.
  std::string getNameForDiagnostic(Sema &S) const {
    std::string Name;
    llvm::raw_string_ostream OS(Name);

    if (auto *FD = dyn_cast<FunctionDecl>(CDecl))
      FD->getNameForDiagnostic(OS, S.getPrintingPolicy(),
                               /*Qualified=*/true);
    else if (auto *BD = dyn_cast<BlockDecl>(CDecl))
      OS << "(block " << BD->getBlockManglingNumber() << ")";
    else if (auto *VD = dyn_cast<NamedDecl>(CDecl))
      VD->printQualifiedName(OS);
    return Name;
  }
};

// ----------
// Map effects to single Violations, to hold the first (of potentially many)
// violations pertaining to an effect, per function.
class EffectToViolationMap {
  // Since we currently only have a tiny number of effects (typically no more
  // than 1), use a SmallVector with an inline capacity of 1. Since it
  // is often empty, use a unique_ptr to the SmallVector.
  // Note that Violation itself contains a FunctionEffect which is the key.
  // FIXME: Is there a way to simplify this using existing data structures?
  using ImplVec = llvm::SmallVector<Violation, 1>;
  std::unique_ptr<ImplVec> Impl;

public:
  // Insert a new Violation if we do not already have one for its effect.
  void maybeInsert(const Violation &Viol) {
    if (Impl == nullptr)
      Impl = std::make_unique<ImplVec>();
    else if (lookup(Viol.Effect) != nullptr)
      return;

    Impl->push_back(Viol);
  }

  const Violation *lookup(FunctionEffect Key) {
    if (Impl == nullptr)
      return nullptr;

    auto *Iter = llvm::find_if(
        *Impl, [&](const auto &Item) { return Item.Effect == Key; });
    return Iter != Impl->end() ? &*Iter : nullptr;
  }

  size_t size() const { return Impl ? Impl->size() : 0; }
};

// ----------
// State pertaining to a function whose AST is walked and whose effect analysis
// is dependent on a subsequent analysis of other functions.
class PendingFunctionAnalysis {
  friend class CompleteFunctionAnalysis;

public:
  struct DirectCall {
    const Decl *Callee;
    SourceLocation CallLoc;
    // Not all recursive calls are detected, just enough
    // to break cycles.
    bool Recursed = false;
    ViolationSite VSite;

    DirectCall(const Decl *D, SourceLocation CallLoc, ViolationSite VSite)
        : Callee(D), CallLoc(CallLoc), VSite(VSite) {}
  };

  // We always have two disjoint sets of effects to verify:
  // 1. Effects declared explicitly by this function.
  // 2. All other inferrable effects needing verification.
  FunctionEffectKindSet DeclaredVerifiableEffects;
  FunctionEffectKindSet EffectsToInfer;

private:
  // Violations pertaining to the function's explicit effects.
  SmallVector<Violation, 0> ViolationsForExplicitEffects;

  // Violations pertaining to other, non-explicit, inferrable effects.
  EffectToViolationMap InferrableEffectToFirstViolation;

  // These unverified direct calls are what keeps the analysis "pending",
  // until the callees can be verified.
  SmallVector<DirectCall, 0> UnverifiedDirectCalls;

public:
  PendingFunctionAnalysis(Sema &S, const CallableInfo &CInfo,
                          FunctionEffectKindSet AllInferrableEffectsToVerify)
      : DeclaredVerifiableEffects(CInfo.Effects) {
    // Check for effects we are not allowed to infer.
    FunctionEffectKindSet InferrableEffects;

    for (FunctionEffect effect : AllInferrableEffectsToVerify) {
      std::optional<FunctionEffect> ProblemCalleeEffect =
          effect.effectProhibitingInference(*CInfo.CDecl, CInfo.Effects);
      if (!ProblemCalleeEffect)
        InferrableEffects.insert(effect);
      else {
        // Add a Violation for this effect if a caller were to
        // try to infer it.
        InferrableEffectToFirstViolation.maybeInsert(Violation(
            effect, ViolationID::DeclDisallowsInference, ViolationSite{},
            CInfo.CDecl->getLocation(), nullptr, ProblemCalleeEffect));
      }
    }
    // InferrableEffects is now the set of inferrable effects which are not
    // prohibited.
    EffectsToInfer = FunctionEffectKindSet::difference(
        InferrableEffects, DeclaredVerifiableEffects);
  }

  // Hide the way that Violations for explicitly required effects vs. inferred
  // ones are handled differently.
  void checkAddViolation(bool Inferring, const Violation &NewViol) {
    if (!Inferring)
      ViolationsForExplicitEffects.push_back(NewViol);
    else
      InferrableEffectToFirstViolation.maybeInsert(NewViol);
  }

  void addUnverifiedDirectCall(const Decl *D, SourceLocation CallLoc,
                               ViolationSite VSite) {
    UnverifiedDirectCalls.emplace_back(D, CallLoc, VSite);
  }

  // Analysis is complete when there are no unverified direct calls.
  bool isComplete() const { return UnverifiedDirectCalls.empty(); }

  const Violation *violationForInferrableEffect(FunctionEffect effect) {
    return InferrableEffectToFirstViolation.lookup(effect);
  }

  // Mutable because caller may need to set a DirectCall's Recursing flag.
  MutableArrayRef<DirectCall> unverifiedCalls() {
    assert(!isComplete());
    return UnverifiedDirectCalls;
  }

  ArrayRef<Violation> getSortedViolationsForExplicitEffects(SourceManager &SM) {
    if (!ViolationsForExplicitEffects.empty())
      llvm::sort(ViolationsForExplicitEffects,
                 [&SM](const Violation &LHS, const Violation &RHS) {
                   return SM.isBeforeInTranslationUnit(LHS.Loc, RHS.Loc);
                 });
    return ViolationsForExplicitEffects;
  }

  void dump(Sema &SemaRef, llvm::raw_ostream &OS) const {
    OS << "Pending: Declared ";
    DeclaredVerifiableEffects.dump(OS);
    OS << ", " << ViolationsForExplicitEffects.size() << " violations; ";
    OS << " Infer ";
    EffectsToInfer.dump(OS);
    OS << ", " << InferrableEffectToFirstViolation.size() << " violations";
    if (!UnverifiedDirectCalls.empty()) {
      OS << "; Calls: ";
      for (const DirectCall &Call : UnverifiedDirectCalls) {
        CallableInfo CI(*Call.Callee);
        OS << " " << CI.getNameForDiagnostic(SemaRef);
      }
    }
    OS << "\n";
  }
};

// ----------
class CompleteFunctionAnalysis {
  // Current size: 2 pointers
public:
  // Has effects which are both the declared ones -- not to be inferred -- plus
  // ones which have been successfully inferred. These are all considered
  // "verified" for the purposes of callers; any issue with verifying declared
  // effects has already been reported and is not the problem of any caller.
  FunctionEffectKindSet VerifiedEffects;

private:
  // This is used to generate notes about failed inference.
  EffectToViolationMap InferrableEffectToFirstViolation;

public:
  // The incoming Pending analysis is consumed (member(s) are moved-from).
  CompleteFunctionAnalysis(ASTContext &Ctx, PendingFunctionAnalysis &&Pending,
                           FunctionEffectKindSet DeclaredEffects,
                           FunctionEffectKindSet AllInferrableEffectsToVerify)
      : VerifiedEffects(DeclaredEffects) {
    for (FunctionEffect effect : AllInferrableEffectsToVerify)
      if (Pending.violationForInferrableEffect(effect) == nullptr)
        VerifiedEffects.insert(effect);

    InferrableEffectToFirstViolation =
        std::move(Pending.InferrableEffectToFirstViolation);
  }

  const Violation *firstViolationForEffect(FunctionEffect Effect) {
    return InferrableEffectToFirstViolation.lookup(Effect);
  }

  void dump(llvm::raw_ostream &OS) const {
    OS << "Complete: Verified ";
    VerifiedEffects.dump(OS);
    OS << "; Infer ";
    OS << InferrableEffectToFirstViolation.size() << " violations\n";
  }
};

// ==========
class Analyzer {
  Sema &S;

  // Subset of Sema.AllEffectsToVerify
  FunctionEffectKindSet AllInferrableEffectsToVerify;

  using FuncAnalysisPtr =
      llvm::PointerUnion<PendingFunctionAnalysis *, CompleteFunctionAnalysis *>;

  // Map all Decls analyzed to FuncAnalysisPtr. Pending state is larger
  // than complete state, so use different objects to represent them.
  // The state pointers are owned by the container.
  class AnalysisMap : llvm::DenseMap<const Decl *, FuncAnalysisPtr> {
    using Base = llvm::DenseMap<const Decl *, FuncAnalysisPtr>;

  public:
    ~AnalysisMap();

    // Use non-public inheritance in order to maintain the invariant
    // that lookups and insertions are via the canonical Decls.

    FuncAnalysisPtr lookup(const Decl *Key) const {
      return Base::lookup(Key->getCanonicalDecl());
    }

    FuncAnalysisPtr &operator[](const Decl *Key) {
      return Base::operator[](Key->getCanonicalDecl());
    }

    /// Shortcut for the case where we only care about completed analysis.
    CompleteFunctionAnalysis *completedAnalysisForDecl(const Decl *D) const {
      if (FuncAnalysisPtr AP = lookup(D);
          isa_and_nonnull<CompleteFunctionAnalysis *>(AP))
        return cast<CompleteFunctionAnalysis *>(AP);
      return nullptr;
    }

    void dump(Sema &SemaRef, llvm::raw_ostream &OS) {
      OS << "\nAnalysisMap:\n";
      for (const auto &item : *this) {
        CallableInfo CI(*item.first);
        const auto AP = item.second;
        OS << item.first << " " << CI.getNameForDiagnostic(SemaRef) << " : ";
        if (AP.isNull()) {
          OS << "null\n";
        } else if (auto *CFA = dyn_cast<CompleteFunctionAnalysis *>(AP)) {
          OS << CFA << " ";
          CFA->dump(OS);
        } else if (auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP)) {
          OS << PFA << " ";
          PFA->dump(SemaRef, OS);
        } else
          llvm_unreachable("never");
      }
      OS << "---\n";
    }
  };
  AnalysisMap DeclAnalysis;

public:
  Analyzer(Sema &S) : S(S) {}

  void run(const TranslationUnitDecl &TU) {
    // Gather all of the effects to be verified to see what operations need to
    // be checked, and to see which ones are inferrable.
    for (FunctionEffect Effect : S.AllEffectsToVerify) {
      const FunctionEffect::Flags Flags = Effect.flags();
      if (Flags & FunctionEffect::FE_InferrableOnCallees)
        AllInferrableEffectsToVerify.insert(Effect);
    }
    LLVM_DEBUG(llvm::dbgs() << "AllInferrableEffectsToVerify: ";
               AllInferrableEffectsToVerify.dump(llvm::dbgs());
               llvm::dbgs() << "\n";);

    // We can use DeclsWithEffectsToVerify as a stack for a
    // depth-first traversal; there's no need for a second container. But first,
    // reverse it, so when working from the end, Decls are verified in the order
    // they are declared.
    SmallVector<const Decl *> &VerificationQueue = S.DeclsWithEffectsToVerify;
    std::reverse(VerificationQueue.begin(), VerificationQueue.end());

    while (!VerificationQueue.empty()) {
      const Decl *D = VerificationQueue.back();
      if (FuncAnalysisPtr AP = DeclAnalysis.lookup(D)) {
        if (auto *Pending = dyn_cast<PendingFunctionAnalysis *>(AP)) {
          // All children have been traversed; finish analysis.
          finishPendingAnalysis(D, Pending);
        }
        VerificationQueue.pop_back();
        continue;
      }

      // Not previously visited; begin a new analysis for this Decl.
      PendingFunctionAnalysis *Pending = verifyDecl(D);
      if (Pending == nullptr) {
        // Completed now.
        VerificationQueue.pop_back();
        continue;
      }

      // Analysis remains pending because there are direct callees to be
      // verified first. Push them onto the queue.
      for (PendingFunctionAnalysis::DirectCall &Call :
           Pending->unverifiedCalls()) {
        FuncAnalysisPtr AP = DeclAnalysis.lookup(Call.Callee);
        if (AP.isNull()) {
          VerificationQueue.push_back(Call.Callee);
          continue;
        }

        // This indicates recursion (not necessarily direct). For the
        // purposes of effect analysis, we can just ignore it since
        // no effects forbid recursion.
        assert(isa<PendingFunctionAnalysis *>(AP));
        Call.Recursed = true;
      }
    }
  }

private:
  // Verify a single Decl. Return the pending structure if that was the result,
  // else null. This method must not recurse.
  PendingFunctionAnalysis *verifyDecl(const Decl *D) {
    CallableInfo CInfo(*D);
    bool isExternC = false;

    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
      isExternC = FD->getCanonicalDecl()->isExternCContext();

    // For C++, with non-extern "C" linkage only - if any of the Decl's declared
    // effects forbid throwing (e.g. nonblocking) then the function should also
    // be declared noexcept.
    if (S.getLangOpts().CPlusPlus && !isExternC) {
      for (FunctionEffect Effect : CInfo.Effects) {
        if (!(Effect.flags() & FunctionEffect::FE_ExcludeThrow))
          continue;

        bool IsNoexcept = false;
        if (auto *FD = D->getAsFunction()) {
          IsNoexcept = isNoexcept(FD);
        } else if (auto *BD = dyn_cast<BlockDecl>(D)) {
          if (auto *TSI = BD->getSignatureAsWritten()) {
            auto *FPT = TSI->getType()->castAs<FunctionProtoType>();
            IsNoexcept = FPT->isNothrow() || BD->hasAttr<NoThrowAttr>();
          }
        }
        if (!IsNoexcept)
          S.Diag(D->getBeginLoc(), diag::warn_perf_constraint_implies_noexcept)
              << GetCallableDeclKind(D, nullptr) << Effect.name();
        break;
      }
    }

    // Build a PendingFunctionAnalysis on the stack. If it turns out to be
    // complete, we'll have avoided a heap allocation; if it's incomplete, it's
    // a fairly trivial move to a heap-allocated object.
    PendingFunctionAnalysis FAnalysis(S, CInfo, AllInferrableEffectsToVerify);

    LLVM_DEBUG(llvm::dbgs()
                   << "\nVerifying " << CInfo.getNameForDiagnostic(S) << " ";
               FAnalysis.dump(S, llvm::dbgs()););

    FunctionBodyASTVisitor Visitor(*this, FAnalysis, CInfo);

    Visitor.run();
    if (FAnalysis.isComplete()) {
      completeAnalysis(CInfo, std::move(FAnalysis));
      return nullptr;
    }
    // Move the pending analysis to the heap and save it in the map.
    PendingFunctionAnalysis *PendingPtr =
        new PendingFunctionAnalysis(std::move(FAnalysis));
    DeclAnalysis[D] = PendingPtr;
    LLVM_DEBUG(llvm::dbgs() << "inserted pending " << PendingPtr << "\n";
               DeclAnalysis.dump(S, llvm::dbgs()););
    return PendingPtr;
  }

  // Consume PendingFunctionAnalysis, create with it a CompleteFunctionAnalysis,
  // inserted in the container.
  void completeAnalysis(const CallableInfo &CInfo,
                        PendingFunctionAnalysis &&Pending) {
    if (ArrayRef<Violation> Viols =
            Pending.getSortedViolationsForExplicitEffects(S.getSourceManager());
        !Viols.empty())
      emitDiagnostics(Viols, CInfo);

    CompleteFunctionAnalysis *CompletePtr = new CompleteFunctionAnalysis(
        S.getASTContext(), std::move(Pending), CInfo.Effects,
        AllInferrableEffectsToVerify);
    DeclAnalysis[CInfo.CDecl] = CompletePtr;
    LLVM_DEBUG(llvm::dbgs() << "inserted complete " << CompletePtr << "\n";
               DeclAnalysis.dump(S, llvm::dbgs()););
  }

  // Called after all direct calls requiring inference have been found -- or
  // not. Repeats calls to FunctionBodyASTVisitor::followCall() but without
  // the possibility of inference. Deletes Pending.
  void finishPendingAnalysis(const Decl *D, PendingFunctionAnalysis *Pending) {
    CallableInfo Caller(*D);
    LLVM_DEBUG(llvm::dbgs() << "finishPendingAnalysis for "
                            << Caller.getNameForDiagnostic(S) << " : ";
               Pending->dump(S, llvm::dbgs()); llvm::dbgs() << "\n";);
    for (const PendingFunctionAnalysis::DirectCall &Call :
         Pending->unverifiedCalls()) {
      if (Call.Recursed)
        continue;

      CallableInfo Callee(*Call.Callee);
      followCall(Caller, *Pending, Callee, Call.CallLoc,
                 /*AssertNoFurtherInference=*/true, Call.VSite);
    }
    completeAnalysis(Caller, std::move(*Pending));
    delete Pending;
  }

  // Here we have a call to a Decl, either explicitly via a CallExpr or some
  // other AST construct. PFA pertains to the caller.
  void followCall(const CallableInfo &Caller, PendingFunctionAnalysis &PFA,
                  const CallableInfo &Callee, SourceLocation CallLoc,
                  bool AssertNoFurtherInference, ViolationSite VSite) {
    const bool DirectCall = Callee.isCalledDirectly();

    // Initially, the declared effects; inferred effects will be added.
    FunctionEffectKindSet CalleeEffects = Callee.Effects;

    bool IsInferencePossible = DirectCall;

    if (DirectCall)
      if (CompleteFunctionAnalysis *CFA =
              DeclAnalysis.completedAnalysisForDecl(Callee.CDecl)) {
        // Combine declared effects with those which may have been inferred.
        CalleeEffects.insert(CFA->VerifiedEffects);
        IsInferencePossible = false; // We've already traversed it.
      }

    if (AssertNoFurtherInference) {
      assert(!IsInferencePossible);
    }

    if (!Callee.isVerifiable())
      IsInferencePossible = false;

    LLVM_DEBUG(llvm::dbgs()
                   << "followCall from " << Caller.getNameForDiagnostic(S)
                   << " to " << Callee.getNameForDiagnostic(S)
                   << "; verifiable: " << Callee.isVerifiable() << "; callee ";
               CalleeEffects.dump(llvm::dbgs()); llvm::dbgs() << "\n";
               llvm::dbgs() << "  callee " << Callee.CDecl << " canonical "
                            << Callee.CDecl->getCanonicalDecl() << "\n";);

    auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {
      if (!Effect.shouldDiagnoseFunctionCall(DirectCall, CalleeEffects))
        return;

      // If inference is not allowed, or the target is indirect (virtual
      // method/function ptr?), generate a Violation now.
      if (!IsInferencePossible ||
          !(Effect.flags() & FunctionEffect::FE_InferrableOnCallees)) {
        if (Callee.FuncType == SpecialFuncType::None)
          PFA.checkAddViolation(Inferring,
                                {Effect, ViolationID::CallsDeclWithoutEffect,
                                 VSite, CallLoc, Callee.CDecl});
        else
          PFA.checkAddViolation(
              Inferring,
              {Effect, ViolationID::AllocatesMemory, VSite, CallLoc});
      } else {
        // Inference is allowed and necessary; defer it.
        PFA.addUnverifiedDirectCall(Callee.CDecl, CallLoc, VSite);
      }
    };

    for (FunctionEffect Effect : PFA.DeclaredVerifiableEffects)
      Check1Effect(Effect, false);

    for (FunctionEffect Effect : PFA.EffectsToInfer)
      Check1Effect(Effect, true);
  }

  // Describe a callable Decl for a diagnostic.
  // (Not an enum class because the value is always converted to an integer for
  // use in a diagnostic.)
  enum CallableDeclKind {
    CDK_Function,
    CDK_Constructor,
    CDK_Destructor,
    CDK_Lambda,
    CDK_Block,
    CDK_MemberInitializer,
  };

  // Describe a call site or target using an enum mapping to a %select{}
  // in a diagnostic, e.g. warn_func_effect_violation,
  // warn_perf_constraint_implies_noexcept, and others.
  static CallableDeclKind GetCallableDeclKind(const Decl *D,
                                              const Violation *V) {
    if (V != nullptr &&
        V->Site.kind() == ViolationSite::Kind::MemberInitializer)
      return CDK_MemberInitializer;
    if (isa<BlockDecl>(D))
      return CDK_Block;
    if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
      if (isa<CXXConstructorDecl>(D))
        return CDK_Constructor;
      if (isa<CXXDestructorDecl>(D))
        return CDK_Destructor;
      const CXXRecordDecl *Rec = Method->getParent();
      if (Rec->isLambda())
        return CDK_Lambda;
    }
    return CDK_Function;
  };

  // Should only be called when function's analysis is determined to be
  // complete.
  void emitDiagnostics(ArrayRef<Violation> Viols, const CallableInfo &CInfo) {
    if (Viols.empty())
      return;

    auto MaybeAddTemplateNote = [&](const Decl *D) {
      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
        while (FD != nullptr && FD->isTemplateInstantiation() &&
               FD->getPointOfInstantiation().isValid()) {
          S.Diag(FD->getPointOfInstantiation(),
                 diag::note_func_effect_from_template);
          FD = FD->getTemplateInstantiationPattern();
        }
      }
    };

    // For note_func_effect_call_indirect.
    enum { Indirect_VirtualMethod, Indirect_FunctionPtr };

    auto MaybeAddSiteContext = [&](const Decl *D, const Violation &V) {
      // If a violation site is a member initializer, add a note pointing to
      // the constructor which invoked it.
      if (V.Site.kind() == ViolationSite::Kind::MemberInitializer) {
        unsigned ImplicitCtor = 0;
        if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D);
            Ctor && Ctor->isImplicit())
          ImplicitCtor = 1;
        S.Diag(D->getLocation(), diag::note_func_effect_in_constructor)
            << ImplicitCtor;
      }

      // If a violation site is a default argument expression, add a note
      // pointing to the call site using the default argument.
      else if (V.Site.kind() == ViolationSite::Kind::DefaultArgExpr)
        S.Diag(V.Site.defaultArgExpr()->getUsedLocation(),
               diag::note_in_evaluating_default_argument);
    };

    // Top-level violations are warnings.
    for (const Violation &Viol1 : Viols) {
      StringRef effectName = Viol1.Effect.name();
      switch (Viol1.ID) {
      case ViolationID::None:
      case ViolationID::DeclDisallowsInference: // Shouldn't happen
                                                // here.
        llvm_unreachable("Unexpected violation kind");
        break;
      case ViolationID::AllocatesMemory:
      case ViolationID::ThrowsOrCatchesExceptions:
      case ViolationID::HasStaticLocalVariable:
      case ViolationID::AccessesThreadLocalVariable:
      case ViolationID::AccessesObjCMethodOrProperty:
        S.Diag(Viol1.Loc, diag::warn_func_effect_violation)
            << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName
            << Viol1.diagnosticSelectIndex();
        MaybeAddSiteContext(CInfo.CDecl, Viol1);
        MaybeAddTemplateNote(CInfo.CDecl);
        break;
      case ViolationID::CallsExprWithoutEffect:
        S.Diag(Viol1.Loc, diag::warn_func_effect_calls_expr_without_effect)
            << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName;
        MaybeAddSiteContext(CInfo.CDecl, Viol1);
        MaybeAddTemplateNote(CInfo.CDecl);
        break;

      case ViolationID::CallsDeclWithoutEffect: {
        CallableInfo CalleeInfo(*Viol1.Callee);
        std::string CalleeName = CalleeInfo.getNameForDiagnostic(S);

        S.Diag(Viol1.Loc, diag::warn_func_effect_calls_func_without_effect)
            << GetCallableDeclKind(CInfo.CDecl, &Viol1) << effectName
            << GetCallableDeclKind(CalleeInfo.CDecl, nullptr) << CalleeName;
        MaybeAddSiteContext(CInfo.CDecl, Viol1);
        MaybeAddTemplateNote(CInfo.CDecl);

        // Emit notes explaining the transitive chain of inferences: Why isn't
        // the callee safe?
        for (const Decl *Callee = Viol1.Callee; Callee != nullptr;) {
          std::optional<CallableInfo> MaybeNextCallee;
          CompleteFunctionAnalysis *Completed =
              DeclAnalysis.completedAnalysisForDecl(CalleeInfo.CDecl);
          if (Completed == nullptr) {
            // No result - could be
            // - non-inline and extern
            // - indirect (virtual or through function pointer)
            // - effect has been explicitly disclaimed (e.g. "blocking")

            CallableType CType = CalleeInfo.type();
            if (CType == CallableType::Virtual)
              S.Diag(Callee->getLocation(),
                     diag::note_func_effect_call_indirect)
                  << Indirect_VirtualMethod << effectName;
            else if (CType == CallableType::Unknown)
              S.Diag(Callee->getLocation(),
                     diag::note_func_effect_call_indirect)
                  << Indirect_FunctionPtr << effectName;
            else if (CalleeInfo.Effects.contains(Viol1.Effect.oppositeKind()))
              S.Diag(Callee->getLocation(),
                     diag::note_func_effect_call_disallows_inference)
                  << GetCallableDeclKind(CInfo.CDecl, nullptr) << effectName
                  << FunctionEffect(Viol1.Effect.oppositeKind()).name();
            else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Callee);
                     FD == nullptr || FD->getBuiltinID() == 0) {
              // A builtin callee generally doesn't have a useful source
              // location at which to insert a note.
              S.Diag(Callee->getLocation(), diag::note_func_effect_call_extern)
                  << effectName;
            }
            break;
          }
          const Violation *PtrViol2 =
              Completed->firstViolationForEffect(Viol1.Effect);
          if (PtrViol2 == nullptr)
            break;

          const Violation &Viol2 = *PtrViol2;
          switch (Viol2.ID) {
          case ViolationID::None:
            llvm_unreachable("Unexpected violation kind");
            break;
          case ViolationID::DeclDisallowsInference:
            S.Diag(Viol2.Loc, diag::note_func_effect_call_disallows_inference)
                << GetCallableDeclKind(CalleeInfo.CDecl, nullptr) << effectName
                << Viol2.CalleeEffectPreventingInference->name();
            break;
          case ViolationID::CallsExprWithoutEffect:
            S.Diag(Viol2.Loc, diag::note_func_effect_call_indirect)
                << Indirect_FunctionPtr << effectName;
            break;
          case ViolationID::AllocatesMemory:
          case ViolationID::ThrowsOrCatchesExceptions:
          case ViolationID::HasStaticLocalVariable:
          case ViolationID::AccessesThreadLocalVariable:
          case ViolationID::AccessesObjCMethodOrProperty:
            S.Diag(Viol2.Loc, diag::note_func_effect_violation)
                << GetCallableDeclKind(CalleeInfo.CDecl, &Viol2) << effectName
                << Viol2.diagnosticSelectIndex();
            MaybeAddSiteContext(CalleeInfo.CDecl, Viol2);
            break;
          case ViolationID::CallsDeclWithoutEffect:
            MaybeNextCallee.emplace(*Viol2.Callee);
            S.Diag(Viol2.Loc, diag::note_func_effect_calls_func_without_effect)
                << GetCallableDeclKind(CalleeInfo.CDecl, &Viol2) << effectName
                << GetCallableDeclKind(Viol2.Callee, nullptr)
                << MaybeNextCallee->getNameForDiagnostic(S);
            break;
          }
          MaybeAddTemplateNote(Callee);
          Callee = Viol2.Callee;
          if (MaybeNextCallee) {
            CalleeInfo = *MaybeNextCallee;
            CalleeName = CalleeInfo.getNameForDiagnostic(S);
          }
        }
      } break;
      }
    }
  }

  // ----------
  // This AST visitor is used to traverse the body of a function during effect
  // verification. This happens in 2 situations:
  //  [1] The function has declared effects which need to be validated.
  //  [2] The function has not explicitly declared an effect in question, and is
  //      being checked for implicit conformance.
  //
  // Violations are always routed to a PendingFunctionAnalysis.
  struct FunctionBodyASTVisitor : DynamicRecursiveASTVisitor {
    Analyzer &Outer;
    PendingFunctionAnalysis &CurrentFunction;
    CallableInfo &CurrentCaller;
    ViolationSite VSite;
    const Expr *TrailingRequiresClause = nullptr;
    const Expr *NoexceptExpr = nullptr;

    FunctionBodyASTVisitor(Analyzer &Outer,
                           PendingFunctionAnalysis &CurrentFunction,
                           CallableInfo &CurrentCaller)
        : Outer(Outer), CurrentFunction(CurrentFunction),
          CurrentCaller(CurrentCaller) {
      ShouldVisitImplicitCode = true;
      ShouldWalkTypesOfTypeLocs = false;
    }

    // -- Entry point --
    void run() {
      // The target function may have implicit code paths beyond the
      // body: member and base destructors. Visit these first.
      if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))
        followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);

      if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) {
        TrailingRequiresClause = FD->getTrailingRequiresClause().ConstraintExpr;

        // Note that FD->getType->getAs<FunctionProtoType>() can yield a
        // noexcept Expr which has been boiled down to a constant expression.
        // Going through the TypeSourceInfo obtains the actual expression which
        // will be traversed as part of the function -- unless we capture it
        // here and have TraverseStmt skip it.
        if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) {
          if (FunctionProtoTypeLoc TL =
                  TSI->getTypeLoc().getAs<FunctionProtoTypeLoc>())
            if (const FunctionProtoType *FPT = TL.getTypePtr())
              NoexceptExpr = FPT->getNoexceptExpr();
        }
      }

      // Do an AST traversal of the function/block body
      TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl));
    }

    // -- Methods implementing common logic --

    // Handle a language construct forbidden by some effects. Only effects whose
    // flags include the specified flag receive a violation. \p Flag describes
    // the construct.
    void diagnoseLanguageConstruct(FunctionEffect::FlagBit Flag,
                                   ViolationID VID, SourceLocation Loc,
                                   const Decl *Callee = nullptr) {
      // If there are any declared verifiable effects which forbid the construct
      // represented by the flag, store just one violation.
      for (FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects) {
        if (Effect.flags() & Flag) {
          addViolation(/*inferring=*/false, Effect, VID, Loc, Callee);
          break;
        }
      }
      // For each inferred effect which forbids the construct, store a
      // violation, if we don't already have a violation for that effect.
      for (FunctionEffect Effect : CurrentFunction.EffectsToInfer)
        if (Effect.flags() & Flag)
          addViolation(/*inferring=*/true, Effect, VID, Loc, Callee);
    }

    void addViolation(bool Inferring, FunctionEffect Effect, ViolationID VID,
                      SourceLocation Loc, const Decl *Callee = nullptr) {
      CurrentFunction.checkAddViolation(
          Inferring, Violation(Effect, VID, VSite, Loc, Callee));
    }

    // Here we have a call to a Decl, either explicitly via a CallExpr or some
    // other AST construct. CallableInfo pertains to the callee.
    void followCall(CallableInfo &CI, SourceLocation CallLoc) {
      // Check for a call to a builtin function, whose effects are
      // handled specially.
      if (const auto *FD = dyn_cast<FunctionDecl>(CI.CDecl)) {
        if (unsigned BuiltinID = FD->getBuiltinID()) {
          CI.Effects = getBuiltinFunctionEffects(BuiltinID);
          if (CI.Effects.empty()) {
            // A builtin with no known effects is assumed safe.
            return;
          }
          // A builtin WITH effects doesn't get any special treatment for
          // being noreturn/noexcept, e.g. longjmp(), so we skip the check
          // below.
        } else {
          // If the callee is both `noreturn` and `noexcept`, it presumably
          // terminates. Ignore it for the purposes of effect analysis.
          // If not C++, `noreturn` alone is sufficient.
          if (FD->isNoReturn() &&
              (!Outer.S.getLangOpts().CPlusPlus || isNoexcept(FD)))
            return;
        }
      }

      Outer.followCall(CurrentCaller, CurrentFunction, CI, CallLoc,
                       /*AssertNoFurtherInference=*/false, VSite);
    }

    void checkIndirectCall(CallExpr *Call, QualType CalleeType) {
      FunctionEffectKindSet CalleeEffects;
      if (FunctionEffectsRef Effects = FunctionEffectsRef::get(CalleeType);
          !Effects.empty())
        CalleeEffects.insert(Effects);

      auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {
        if (Effect.shouldDiagnoseFunctionCall(
                /*direct=*/false, CalleeEffects))
          addViolation(Inferring, Effect, ViolationID::CallsExprWithoutEffect,
                       Call->getBeginLoc());
      };

      for (FunctionEffect Effect : CurrentFunction.DeclaredVerifiableEffects)
        Check1Effect(Effect, false);

      for (FunctionEffect Effect : CurrentFunction.EffectsToInfer)
        Check1Effect(Effect, true);
    }

    // This destructor's body should be followed by the caller, but here we
    // follow the field and base destructors.
    void followDestructor(const CXXRecordDecl *Rec,
                          const CXXDestructorDecl *Dtor) {
      SourceLocation DtorLoc = Dtor->getLocation();
      for (const FieldDecl *Field : Rec->fields())
        followTypeDtor(Field->getType(), DtorLoc);

      if (const auto *Class = dyn_cast<CXXRecordDecl>(Rec))
        for (const CXXBaseSpecifier &Base : Class->bases())
          followTypeDtor(Base.getType(), DtorLoc);
    }

    void followTypeDtor(QualType QT, SourceLocation CallSite) {
      const Type *Ty = QT.getTypePtr();
      while (Ty->isArrayType()) {
        const ArrayType *Arr = Ty->getAsArrayTypeUnsafe();
        QT = Arr->getElementType();
        Ty = QT.getTypePtr();
      }

      if (Ty->isRecordType()) {
        if (const CXXRecordDecl *Class = Ty->getAsCXXRecordDecl()) {
          if (CXXDestructorDecl *Dtor = Class->getDestructor();
              Dtor && !Dtor->isDeleted()) {
            CallableInfo CI(*Dtor);
            followCall(CI, CallSite);
          }
        }
      }
    }

    // -- Methods for use of RecursiveASTVisitor --

    bool VisitCXXThrowExpr(CXXThrowExpr *Throw) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow,
                                ViolationID::ThrowsOrCatchesExceptions,
                                Throw->getThrowLoc());
      return true;
    }

    bool VisitCXXCatchStmt(CXXCatchStmt *Catch) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,
                                ViolationID::ThrowsOrCatchesExceptions,
                                Catch->getCatchLoc());
      return true;
    }

    bool VisitObjCAtThrowStmt(ObjCAtThrowStmt *Throw) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow,
                                ViolationID::ThrowsOrCatchesExceptions,
                                Throw->getThrowLoc());
      return true;
    }

    bool VisitObjCAtCatchStmt(ObjCAtCatchStmt *Catch) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,
                                ViolationID::ThrowsOrCatchesExceptions,
                                Catch->getAtCatchLoc());
      return true;
    }

    bool VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Finally) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,
                                ViolationID::ThrowsOrCatchesExceptions,
                                Finally->getAtFinallyLoc());
      return true;
    }

    bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,
                                ViolationID::AccessesObjCMethodOrProperty,
                                Msg->getBeginLoc());
      return true;
    }

    bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *ARP) override {
      // Under the hood, @autorelease (potentially?) allocates memory and
      // invokes ObjC methods. We don't currently have memory allocation as
      // a "language construct" but we do have ObjC messaging, so diagnose that.
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,
                                ViolationID::AccessesObjCMethodOrProperty,
                                ARP->getBeginLoc());
      return true;
    }

    bool VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Sync) override {
      // Under the hood, this calls objc_sync_enter and objc_sync_exit, wrapped
      // in a @try/@finally block. Diagnose this generically as "ObjC
      // messaging".
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend,
                                ViolationID::AccessesObjCMethodOrProperty,
                                Sync->getBeginLoc());
      return true;
    }

    bool VisitSEHExceptStmt(SEHExceptStmt *Exc) override {
      diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch,
                                ViolationID::ThrowsOrCatchesExceptions,
                                Exc->getExceptLoc());
      return true;
    }

    bool VisitCallExpr(CallExpr *Call) override {
      LLVM_DEBUG(llvm::dbgs()
                     << "VisitCallExpr : "
                     << Call->getBeginLoc().printToString(Outer.S.SourceMgr)
                     << "\n";);

      Expr *CalleeExpr = Call->getCallee();
      if (const Decl *Callee = CalleeExpr->getReferencedDeclOfCallee()) {
        CallableInfo CI(*Callee);
        followCall(CI, Call->getBeginLoc());
        return true;
      }

      if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) {
        // Just destroying a scalar, fine.
        return true;
      }

      // No Decl, just an Expr. Just check based on its type.
      checkIndirectCall(Call, CalleeExpr->getType());

      return true;
    }

    bool VisitVarDecl(VarDecl *Var) override {
      LLVM_DEBUG(llvm::dbgs()
                     << "VisitVarDecl : "
                     << Var->getBeginLoc().printToString(Outer.S.SourceMgr)
                     << "\n";);

      if (Var->isStaticLocal())
        diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeStaticLocalVars,
                                  ViolationID::HasStaticLocalVariable,
                                  Var->getLocation());

      const QualType::DestructionKind DK =
          Var->needsDestruction(Outer.S.getASTContext());
      if (DK == QualType::DK_cxx_destructor)
        followTypeDtor(Var->getType(), Var->getLocation());
      return true;
    }

    bool VisitCXXNewExpr(CXXNewExpr *New) override {
      // RecursiveASTVisitor does not visit the implicit call to operator new.
      if (FunctionDecl *FD = New->getOperatorNew()) {
        CallableInfo CI(*FD, SpecialFuncType::OperatorNew);
        followCall(CI, New->getBeginLoc());
      }

      // It's a bit excessive to check operator delete here, since it's
      // just a fallback for operator new followed by a failed constructor.
      // We could check it via New->getOperatorDelete().

      // It DOES however visit the called constructor
      return true;
    }

    bool VisitCXXDeleteExpr(CXXDeleteExpr *Delete) override {
      // RecursiveASTVisitor does not visit the implicit call to operator
      // delete.
      if (FunctionDecl *FD = Delete->getOperatorDelete()) {
        CallableInfo CI(*FD, SpecialFuncType::OperatorDelete);
        followCall(CI, Delete->getBeginLoc());
      }

      // It DOES however visit the called destructor

      return true;
    }

    bool VisitCXXConstructExpr(CXXConstructExpr *Construct) override {
      LLVM_DEBUG(llvm::dbgs() << "VisitCXXConstructExpr : "
                              << Construct->getBeginLoc().printToString(
                                     Outer.S.SourceMgr)
                              << "\n";);

      // RecursiveASTVisitor does not visit the implicit call to the
      // constructor.
      const CXXConstructorDecl *Ctor = Construct->getConstructor();
      CallableInfo CI(*Ctor);
      followCall(CI, Construct->getLocation());

      return true;
    }

    bool TraverseStmt(Stmt *Statement) override {
      // If this statement is a `requires` clause from the top-level function
      // being traversed, ignore it, since it's not generating runtime code.
      // We skip the traversal of lambdas (beyond their captures, see
      // TraverseLambdaExpr below), so just caching this from our constructor
      // should suffice.
      if (Statement != TrailingRequiresClause && Statement != NoexceptExpr)
        return DynamicRecursiveASTVisitor::TraverseStmt(Statement);
      return true;
    }

    bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {
      ViolationSite PrevVS = VSite;
      if (Init->isAnyMemberInitializer())
        VSite.setKind(ViolationSite::Kind::MemberInitializer);
      bool Result =
          DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);
      VSite = PrevVS;
      return Result;
    }

    bool TraverseCXXDefaultArgExpr(CXXDefaultArgExpr *E) override {
      LLVM_DEBUG(llvm::dbgs()
                     << "TraverseCXXDefaultArgExpr : "
                     << E->getUsedLocation().printToString(Outer.S.SourceMgr)
                     << "\n";);

      ViolationSite PrevVS = VSite;
      if (VSite.kind() == ViolationSite::Kind::Default)
        VSite = ViolationSite{E};

      bool Result = DynamicRecursiveASTVisitor::TraverseCXXDefaultArgExpr(E);
      VSite = PrevVS;
      return Result;
    }

    bool TraverseLambdaExpr(LambdaExpr *Lambda) override {
      // We override this so as to be able to skip traversal of the lambda's
      // body. We have to explicitly traverse the captures. Why not return
      // false from shouldVisitLambdaBody()? Because we need to visit a lambda's
      // body when we are verifying the lambda itself; we only want to skip it
      // in the context of the outer function.
      for (unsigned I = 0, N = Lambda->capture_size(); I < N; ++I)
        TraverseLambdaCapture(Lambda, Lambda->capture_begin() + I,
                              Lambda->capture_init_begin()[I]);

      return true;
    }

    bool TraverseBlockExpr(BlockExpr * /*unused*/) override {
      // As with lambdas, don't traverse the block's body.
      // TODO: are the capture expressions (ctor call?) safe?
      return true;
    }

    bool VisitDeclRefExpr(DeclRefExpr *E) override {
      const ValueDecl *Val = E->getDecl();
      if (const auto *Var = dyn_cast<VarDecl>(Val)) {
        if (Var->getTLSKind() != VarDecl::TLS_None) {
          // At least on macOS, thread-local variables are initialized on
          // first access, including a heap allocation.
          diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThreadLocalVars,
                                    ViolationID::AccessesThreadLocalVariable,
                                    E->getLocation());
        }
      }
      return true;
    }

    bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override {
      return TraverseStmt(Node->getResultExpr());
    }
    bool
    TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override {
      return true;
    }

    bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override {
      return true;
    }

    bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { return true; }

    bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override {
      return true;
    }

    bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override { return true; }

    // Skip concept requirements since they don't generate code.
    bool TraverseConceptRequirement(concepts::Requirement *R) override {
      return true;
    }
  };
};

Analyzer::AnalysisMap::~AnalysisMap() {
  for (const auto &Item : *this) {
    FuncAnalysisPtr AP = Item.second;
    if (auto *PFA = dyn_cast<PendingFunctionAnalysis *>(AP))
      delete PFA;
    else
      delete cast<CompleteFunctionAnalysis *>(AP);
  }
}

} // anonymous namespace

namespace clang {

bool Sema::diagnoseConflictingFunctionEffect(
    const FunctionEffectsRef &FX, const FunctionEffectWithCondition &NewEC,
    SourceLocation NewAttrLoc) {
  // If the new effect has a condition, we can't detect conflicts until the
  // condition is resolved.
  if (NewEC.Cond.getCondition() != nullptr)
    return false;

  // Diagnose the new attribute as incompatible with a previous one.
  auto Incompatible = [&](const FunctionEffectWithCondition &PrevEC) {
    Diag(NewAttrLoc, diag::err_attributes_are_not_compatible)
        << ("'" + NewEC.description() + "'")
        << ("'" + PrevEC.description() + "'") << false;
    // We don't necessarily have the location of the previous attribute,
    // so no note.
    return true;
  };

  // Compare against previous attributes.
  FunctionEffect::Kind NewKind = NewEC.Effect.kind();

  for (const FunctionEffectWithCondition &PrevEC : FX) {
    // Again, can't check yet when the effect is conditional.
    if (PrevEC.Cond.getCondition() != nullptr)
      continue;

    FunctionEffect::Kind PrevKind = PrevEC.Effect.kind();
    // Note that we allow PrevKind == NewKind; it's redundant and ignored.

    if (PrevEC.Effect.oppositeKind() == NewKind)
      return Incompatible(PrevEC);

    // A new allocating is incompatible with a previous nonblocking.
    if (PrevKind == FunctionEffect::Kind::NonBlocking &&
        NewKind == FunctionEffect::Kind::Allocating)
      return Incompatible(PrevEC);

    // A new nonblocking is incompatible with a previous allocating.
    if (PrevKind == FunctionEffect::Kind::Allocating &&
        NewKind == FunctionEffect::Kind::NonBlocking)
      return Incompatible(PrevEC);
  }

  return false;
}

void Sema::diagnoseFunctionEffectMergeConflicts(
    const FunctionEffectSet::Conflicts &Errs, SourceLocation NewLoc,
    SourceLocation OldLoc) {
  for (const FunctionEffectSet::Conflict &Conflict : Errs) {
    Diag(NewLoc, diag::warn_conflicting_func_effects)
        << Conflict.Kept.description() << Conflict.Rejected.description();
    Diag(OldLoc, diag::note_previous_declaration);
  }
}

// Decl should be a FunctionDecl or BlockDecl.
void Sema::maybeAddDeclWithEffects(const Decl *D,
                                   const FunctionEffectsRef &FX) {
  if (!D->hasBody()) {
    if (const auto *FD = D->getAsFunction(); FD && !FD->willHaveBody())
      return;
  }

  if (Diags.getIgnoreAllWarnings() ||
      (Diags.getSuppressSystemWarnings() &&
       SourceMgr.isInSystemHeader(D->getLocation())))
    return;

  if (hasUncompilableErrorOccurred())
    return;

  // For code in dependent contexts, we'll do this at instantiation time.
  // Without this check, we would analyze the function based on placeholder
  // template parameters, and potentially generate spurious diagnostics.
  if (cast<DeclContext>(D)->isDependentContext())
    return;

  addDeclWithEffects(D, FX);
}

void Sema::addDeclWithEffects(const Decl *D, const FunctionEffectsRef &FX) {
  // To avoid the possibility of conflict, don't add effects which are
  // not FE_InferrableOnCallees and therefore not verified; this removes
  // blocking/allocating but keeps nonblocking/nonallocating.
  // Also, ignore any conditions when building the list of effects.
  bool AnyVerifiable = false;
  for (const FunctionEffectWithCondition &EC : FX)
    if (EC.Effect.flags() & FunctionEffect::FE_InferrableOnCallees) {
      AllEffectsToVerify.insert(EC.Effect);
      AnyVerifiable = true;
    }

  // Record the declaration for later analysis.
  if (AnyVerifiable)
    DeclsWithEffectsToVerify.push_back(D);
}

void Sema::performFunctionEffectAnalysis(TranslationUnitDecl *TU) {
  if (hasUncompilableErrorOccurred() || Diags.getIgnoreAllWarnings())
    return;
  if (TU == nullptr)
    return;
  Analyzer{*this}.run(*TU);
}

Sema::FunctionEffectDiffVector::FunctionEffectDiffVector(
    const FunctionEffectsRef &Old, const FunctionEffectsRef &New) {

  FunctionEffectsRef::iterator POld = Old.begin();
  FunctionEffectsRef::iterator OldEnd = Old.end();
  FunctionEffectsRef::iterator PNew = New.begin();
  FunctionEffectsRef::iterator NewEnd = New.end();

  while (true) {
    int cmp = 0;
    if (POld == OldEnd) {
      if (PNew == NewEnd)
        break;
      cmp = 1;
    } else if (PNew == NewEnd)
      cmp = -1;
    else {
      FunctionEffectWithCondition Old = *POld;
      FunctionEffectWithCondition New = *PNew;
      if (Old.Effect.kind() < New.Effect.kind())
        cmp = -1;
      else if (New.Effect.kind() < Old.Effect.kind())
        cmp = 1;
      else {
        cmp = 0;
        if (Old.Cond.getCondition() != New.Cond.getCondition()) {
          // FIXME: Cases where the expressions are equivalent but
          // don't have the same identity.
          push_back(FunctionEffectDiff{
              Old.Effect.kind(), FunctionEffectDiff::Kind::ConditionMismatch,
              Old, New});
        }
      }
    }

    if (cmp < 0) {
      // removal
      FunctionEffectWithCondition Old = *POld;
      push_back(FunctionEffectDiff{Old.Effect.kind(),
                                   FunctionEffectDiff::Kind::Removed, Old,
                                   std::nullopt});
      ++POld;
    } else if (cmp > 0) {
      // addition
      FunctionEffectWithCondition New = *PNew;
      push_back(FunctionEffectDiff{New.Effect.kind(),
                                   FunctionEffectDiff::Kind::Added,
                                   std::nullopt, New});
      ++PNew;
    } else {
      ++POld;
      ++PNew;
    }
  }
}

bool Sema::FunctionEffectDiff::shouldDiagnoseConversion(
    QualType SrcType, const FunctionEffectsRef &SrcFX, QualType DstType,
    const FunctionEffectsRef &DstFX) const {

  switch (EffectKind) {
  case FunctionEffect::Kind::NonAllocating:
    // nonallocating can't be added (spoofed) during a conversion, unless we
    // have nonblocking.
    if (DiffKind == Kind::Added) {
      for (const auto &CFE : SrcFX) {
        if (CFE.Effect.kind() == FunctionEffect::Kind::NonBlocking)
          return false;
      }
    }
    [[fallthrough]];
  case FunctionEffect::Kind::NonBlocking:
    // nonblocking can't be added (spoofed) during a conversion.
    switch (DiffKind) {
    case Kind::Added:
      return true;
    case Kind::Removed:
      return false;
    case Kind::ConditionMismatch:
      // FIXME: Condition mismatches are too coarse right now -- expressions
      // which are equivalent but don't have the same identity are detected as
      // mismatches. We're going to diagnose those anyhow until expression
      // matching is better.
      return true;
    }
    break;
  case FunctionEffect::Kind::Blocking:
  case FunctionEffect::Kind::Allocating:
    return false;
  }
  llvm_unreachable("unknown effect kind");
}

bool Sema::FunctionEffectDiff::shouldDiagnoseRedeclaration(
    const FunctionDecl &OldFunction, const FunctionEffectsRef &OldFX,
    const FunctionDecl &NewFunction, const FunctionEffectsRef &NewFX) const {
  switch (EffectKind) {
  case FunctionEffect::Kind::NonAllocating:
  case FunctionEffect::Kind::NonBlocking:
    // nonblocking/nonallocating can't be removed in a redeclaration.
    switch (DiffKind) {
    case Kind::Added:
      return false; // No diagnostic.
    case Kind::Removed:
      return true; // Issue diagnostic.
    case Kind::ConditionMismatch:
      // All these forms of mismatches are diagnosed.
      return true;
    }
    break;
  case FunctionEffect::Kind::Blocking:
  case FunctionEffect::Kind::Allocating:
    return false;
  }
  llvm_unreachable("unknown effect kind");
}

Sema::FunctionEffectDiff::OverrideResult
Sema::FunctionEffectDiff::shouldDiagnoseMethodOverride(
    const CXXMethodDecl &OldMethod, const FunctionEffectsRef &OldFX,
    const CXXMethodDecl &NewMethod, const FunctionEffectsRef &NewFX) const {
  switch (EffectKind) {
  case FunctionEffect::Kind::NonAllocating:
  case FunctionEffect::Kind::NonBlocking:
    switch (DiffKind) {

    // If added on an override, that's fine and not diagnosed.
    case Kind::Added:
      return OverrideResult::NoAction;

    // If missing from an override (removed), propagate from base to derived.
    case Kind::Removed:
      return OverrideResult::Merge;

    // If there's a mismatch involving the effect's polarity or condition,
    // issue a warning.
    case Kind::ConditionMismatch:
      return OverrideResult::Warn;
    }
    break;
  case FunctionEffect::Kind::Blocking:
  case FunctionEffect::Kind::Allocating:
    return OverrideResult::NoAction;
  }
  llvm_unreachable("unknown effect kind");
}

} // namespace clang
