//===--- TypeCheckCaptures.cpp - Capture Analysis -------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements computing capture info for closure expressions and named
// local functions.
//
//===----------------------------------------------------------------------===//

#include "TypeChecker.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/TypeWalker.h"
#include "swift/Basic/Defer.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace swift;

static SourceLoc getCaptureLoc(AnyFunctionRef AFR) {
  if (auto AFD = AFR.getAbstractFunctionDecl()) {
    if (auto *FD = dyn_cast<FuncDecl>(AFD)) {
      if (FD->isDeferBody()) {
        // HACK: Defer statements generate implicit FuncDecls, and hence do
        // not have valid source locations.  Instead, use the location of
        // the body.
        return FD->getBody()->getLBraceLoc();
      }
    }

    return AFD->getLoc();
  } else {
    auto ACE = AFR.getAbstractClosureExpr();
    if (auto CE = dyn_cast<ClosureExpr>(ACE)) {
      if (!CE->getInLoc().isInvalid())
        return CE->getInLoc();
    }

    return ACE->getLoc();
  }
}

namespace {

class FindCapturedVars : public ASTWalker {
  TypeChecker &TC;
  SmallVectorImpl<CapturedValue> &Captures;
  llvm::SmallDenseMap<ValueDecl*, unsigned, 4> captureEntryNumber;
  SourceLoc CaptureLoc;
  SourceLoc &GenericParamCaptureLoc;
  SourceLoc &DynamicSelfCaptureLoc;
  DynamicSelfType *&DynamicSelf;
  llvm::SmallPtrSet<ValueDecl *, 2> Diagnosed;
  /// The AbstractClosureExpr or AbstractFunctionDecl being analyzed.
  AnyFunctionRef AFR;
public:
  FindCapturedVars(TypeChecker &tc,
                   SmallVectorImpl<CapturedValue> &Captures,
                   SourceLoc &GenericParamCaptureLoc,
                   SourceLoc &DynamicSelfCaptureLoc,
                   DynamicSelfType *&DynamicSelf,
                   AnyFunctionRef AFR)
      : TC(tc), Captures(Captures),
        GenericParamCaptureLoc(GenericParamCaptureLoc),
        DynamicSelfCaptureLoc(DynamicSelfCaptureLoc),
        DynamicSelf(DynamicSelf),
        AFR(AFR) {
    CaptureLoc = getCaptureLoc(AFR);
  }

  /// \brief Check if the type of an expression references any generic
  /// type parameters, or the dynamic Self type.
  ///
  /// Note that we do not need to distinguish inner from outer generic
  /// parameters here -- if a local function has its own inner parameter
  /// list, it also implicitly captures outer parameters, even if they're
  /// not used anywhere inside the body.
  void checkType(Type type, SourceLoc loc) {

    if (!type)
      return;

    // We want to look through type aliases here.
    type = type->getCanonicalType();
    
    class TypeCaptureWalker : public TypeWalker {
      AnyFunctionRef AFR;
      std::function<void(Type)> Callback;
    public:
      explicit TypeCaptureWalker(AnyFunctionRef AFR,
                                 std::function<void(Type)> callback)
        : AFR(AFR), Callback(std::move(callback)) {}
    
      Action walkToTypePre(Type ty) override {
        Callback(ty);
        // Pseudogeneric classes don't use their generic parameters so we
        // don't need to visit them.
        if (AFR.isObjC()) {
          if (auto clas = dyn_cast_or_null<ClassDecl>(ty->getAnyNominal())) {
            if (clas->usesObjCGenericsModel()) {
              return Action::SkipChildren;
            }
          }
        }
        return Action::Continue;
      }
    };
    // If the type contains dynamic 'Self', conservatively assume we will
    // need 'Self' metadata at runtime. We could generalize the analysis
    // used below for usages of generic parameters in Objective-C
    // extensions, and re-use it here.
    //
    // For example, forming an existential from a value of type 'Self'
    // does not need the dynamic 'Self' type -- the static type will
    // suffice. Also, just passing around a value of type 'Self' does
    // not need metadata either, since it is represented as a single
    // retainable pointer. Similarly stored property access does not
    // need it, etc.
    if (type->hasDynamicSelfType()) {
      type.walk(TypeCaptureWalker(AFR, [&](Type t) {
        if (auto *dynamicSelf = t->getAs<DynamicSelfType>()) {
          if (DynamicSelfCaptureLoc.isInvalid()) {
            DynamicSelfCaptureLoc = loc;
            DynamicSelf = dynamicSelf;
          }
        }
      }));
    }

    // Similar to dynamic 'Self', IRGen doesn't really need type metadata
    // for class-bound archetypes in nearly as many cases as with opaque
    // archetypes.
    //
    // Perhaps this entire analysis should happen at the SILGen level,
    // instead, but even there we don't really have enough information to
    // perform it accurately.
    if (type->hasArchetype() || type->hasTypeParameter()) {
      type.walk(TypeCaptureWalker(AFR, [&](Type t) {
        if ((t->is<ArchetypeType>() ||
             t->is<GenericTypeParamType>()) &&
            !t->isOpenedExistential() &&
            GenericParamCaptureLoc.isInvalid()) {
          GenericParamCaptureLoc = loc;
        }
      }));
    }

    if (auto *gft = type->getAs<GenericFunctionType>()) {
      TypeCaptureWalker walker(AFR, [&](Type t) {
        if (t->is<GenericTypeParamType>() &&
            GenericParamCaptureLoc.isInvalid()) {
          GenericParamCaptureLoc = loc;
        }
      });

      gft->getInput().walk(walker);
      gft->getResult().walk(walker);
    }
  }

  /// Add the specified capture to the closure's capture list, diagnosing it
  /// if invalid.
  void addCapture(CapturedValue capture, SourceLoc Loc) {
    auto VD = capture.getDecl();

    // Check to see if we already have an entry for this decl.
    unsigned &entryNumber = captureEntryNumber[VD];
    if (entryNumber == 0) {
      Captures.push_back(capture);
      entryNumber = Captures.size();
    } else {
      // If this already had an entry in the capture list, make sure to merge
      // the information together.  If one is noescape but the other isn't,
      // then the result is escaping.
      unsigned Flags =
        Captures[entryNumber-1].getFlags() & capture.getFlags();
      capture = CapturedValue(VD, Flags);
      Captures[entryNumber-1] = capture;
    }

    // Visit the type of the capture, if it isn't a class reference, since
    // we'd need the metadata to do so.
    if (VD->hasInterfaceType()
        && (!AFR.isObjC()
            || !isa<VarDecl>(VD)
            || !cast<VarDecl>(VD)->getType()->hasRetainablePointerRepresentation()))
      checkType(VD->getInterfaceType(), VD->getLoc());

    // If VD is a noescape decl, then the closure we're computing this for
    // must also be noescape.
    if (AFR.hasType() &&
        !AFR.getType()->hasError() &&
        VD->hasInterfaceType() &&
        VD->getInterfaceType()->is<AnyFunctionType>() &&
        VD->getInterfaceType()->castTo<AnyFunctionType>()->isNoEscape() &&
        !capture.isNoEscape() &&
        // Don't repeatedly diagnose the same thing.
        Diagnosed.insert(VD).second) {

      // Otherwise, diagnose this as an invalid capture.
      bool isDecl = AFR.getAbstractFunctionDecl() != nullptr;

      TC.diagnose(Loc, isDecl ? diag::decl_closure_noescape_use
                              : diag::closure_noescape_use,
                  VD->getBaseName().getIdentifier());

      // If we're a parameter, emit a helpful fixit to add @escaping
      auto paramDecl = dyn_cast<ParamDecl>(VD);
      if (paramDecl) {
        TC.diagnose(paramDecl->getStartLoc(), diag::noescape_parameter,
                    paramDecl->getName())
            .fixItInsert(paramDecl->getTypeLoc().getSourceRange().Start,
                         "@escaping ");
      }
    }
  }

  std::pair<bool, Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
    auto *D = DRE->getDecl();

    // Capture the generic parameters of the decl, unless it's a
    // local declaration in which case we will pick up generic
    // parameter references transitively.
    if (!D->getDeclContext()->isLocalContext()) {
      if (!AFR.isObjC() || !D->isObjC() || isa<ConstructorDecl>(D)) {
        for (auto sub : DRE->getDeclRef().getSubstitutions()) {
          checkType(sub.getReplacement(), DRE->getLoc());
        }
      }
    }

    // DC is the DeclContext where D was defined
    // CurDC is the DeclContext where D was referenced
    auto DC = D->getDeclContext();
    auto CurDC = AFR.getAsDeclContext();

    // A local reference is not a capture.
    if (CurDC == DC)
      return { false, DRE };

    auto TmpDC = CurDC;

    if (!isa<TopLevelCodeDecl>(DC)) {
      while (TmpDC != nullptr) {
        if (TmpDC == DC)
          break;

        // We have an intervening nominal type context that is not the
        // declaration context, and the declaration context is not global.
        // This is not supported since nominal types cannot capture values.
        if (auto NTD = dyn_cast<NominalTypeDecl>(TmpDC)) {
          if (DC->isLocalContext()) {
            TC.diagnose(DRE->getLoc(), diag::capture_across_type_decl,
                        NTD->getDescriptiveKind(),
                        D->getBaseName().getIdentifier());

            TC.diagnose(NTD->getLoc(), diag::type_declared_here);

            TC.diagnose(D, diag::decl_declared_here, D->getFullName());
            return { false, DRE };
          }
        }

        TmpDC = TmpDC->getParent();
      }

      // We walked all the way up to the root without finding the declaration,
      // so this is not a capture.
      if (TmpDC == nullptr)
        return { false, DRE };
    }

    // Only capture var decls at global scope.  Other things can be captured
    // if they are local.
    if (!isa<VarDecl>(D) && !DC->isLocalContext())
      return { false, DRE };

    // Can only capture a variable that is declared before the capturing
    // entity.
    llvm::DenseSet<ValueDecl *> checkedCaptures;
    llvm::SmallVector<FuncDecl *, 2> capturePath;

    std::function<bool (ValueDecl *)>
    validateForwardCapture = [&](ValueDecl *capturedDecl) -> bool {
      if (!checkedCaptures.insert(capturedDecl).second)
        return true;

      // Captures at nonlocal scope are order-invariant.
      if (!capturedDecl->getDeclContext()->isLocalContext())
        return true;

      // Assume implicit decl captures are OK.
      if (!CaptureLoc.isValid() || !capturedDecl->getLoc().isValid())
        return true;

      // Check the order of the declarations.
      if (!TC.Context.SourceMgr.isBeforeInBuffer(CaptureLoc,
                                                 capturedDecl->getLoc()))
        return true;

      // Forward captures of functions are OK, if the function doesn't
      // transitively capture variables ahead of the original function.
      if (auto func = dyn_cast<FuncDecl>(capturedDecl)) {
        if (!func->getCaptureInfo().hasBeenComputed()) {
          // Check later.
          TC.ForwardCapturedFuncs[func].push_back(AFR);
          return true;
        }
        // Recursively check the transitive captures.
        capturePath.push_back(func);
        SWIFT_DEFER { capturePath.pop_back(); };
        for (auto capture : func->getCaptureInfo().getCaptures())
          if (!validateForwardCapture(capture.getDecl()))
            return false;
        return true;
      }

      // Diagnose the improper forward capture.
      if (Diagnosed.insert(capturedDecl).second) {
        if (capturedDecl == DRE->getDecl()) {
          TC.diagnose(DRE->getLoc(), diag::capture_before_declaration,
                      capturedDecl->getBaseName().getIdentifier());
        } else {
          TC.diagnose(DRE->getLoc(),
                      diag::transitive_capture_before_declaration,
                      DRE->getDecl()->getBaseName().getIdentifier(),
                      capturedDecl->getBaseName().getIdentifier());
          ValueDecl *prevDecl = capturedDecl;
          for (auto path : reversed(capturePath)) {
            TC.diagnose(path->getLoc(),
                        diag::transitive_capture_through_here,
                        path->getName(),
                        prevDecl->getBaseName().getIdentifier());
            prevDecl = path;
          }
        }
        TC.diagnose(capturedDecl, diag::decl_declared_here,
                    capturedDecl->getFullName());
      }
      return false;
    };

    if (!validateForwardCapture(DRE->getDecl()))
      return { false, DRE };

    bool isInOut = (isa<ParamDecl>(D) && cast<ParamDecl>(D)->isInOut());
    bool isNested = false;
    if (auto f = AFR.getAbstractFunctionDecl())
      isNested = f->getDeclContext()->isLocalContext();

    if (isInOut && !AFR.isKnownNoEscape() && !isNested) {
      if (D->getBaseName() == D->getASTContext().Id_self) {
        TC.diagnose(DRE->getLoc(),
          diag::closure_implicit_capture_mutating_self);
      } else {
        TC.diagnose(DRE->getLoc(),
          diag::closure_implicit_capture_without_noescape);
      }
      return { false, DRE };
    }

    // We're going to capture this, compute flags for the capture.
    unsigned Flags = 0;

    // If this is a direct reference to underlying storage, then this is a
    // capture of the storage address - not a capture of the getter/setter.
    if (DRE->getAccessSemantics() == AccessSemantics::DirectToStorage)
      Flags |= CapturedValue::IsDirect;

    // If the closure is noescape, then we can capture the decl as noescape.
    if (AFR.isKnownNoEscape())
      Flags |= CapturedValue::IsNoEscape;

    addCapture(CapturedValue(D, Flags), DRE->getStartLoc());
    return { false, DRE };
  }

  void propagateCaptures(AnyFunctionRef innerClosure, SourceLoc captureLoc) {
    TC.computeCaptures(innerClosure);

    auto CurDC = AFR.getAsDeclContext();
    bool isNoEscapeClosure = AFR.isKnownNoEscape();

    auto &captureInfo = innerClosure.getCaptureInfo();

    for (auto capture : captureInfo.getCaptures()) {
      // If the decl was captured from us, it isn't captured *by* us.
      if (capture.getDecl()->getDeclContext() == CurDC)
        continue;

      // Compute adjusted flags.
      unsigned Flags = capture.getFlags();

      // The decl is captured normally, even if it was captured directly
      // in the subclosure.
      Flags &= ~CapturedValue::IsDirect;

      // If this is an escaping closure, then any captured decls are also
      // escaping, even if they are coming from an inner noescape closure.
      if (!isNoEscapeClosure)
        Flags &= ~CapturedValue::IsNoEscape;

      addCapture(CapturedValue(capture.getDecl(), Flags), captureLoc);
    }

    if (GenericParamCaptureLoc.isInvalid())
      if (captureInfo.hasGenericParamCaptures())
        GenericParamCaptureLoc = getCaptureLoc(innerClosure);

    if (DynamicSelfCaptureLoc.isInvalid())
      if (captureInfo.hasDynamicSelfCapture()) {
        DynamicSelfCaptureLoc = getCaptureLoc(innerClosure);
        DynamicSelf = captureInfo.getDynamicSelfType();
      }
  }

  bool walkToDeclPre(Decl *D) override {
    if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
      propagateCaptures(AFD, AFD->getLoc());

      // Can default parameter initializers capture state?  That seems like
      // a really bad idea.
      for (auto *paramList : AFD->getParameterLists())
        for (auto param : *paramList) {
          if (auto E = param->getDefaultValue())
            E->walk(*this);
        }
      return false;
    }

    return true;
  }

  bool usesTypeMetadataOfFormalType(Expr *E) {
    // For non-ObjC closures, assume the type metadata is always used.
    if (!AFR.isObjC())
      return true;

    if (!E->getType() || E->getType()->hasError())
      return false;

    // We can use Objective-C generics in limited ways without reifying
    // their type metadata, meaning we don't need to capture their generic
    // params.

    // Look through one layer of optionality when considering the class-

    // Referring to a class-constrained generic or metatype
    // doesn't require its type metadata.
    if (auto declRef = dyn_cast<DeclRefExpr>(E))
      return (!declRef->getDecl()->isObjC()
              && !E->getType()->getWithoutSpecifierType()
                              ->hasRetainablePointerRepresentation()
              && !E->getType()->getWithoutSpecifierType()
                              ->is<AnyMetatypeType>());

    // Loading classes or metatypes doesn't require their metadata.
    if (isa<LoadExpr>(E))
      return (!E->getType()->hasRetainablePointerRepresentation()
              && !E->getType()->is<AnyMetatypeType>());

    // Accessing @objc members doesn't require type metadata.
    // rdar://problem/27796375 -- allocating init entry points for ObjC
    // initializers are generated as true Swift generics, so reify type
    // parameters.
    if (auto memberRef = dyn_cast<MemberRefExpr>(E))
      return !memberRef->getMember().getDecl()->hasClangNode();

    if (auto applyExpr = dyn_cast<ApplyExpr>(E)) {
      if (auto methodApply = dyn_cast<ApplyExpr>(applyExpr->getFn())) {
        if (auto callee = dyn_cast<DeclRefExpr>(methodApply->getFn())) {
          return !callee->getDecl()->isObjC()
            || isa<ConstructorDecl>(callee->getDecl());
        }
      }
      if (auto callee = dyn_cast<DeclRefExpr>(applyExpr->getFn())) {
        return !callee->getDecl()->isObjC()
          || isa<ConstructorDecl>(callee->getDecl());
      }
    }

    if (auto subscriptExpr = dyn_cast<SubscriptExpr>(E)) {
      return (subscriptExpr->hasDecl() &&
              !subscriptExpr->getDecl().getDecl()->isObjC());
    }

    // Getting the dynamic type of a class doesn't require type metadata.
    if (isa<DynamicTypeExpr>(E))
      return (!E->getType()->castTo<AnyMetatypeType>()->getInstanceType()
                  ->hasRetainablePointerRepresentation());

    // Building a fixed-size tuple doesn't require type metadata.
    // Approximate this for the purposes of being able to invoke @objc methods
    // by considering tuples of ObjC-representable types to not use metadata.
    if (auto tuple = dyn_cast<TupleExpr>(E)) {
      for (auto elt : tuple->getType()->castTo<TupleType>()->getElements()) {
        if (!elt.getType()->isRepresentableIn(ForeignLanguage::ObjectiveC,
                                              AFR.getAsDeclContext()))
          return true;
      }
      return false;
    }

    // Coercion by itself is a no-op.
    if (isa<CoerceExpr>(E))
      return false;

    // Upcasting doesn't require type metadata.
    if (isa<DerivedToBaseExpr>(E))
      return false;
    if (isa<ArchetypeToSuperExpr>(E))
      return false;
    if (isa<CovariantReturnConversionExpr>(E))
      return false;
    if (isa<MetatypeConversionExpr>(E))
      return false;

    // Identity expressions are no-ops.
    if (isa<IdentityExpr>(E))
      return false;

    // Discarding an assignment is a no-op.
    if (isa<DiscardAssignmentExpr>(E))
      return false;

    // Opening an @objc existential or metatype is a no-op.
    if (auto open = dyn_cast<OpenExistentialExpr>(E))
      return (!open->getSubExpr()->getType()->isObjCExistentialType()
              && !open->getSubExpr()->getType()->is<AnyMetatypeType>());

    // Erasure to an ObjC existential or between metatypes doesn't require
    // type metadata.
    if (auto erasure = dyn_cast<ErasureExpr>(E)) {
      if (E->getType()->isObjCExistentialType()
          || E->getType()->is<AnyMetatypeType>())
        return false;
      
      // We also special case Any erasure in pseudogeneric contexts
      // not to rely on concrete type metadata by erasing from AnyObject
      // as a waypoint.
      if (E->getType()->isAny()
          && erasure->getSubExpr()->getType()->is<ArchetypeType>())
        return false;

      // Erasure to a Swift protocol always captures the type metadata from
      // its subexpression.
      checkType(erasure->getSubExpr()->getType(),
                erasure->getSubExpr()->getLoc());
      return true;
    }

    
    // Converting an @objc metatype to AnyObject doesn't require type
    // metadata.
    if (isa<ClassMetatypeToObjectExpr>(E)
        || isa<ExistentialMetatypeToObjectExpr>(E))
      return false;
    
    // Casting to an ObjC class doesn't require the metadata of its type
    // parameters, if any.
    if (auto cast = dyn_cast<CheckedCastExpr>(E)) {
      // If we failed to resolve the written type, we've emitted an
      // earlier diagnostic and should bail.
      auto toTy = cast->getCastTypeLoc().getType();
      if (!toTy || toTy->hasError())
        return false;

      if (auto clas = dyn_cast_or_null<ClassDecl>(
                         cast->getCastTypeLoc().getType()->getAnyNominal())) {
        if (clas->usesObjCGenericsModel()) {
          return false;
        }
      }
    }
    
    // Assigning an object doesn't require type metadata.
    if (auto assignment = dyn_cast<AssignExpr>(E))
      return assignment->getSrc()->getType() &&
        !assignment->getSrc()->getType()
            ->hasRetainablePointerRepresentation();

    return true;
  }

  std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
    if (usesTypeMetadataOfFormalType(E)) {
      checkType(E->getType(), E->getLoc());
    }

    // Some kinds of expression don't really evaluate their subexpression,
    // so we don't need to traverse.
    if (isa<ObjCSelectorExpr>(E)) {
      return { false, E };
    }

    if (auto *ECE = dyn_cast<ExplicitCastExpr>(E)) {
      checkType(ECE->getCastTypeLoc().getType(), ECE->getLoc());
      return { true, E };
    }

    if (auto *DRE = dyn_cast<DeclRefExpr>(E))
      return walkToDeclRefExpr(DRE);

    // When we see a reference to the 'super' expression, capture 'self' decl.
    if (auto *superE = dyn_cast<SuperRefExpr>(E)) {
      auto CurDC = AFR.getAsDeclContext();
      if (CurDC->isChildContextOf(superE->getSelf()->getDeclContext()))
        addCapture(CapturedValue(superE->getSelf(), 0), superE->getLoc());
      return { false, superE };
    }

    // Don't recur into child closures. They should already have a capture
    // list computed; we just propagate it, filtering out stuff that they
    // capture from us.
    if (auto *SubCE = dyn_cast<AbstractClosureExpr>(E)) {
      propagateCaptures(SubCE, SubCE->getStartLoc());
      return { false, E };
    }

    return { true, E };
  }
};

} // end anonymous namespace

void TypeChecker::maybeDiagnoseCaptures(Expr *E, AnyFunctionRef AFR) {
  if (!AFR.getCaptureInfo().hasBeenComputed()) {
    // The capture list is not always initialized by the point we reference
    // it. Remember we formed a C function pointer so we can diagnose later
    // if necessary.
    LocalCFunctionPointers[AFR].push_back(E);
    return;
  }

  if (AFR.getCaptureInfo().hasGenericParamCaptures() ||
      AFR.getCaptureInfo().hasDynamicSelfCapture() ||
      AFR.getCaptureInfo().hasLocalCaptures()) {
    unsigned kind;
    if (AFR.getCaptureInfo().hasLocalCaptures())
      kind = 0;
    else if (AFR.getCaptureInfo().hasGenericParamCaptures())
      kind = 1;
    else
      kind = 2;
    diagnose(E->getLoc(),
             diag::c_function_pointer_from_function_with_context,
             /*closure*/ AFR.getAbstractClosureExpr() != nullptr,
             kind);
  }
}

void TypeChecker::computeCaptures(AnyFunctionRef AFR) {
  if (AFR.getCaptureInfo().hasBeenComputed())
    return;

  SmallVector<CapturedValue, 4> Captures;
  SourceLoc GenericParamCaptureLoc;
  SourceLoc DynamicSelfCaptureLoc;
  DynamicSelfType *DynamicSelf = nullptr;
  FindCapturedVars finder(*this, Captures,
                          GenericParamCaptureLoc,
                          DynamicSelfCaptureLoc,
                          DynamicSelf,
                          AFR);
  AFR.getBody()->walk(finder);

  unsigned inoutCount = 0;
  for (auto C : Captures) {
    if (auto PD = dyn_cast<ParamDecl>(C.getDecl()))
      if (PD->isInOut())
        inoutCount++;
  }

  if (inoutCount > 0) {
    if (auto e = AFR.getAbstractFunctionDecl()) {
      for (auto returnOccurrence : getEscapingFunctionAsReturnValue(e)) {
        diagnose(returnOccurrence->getReturnLoc(),
          diag::nested_function_escaping_inout_capture);
      }
      auto occurrences = getEscapingFunctionAsArgument(e);
      for (auto occurrence : occurrences) {
        diagnose(occurrence->getLoc(),
          diag::nested_function_with_implicit_capture_argument,
          inoutCount > 1);
      }
    }
  }

  if (AFR.hasType() && !AFR.isObjC()) {
    finder.checkType(AFR.getType(), getCaptureLoc(AFR));
  }

  // If this is an init(), explicitly walk the initializer values for members of
  // the type.  They will be implicitly emitted by SILGen into the generated
  // initializer.
  if (auto CD =
        dyn_cast_or_null<ConstructorDecl>(AFR.getAbstractFunctionDecl())) {
    auto *typeDecl = dyn_cast<NominalTypeDecl>(CD->getDeclContext());
    if (typeDecl && CD->isDesignatedInit()) {
      for (auto member : typeDecl->getMembers()) {
        // Ignore everything other than PBDs.
        auto *PBD = dyn_cast<PatternBindingDecl>(member);
        if (!PBD) continue;
        // Walk the initializers for all properties declared in the type with
        // an initializer.
        for (auto &elt : PBD->getPatternList())
          if (auto *init = elt.getInit())
            init->walk(finder);
      }
    }
  }

  // A generic function always captures outer generic parameters.
  auto *AFD = AFR.getAbstractFunctionDecl();
  if (AFD) {
    if (AFD->getGenericParams())
      AFR.getCaptureInfo().setGenericParamCaptures(true);
  }

  // Only local functions capture dynamic 'Self'.
  if (AFR.getAsDeclContext()->getParent()->isLocalContext()) {
    if (GenericParamCaptureLoc.isValid())
      AFR.getCaptureInfo().setGenericParamCaptures(true);

    if (DynamicSelfCaptureLoc.isValid())
      AFR.getCaptureInfo().setDynamicSelfType(DynamicSelf);
  }

  if (Captures.empty())
    AFR.getCaptureInfo().setCaptures(None);
  else
    AFR.getCaptureInfo().setCaptures(Context.AllocateCopy(Captures));

  // Extensions of generic ObjC functions can't use generic parameters from
  // their context.
  if (AFD && GenericParamCaptureLoc.isValid()) {
    if (auto Clas = AFD->getParent()->getAsClassOrClassExtensionContext()) {
      if (Clas->isGenericContext() && Clas->hasClangNode()) {
        diagnose(AFD->getLoc(),
                 diag::objc_generic_extension_using_type_parameter);
        diagnose(GenericParamCaptureLoc,
                 diag::objc_generic_extension_using_type_parameter_here);
      }
    }
  }

  // Diagnose if we have local captures and there were C pointers formed to
  // this function before we computed captures.
  auto cFunctionPointers = LocalCFunctionPointers.find(AFR);
  if (cFunctionPointers != LocalCFunctionPointers.end())
    for (auto *expr : cFunctionPointers->second)
      maybeDiagnoseCaptures(expr, AFR);
}
