//===--- ASTScopeImpl.h - Swift AST Object-Oriented Scope --------*- C++-*-===//
//
// 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 defines the ASTScopeImpl class ontology, which
/// describes the scopes that exist within a Swift AST.
///
/// Each scope has four basic functions: printing for debugging, creation of
/// itself and its children, obtaining its SourceRange (for lookup), and looking
/// up names accessible from that scope.
///
/// Invariants:
///   a child's source range is a subset (proper or improper) of its parent's,
///   children are ordered by source range, and do not overlap,
///   all the names visible within a parent are visible within the child, unless
///   the nesting is illegal. For instance, a protocol nested inside of a class
///   does not get to see the symbols in the class or its ancestors.
///
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_AST_SCOPE_H
#define SWIFT_AST_AST_SCOPE_H

#include "swift/AST/ASTNode.h"
#include "swift/AST/NameLookup.h" // for DeclVisibilityKind
#include "swift/Basic/Compiler.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"

/// In case there's a bug in the ASTScope lookup system, suggest that the user
/// try disabling it.
/// \p message must be a string literal
#define ASTScopeAssert(predicate, message)                                     \
  assert((predicate) && message                                                \
         " Try compiling with '-disable-astscope-lookup'.")

#define ASTScope_unreachable(message)                                          \
  llvm_unreachable(message " Try compiling with '-disable-astscope-lookup'.")

namespace swift {

#pragma mark Forward-references

#define DECL(Id, Parent) class Id##Decl;
#define ABSTRACT_DECL(Id, Parent) class Id##Decl;
#include "swift/AST/DeclNodes.def"
#undef DECL
#undef ABSTRACT_DECL

#define EXPR(Id, Parent) class Id##Expr;
#include "swift/AST/ExprNodes.def"
#undef EXPR

#define STMT(Id, Parent) class Id##Stmt;
#define ABSTRACT_STMT(Id, Parent) class Id##Stmt;
#include "swift/AST/StmtNodes.def"
#undef STMT
#undef ABSTRACT_STMT

class GenericParamList;
class TrailingWhereClause;
class ParameterList;
class PatternBindingEntry;
class SpecializeAttr;
class GenericContext;
class DeclName;
class StmtConditionElement;

namespace ast_scope {
class ASTScopeImpl;
class GenericTypeOrExtensionScope;
class IterableTypeScope;
class TypeAliasScope;
class ScopeCreator;

struct AnnotatedInsertionPoint {
  ASTScopeImpl *insertionPoint;
  const char *explanation;
};

#pragma mark the root ASTScopeImpl class

/// Describes a lexical scope within a source file.
///
/// Each \c ASTScopeImpl is a node within a tree that describes all of the
/// lexical scopes within a particular source range. The root of this scope tree
/// is always a \c SourceFile node, and the tree covers the entire source file.
/// The children of a particular node are the lexical scopes immediately
/// nested within that node, and have source ranges that are enclosed within
/// the source range of their parent node. At the leaves are lexical scopes
/// that cannot be subdivided further.
///
/// The tree provides source-location-based query operations, allowing one to
/// find the innermost scope that contains a given source location. Navigation
/// to parent nodes from that scope allows one to walk the lexically enclosing
/// scopes outward to the source file. Given a scope, one can also query the
/// associated \c DeclContext for additional contextual information.
///
/// \code
/// -dump-scope-maps expanded
/// \endcode
class ASTScopeImpl {
  friend class NodeAdder;
  friend class Portion;
  friend class GenericTypeOrExtensionWholePortion;
  friend class NomExtDeclPortion;
  friend class GenericTypeOrExtensionWherePortion;
  friend class GenericTypeOrExtensionWherePortion;
  friend class IterableTypeBodyPortion;
  friend class ScopeCreator;

#pragma mark - tree state
protected:
  using Children = SmallVector<ASTScopeImpl *, 4>;
  /// Whether the given parent is the accessor node for an abstract
  /// storage declaration or is directly descended from it.

private:
  /// Always set by the constructor, so that when creating a child
  /// the parent chain is available.
  ASTScopeImpl *parent = nullptr; // null at the root

  /// Child scopes, sorted by source range.
  /// Must clear source range change whenever this changes
  Children storedChildren;

  bool wasExpanded = false;

  /// For use-before-def, ASTAncestor scopes may be added to a BraceStmt.
  unsigned astAncestorScopeCount = 0;

  /// Can clear storedChildren, so must remember this
  bool haveAddedCleanup = false;

  // Must be updated after last child is added and after last child's source
  // position is known
  mutable Optional<SourceRange> cachedSourceRange;

  // When ignoring ASTNodes in a scope, they still must count towards a scope's
  // source range. So include their ranges here
  SourceRange sourceRangeOfIgnoredASTNodes;

#pragma mark - constructor / destructor
public:
  ASTScopeImpl(){};
  // TOD: clean up all destructors and deleters
  virtual ~ASTScopeImpl() {}

  ASTScopeImpl(ASTScopeImpl &&) = delete;
  ASTScopeImpl &operator=(ASTScopeImpl &&) = delete;
  ASTScopeImpl(const ASTScopeImpl &) = delete;
  ASTScopeImpl &operator=(const ASTScopeImpl &) = delete;

  // Make vanilla new illegal for ASTScopes.
  void *operator new(size_t bytes) = delete;
  // Need this because have virtual destructors
  void operator delete(void *data) {}

  // Only allow allocation of scopes using the allocator of a particular source
  // file.
  void *operator new(size_t bytes, const ASTContext &ctx,
                     unsigned alignment = alignof(ASTScopeImpl));
  void *operator new(size_t Bytes, void *Mem) {
    ASTScopeAssert(Mem, "Allocation failed");
    return Mem;
  }

#pragma mark - tree declarations
protected:
  NullablePtr<ASTScopeImpl> getParent() { return parent; }
  NullablePtr<const ASTScopeImpl> getParent() const { return parent; }

  const Children &getChildren() const { return storedChildren; }

  /// Get ride of descendants and remove them from scopedNodes so the scopes
  /// can be recreated. Needed because typechecking inserts a return statment
  /// into intiailizers.
  void disownDescendants(ScopeCreator &);

public: // for addReusedBodyScopes
  void addChild(ASTScopeImpl *child, ASTContext &);
  std::vector<ASTScopeImpl *> rescueASTAncestorScopesForReuseFromMe();

  /// When reexpanding, do we always create a new body?
  virtual NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued();
  std::vector<ASTScopeImpl *>
  rescueASTAncestorScopesForReuseFromMeOrDescendants();
  void replaceASTAncestorScopes(ArrayRef<ASTScopeImpl *>);

private:
  void removeChildren();

private:
  void emancipate() { parent = nullptr; }
  NullablePtr<ASTScopeImpl> getPriorSibling() const;

public:
  void preOrderDo(function_ref<void(ASTScopeImpl *)>);
  /// Like preorderDo but without myself.
  void preOrderChildrenDo(function_ref<void(ASTScopeImpl *)>);
  void postOrderDo(function_ref<void(ASTScopeImpl *)>);

#pragma mark - source ranges

#pragma mark - source range queries

public:
  SourceRange getSourceRangeOfScope(bool omitAssertions = false) const;

  /// InterpolatedStringLiteralExprs and EditorPlaceHolders respond to
  /// getSourceRange with the starting point. But we might be asked to lookup an
  /// identifer within one of them. So, find the real source range of them here.
  SourceRange getEffectiveSourceRange(ASTNode) const;

  void computeAndCacheSourceRangeOfScope(bool omitAssertions = false) const;
  bool isSourceRangeCached(bool omitAssertions = false) const;

  bool checkSourceRangeOfThisASTNode() const;

  /// For debugging
  bool doesRangeMatch(unsigned start, unsigned end, StringRef file = "",
                      StringRef className = "");

  unsigned countDescendants() const;

  /// Make sure that when the argument is executed, there are as many
  /// descendants after as before.
  void assertThatTreeDoesNotShrink(function_ref<void()>);

private:
  SourceRange computeSourceRangeOfScope(bool omitAssertions = false) const;
  SourceRange
  computeSourceRangeOfScopeWithChildASTNodes(bool omitAssertions = false) const;
  bool ensureNoAncestorsSourceRangeIsCached() const;

#pragma mark - source range adjustments
private:
  SourceRange widenSourceRangeForIgnoredASTNodes(SourceRange range) const;

  /// If the scope refers to a Decl whose source range tells the whole story,
  /// for example a NominalTypeScope, it is not necessary to widen the source
  /// range by examining the children. In that case we could just return
  /// the childlessRange here.
  /// But, we have not marked such scopes yet. Doing so would be an
  /// optimization.
  SourceRange widenSourceRangeForChildren(SourceRange range,
                                          bool omitAssertions) const;

  /// Even ASTNodes that do not form scopes must be included in a Scope's source
  /// range. Widen the source range of the receiver to include the (ignored)
  /// node.
  void widenSourceRangeForIgnoredASTNode(ASTNode);

private:
  void clearCachedSourceRangesOfMeAndAncestors();

public:
  /// Since source ranges are cached but depend on child ranges,
  /// when descendants are added, my and my ancestor ranges must be
  /// recalculated.
  void ensureSourceRangesAreCorrectWhenAddingDescendants(function_ref<void()>);

public: // public for debugging
  /// Returns source range of this node alone, without factoring in any
  /// children.
  virtual SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const = 0;

protected:
  SourceManager &getSourceManager() const;
  bool hasValidSourceRange() const;
  bool hasValidSourceRangeOfIgnoredASTNodes() const;
  bool precedesInSource(const ASTScopeImpl *) const;
  bool verifyThatChildrenAreContainedWithin(SourceRange) const;
  bool verifyThatThisNodeComeAfterItsPriorSibling() const;

  virtual SourceRange
  getSourceRangeOfEnclosedParamsOfASTNode(bool omitAssertions) const;

private:
  bool checkSourceRangeAfterExpansion(const ASTContext &) const;

#pragma mark common queries
public:
  virtual NullablePtr<ClosureExpr> getClosureIfClosureScope() const;
  virtual ASTContext &getASTContext() const;
  virtual NullablePtr<DeclContext> getDeclContext() const;
  virtual NullablePtr<Decl> getDeclIfAny() const { return nullptr; };
  virtual NullablePtr<Stmt> getStmtIfAny() const { return nullptr; };
  virtual NullablePtr<Expr> getExprIfAny() const { return nullptr; };
  virtual NullablePtr<DeclAttribute> getDeclAttributeIfAny() const {
    return nullptr;
  }
  virtual NullablePtr<const void> getReferrent() const { return nullptr; }

#pragma mark - debugging and printing

public:
  virtual const SourceFile *getSourceFile() const;
  virtual std::string getClassName() const = 0;

  /// Print out this scope for debugging/reporting purposes.
  void print(llvm::raw_ostream &out, unsigned level = 0, bool lastChild = false,
             bool printChildren = true) const;

  void printRange(llvm::raw_ostream &out) const;

protected:
  virtual void printSpecifics(llvm::raw_ostream &out) const {}
  virtual NullablePtr<const void> addressForPrinting() const;

public:
  LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED,
                            "only for use within the debugger");

  void dumpOneScopeMapLocation(std::pair<unsigned, unsigned> lineColumn);

private:
  llvm::raw_ostream &verificationError() const;

#pragma mark - Scope tree creation
public:
  /// expandScope me, sending deferred nodes to my descendants.
  /// Return the scope into which to place subsequent decls
  ASTScopeImpl *expandAndBeCurrent(ScopeCreator &);

  unsigned getASTAncestorScopeCount() const { return astAncestorScopeCount; }
  bool getWasExpanded() const { return wasExpanded; }

protected:
  void resetASTAncestorScopeCount() { astAncestorScopeCount = 0; }
  void increaseASTAncestorScopeCount(unsigned c) { astAncestorScopeCount += c; }
  void setWasExpanded() { wasExpanded = true; }
  virtual ASTScopeImpl *expandSpecifically(ScopeCreator &) = 0;
  virtual void beCurrent();
  bool isCurrent() const;
  virtual bool isCurrentIfWasExpanded() const;

private:
  /// Compare the pre-expasion range with the post-expansion range and return
  /// false if lazyiness couild miss lookups.
  bool checkLazySourceRange(const ASTContext &) const;

public:
  /// Some scopes can be expanded lazily.
  /// Such scopes must: not change their source ranges after expansion, and
  /// their expansion must return an insertion point outside themselves.
  /// After a node is expanded, its source range (getSourceRangeofThisASTNode
  /// union children's ranges) must be same as this.
  virtual NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion();
  virtual SourceRange sourceRangeForDeferredExpansion() const;

public:
  // Some nodes (VarDecls and Accessors) are created directly from
  // pattern scope code and should neither be deferred nor should
  // contribute to widenSourceRangeForIgnoredASTNode.
  // Closures and captures are also created directly but are
  // screened out because they are expressions.
  static bool isHandledSpeciallyByPatterns(const ASTNode n);

  virtual NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const;

  bool isATypeDeclScope() const;

  /// There are several places in the compiler that mutate the AST after the
  /// fact, above and beyond adding Decls to the SourceFile. These are
  /// documented in: rdar://53018839, rdar://53027266, rdar://53027733,
  /// rdar://53028050
  /// Return true if did reexpand
  bool reexpandIfObsolete(ScopeCreator &);

private:
  void reexpand(ScopeCreator &);

  virtual ScopeCreator &getScopeCreator();

#pragma mark - - creation queries
public:
  virtual bool isThisAnAbstractStorageDecl() const { return false; }

#pragma mark - lookup

public:
  using DeclConsumer = namelookup::AbstractASTScopeDeclConsumer &;

  /// Entry point into ASTScopeImpl-land for lookups
  static llvm::SmallVector<const ASTScopeImpl *, 0>
  unqualifiedLookup(SourceFile *, DeclName, SourceLoc,
                    const DeclContext *startingContext, DeclConsumer);

  static Optional<bool>
  computeIsCascadingUse(ArrayRef<const ASTScopeImpl *> history,
                        Optional<bool> initialIsCascadingUse);

#pragma mark - - lookup- starting point
private:
  static const ASTScopeImpl *findStartingScopeForLookup(SourceFile *,
                                                        const DeclName name,
                                                        const SourceLoc where,
                                                        const DeclContext *ctx);

protected:
  virtual bool doesContextMatchStartingContext(const DeclContext *) const;

protected:
  /// Not const because may reexpand some scopes.
  const ASTScopeImpl *findInnermostEnclosingScope(SourceLoc,
                                                  NullablePtr<raw_ostream>);
  const ASTScopeImpl *findInnermostEnclosingScopeImpl(SourceLoc,
                                                      NullablePtr<raw_ostream>,
                                                      SourceManager &,
                                                      ScopeCreator &);

private:
  NullablePtr<ASTScopeImpl> findChildContaining(SourceLoc loc,
                                                SourceManager &sourceMgr) const;

#pragma mark - - lookup- per scope
protected:
  /// The main (recursive) lookup function:
  /// Tell DeclConsumer about all names found in this scope and if not done,
  /// recurse for enclosing scopes. Stop lookup if about to look in limit.
  /// Return final value for isCascadingUse
  ///
  /// If the lookup depends on implicit self, selfDC is its context.
  /// (Names in extensions never depend on self.)
  ///
  /// In a Nominal, Extension, or TypeAliasScope, the lookup can start at either
  /// the body portion (for the first two), the where portion, or a
  /// GenericParamScope. In every case, the generics on the type decl must be
  /// searched, but only once. And they must be searched *before* the generic
  /// parameters. For instance, the following is correct: \code class
  /// ShadowingGenericParameter<T> { \code   typealias T = Int;  func foo (t :
  /// T) {} \code } \code ShadowingGenericParameter<String>().foo(t: "hi")
  ///
  /// So keep track of the last generic param list searched to avoid
  /// duplicating work.
  ///
  /// Look in this scope.
  /// \param history are the scopes traversed for this lookup (including this
  /// one) \param limit A scope into which lookup should not go. See \c
  /// getLookupLimit. \param lastListSearched Last list searched.
  /// \param consumer is the object to which found decls are reported.
  void lookup(llvm::SmallVectorImpl<const ASTScopeImpl *> &history,
              NullablePtr<const ASTScopeImpl> limit,
              NullablePtr<const GenericParamList> lastListSearched,
              DeclConsumer consumer) const;

public:
  /// Returns the SelfDC for parent (and possibly ancestor) scopes.
  /// A return of None indicates that the previous child (in history) should be
  /// asked.
  virtual Optional<NullablePtr<DeclContext>> computeSelfDCForParent() const;

protected:
  /// Find either locals or members (no scope has both)
  /// \param history The scopes visited since the start of lookup (including
  /// this one)
  /// \return True if lookup is done
  virtual bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *> history,
                                     DeclConsumer consumer) const;

  /// Returns isDone and the list searched, if any
  std::pair<bool, NullablePtr<const GenericParamList>>
  lookInMyGenericParameters(
      NullablePtr<const GenericParamList> priorListSearched,
      DeclConsumer consumer) const;

  virtual NullablePtr<const GenericParamList> genericParams() const;

  // Consume the generic parameters in the context and its outer contexts
  static bool lookInGenericParametersOf(NullablePtr<const GenericParamList>,
                                        DeclConsumer);

  NullablePtr<const ASTScopeImpl> parentIfNotChildOfTopScope() const {
    const auto *p = getParent().get();
    return p->getParent().isNonNull() ? p : nullptr;
  }

  /// The tree is organized by source location and for most nodes this is also
  /// what obtaines for scoping. However, guards are different. The scope after
  /// the guard else must hop into the innermoset scope of the guard condition.
  virtual NullablePtr<const ASTScopeImpl> getLookupParent() const {
    return parent;
  }

#pragma mark - - lookup- local bindings
protected:
  virtual Optional<bool>
  resolveIsCascadingUseForThisScope(Optional<bool>) const;

  // A local binding is a basically a local variable defined in that very scope
  // It is not an instance variable or inherited type.

  static bool lookupLocalBindingsInPattern(Pattern *p,
                                           DeclVisibilityKind vis,
                                           DeclConsumer consumer);

  /// When lookup must stop before the outermost scope, return the scope to stop
  /// at. Example, if a protocol is nested in a struct, we must stop before
  /// looking into the struct.
  ///
  /// Ultimately, the task of rejecting results found in inapplicable outer
  /// scopes is best moved to the clients of the ASTScope lookup subsystem. It
  /// seems out of place here.
  virtual NullablePtr<const ASTScopeImpl> getLookupLimit() const;

  NullablePtr<const ASTScopeImpl>
  ancestorWithDeclSatisfying(function_ref<bool(const Decl *)> predicate) const;
}; // end of ASTScopeImpl

#pragma mark - specific scope classes

/// The root of the scope tree.
class ASTSourceFileScope final : public ASTScopeImpl {
public:
  SourceFile *const SF;
  ScopeCreator *const scopeCreator;
  ASTScopeImpl *insertionPoint;

  /// The number of \c Decls in the \c SourceFile that were already seen.
  /// Since parsing can be interleaved with type-checking, on every
  /// lookup, look at creating scopes for any \c Decls beyond this number.
  /// rdar://55562483 Unify with numberOfChildrenWhenLastExpanded
  int numberOfDeclsAlreadySeen = 0;

  ASTSourceFileScope(SourceFile *SF, ScopeCreator *scopeCreator);

  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  NullablePtr<DeclContext> getDeclContext() const override;

  void addNewDeclsToScopeTree();
  void buildFullyExpandedTree();
  void
  buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();

  const SourceFile *getSourceFile() const override;
  NullablePtr<const void> addressForPrinting() const override { return SF; }
  bool crossCheckWithAST();

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

  ScopeCreator &getScopeCreator() override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
};

class Portion {
public:
  const char *portionName;
  Portion(const char *n) : portionName(n) {}
  virtual ~Portion() {}

  // Make vanilla new illegal for ASTScopes.
  void *operator new(size_t bytes) = delete;
  // Need this because have virtual destructors
  void operator delete(void *data) {}

  // Only allow allocation of scopes using the allocator of a particular source
  // file.
  void *operator new(size_t bytes, const ASTContext &ctx,
                     unsigned alignment = alignof(ASTScopeImpl));
  void *operator new(size_t Bytes, void *Mem) {
    ASTScopeAssert(Mem, "Allocation failed");
    return Mem;
  }

  /// Return the new insertion point
  virtual ASTScopeImpl *expandScope(GenericTypeOrExtensionScope *,
                                    ScopeCreator &) const = 0;

  virtual SourceRange
  getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *scope,
                            bool omitAssertions) const = 0;

  /// Returns isDone and isCascadingUse
  virtual bool lookupMembersOf(const GenericTypeOrExtensionScope *scope,
                               ArrayRef<const ASTScopeImpl *>,
                               ASTScopeImpl::DeclConsumer consumer) const;

  virtual NullablePtr<const ASTScopeImpl>
  getLookupLimitFor(const GenericTypeOrExtensionScope *) const;

  virtual const Decl *
  getReferrentOfScope(const GenericTypeOrExtensionScope *s) const;

  virtual void beCurrent(IterableTypeScope *) const = 0;
  virtual bool isCurrentIfWasExpanded(const IterableTypeScope *) const = 0;
  virtual NullablePtr<ASTScopeImpl>
  insertionPointForDeferredExpansion(IterableTypeScope *) const = 0;
  virtual SourceRange
  sourceRangeForDeferredExpansion(const IterableTypeScope *) const = 0;
  };

  // For the whole Decl scope of a GenericType or an Extension
  class GenericTypeOrExtensionWholePortion final : public Portion {
  public:
    GenericTypeOrExtensionWholePortion() : Portion("Decl") {}
    virtual ~GenericTypeOrExtensionWholePortion() {}

    // Just for TypeAlias
    ASTScopeImpl *expandScope(GenericTypeOrExtensionScope *,
                              ScopeCreator &) const override;

    SourceRange getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *,
                                          bool omitAssertions) const override;

    NullablePtr<const ASTScopeImpl>
    getLookupLimitFor(const GenericTypeOrExtensionScope *) const override;

    const Decl *
    getReferrentOfScope(const GenericTypeOrExtensionScope *s) const override;

    /// Make whole portion lazy to avoid circularity in lookup of generic
    /// parameters of extensions. When \c bindExtension is called, it needs to
    /// unqualifed-lookup the type being extended. That causes an \c
    /// ExtensionScope
    /// (\c GenericTypeOrExtensionWholePortion) to be built.
    /// The building process needs the generic parameters, but that results in a
    /// request for the extended nominal type of the \c ExtensionDecl, which is
    /// an endless recursion. Although we only need to make \c ExtensionScope
    /// lazy, might as well do it for all \c IterableTypeScopes.

    void beCurrent(IterableTypeScope *) const override;
    bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;

    NullablePtr<ASTScopeImpl>
    insertionPointForDeferredExpansion(IterableTypeScope *) const override;
    SourceRange
    sourceRangeForDeferredExpansion(const IterableTypeScope *) const override;
  };

  /// GenericTypeOrExtension = GenericType or Extension
  class GenericTypeOrExtensionWhereOrBodyPortion : public Portion {
  public:
    GenericTypeOrExtensionWhereOrBodyPortion(const char *n) : Portion(n) {}
    virtual ~GenericTypeOrExtensionWhereOrBodyPortion() {}

    bool lookupMembersOf(const GenericTypeOrExtensionScope *scope,
                         ArrayRef<const ASTScopeImpl *>,
                         ASTScopeImpl::DeclConsumer consumer) const override;

  private:
    /// A client needs to know if a lookup result required the dynamic implicit
    /// self value. It is required if the lookup originates from a method body
    /// or a lazy pattern initializer. So, one approach would be to call the
    /// consumer to find members right from those scopes. However, because
    /// members aren't the first things searched, generics are, that approache
    /// ends up duplicating code from the \c GenericTypeOrExtensionScope. So we
    /// take the approach of doing those lookups there, and using this function
    /// to compute the selfDC from the history.
    static NullablePtr<DeclContext>
    computeSelfDC(ArrayRef<const ASTScopeImpl *> history);
};

/// Behavior specific to representing the trailing where clause of a
/// GenericTypeDecl or ExtensionDecl scope.
class GenericTypeOrExtensionWherePortion final
    : public GenericTypeOrExtensionWhereOrBodyPortion {
public:
  GenericTypeOrExtensionWherePortion()
      : GenericTypeOrExtensionWhereOrBodyPortion("Where") {}

  ASTScopeImpl *expandScope(GenericTypeOrExtensionScope *,
                            ScopeCreator &) const override;

  SourceRange getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *,
                                        bool omitAssertions) const override;

  void beCurrent(IterableTypeScope *) const override;
  bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;

  NullablePtr<ASTScopeImpl>
  insertionPointForDeferredExpansion(IterableTypeScope *) const override;
  SourceRange
  sourceRangeForDeferredExpansion(const IterableTypeScope *) const override;
};

/// Behavior specific to representing the Body of a NominalTypeDecl or
/// ExtensionDecl scope
class IterableTypeBodyPortion final
    : public GenericTypeOrExtensionWhereOrBodyPortion {
public:
  IterableTypeBodyPortion()
      : GenericTypeOrExtensionWhereOrBodyPortion("Body") {}

  ASTScopeImpl *expandScope(GenericTypeOrExtensionScope *,
                            ScopeCreator &) const override;
  SourceRange getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *,
                                        bool omitAssertions) const override;

  void beCurrent(IterableTypeScope *) const override;
  bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;
  NullablePtr<ASTScopeImpl>
  insertionPointForDeferredExpansion(IterableTypeScope *) const override;
  SourceRange
  sourceRangeForDeferredExpansion(const IterableTypeScope *) const override;
};

/// GenericType or Extension scope
/// : Whole type decl, trailing where clause, or body
class GenericTypeOrExtensionScope : public ASTScopeImpl {
public:
  const Portion *const portion;

  GenericTypeOrExtensionScope(const Portion *p) : portion(p) {}
  virtual ~GenericTypeOrExtensionScope() {}

  virtual NullablePtr<IterableDeclContext> getIterableDeclContext() const {
    return nullptr;
  }
  virtual bool shouldHaveABody() const { return false; }

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

public:
  virtual void expandBody(ScopeCreator &);

  virtual Decl *getDecl() const = 0;
  NullablePtr<Decl> getDeclIfAny() const override { return getDecl(); }
  NullablePtr<const void> getReferrent() const override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);

public:
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

  /// \c tryBindExtension needs to get the extended nominal, and the DeclContext
  /// is the parent of the \c ExtensionDecl. If the \c SourceRange of an \c
  /// ExtensionScope were to start where the \c ExtensionDecl says, the lookup
  /// source locaiton would fall within the \c ExtensionScope. This inclusion
  /// would cause the lazy \c ExtensionScope to be expanded which would ask for
  /// its generic parameters in order to create those sub-scopes. That request
  /// would cause a cycle because it would ask for the extended nominal. So,
  /// move the source range of an \c ExtensionScope *past* the extended nominal
  /// type, which is not in-scope there anyway.
  virtual SourceRange moveStartPastExtendedNominal(SourceRange) const = 0;

  virtual GenericContext *getGenericContext() const = 0;
  std::string getClassName() const override;
  virtual std::string declKindName() const = 0;
  virtual bool doesDeclHaveABody() const;
  const char *portionName() const { return portion->portionName; }
  Optional<NullablePtr<DeclContext>> computeSelfDCForParent() const override;

protected:
  Optional<bool> resolveIsCascadingUseForThisScope(
      Optional<bool> isCascadingUse) const override;

public:
  // Only for DeclScope, not BodyScope
  // Returns the where clause scope, or the parent if none
  virtual ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                                       ScopeCreator &);
  NullablePtr<DeclContext> getDeclContext() const override;
  virtual NullablePtr<NominalTypeDecl> getCorrespondingNominalTypeDecl() const {
    return nullptr;
  }

  virtual void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) {}

protected:
  bool
  lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *> history,
                        ASTScopeImpl::DeclConsumer consumer) const override;
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  NullablePtr<const ASTScopeImpl> getLookupLimit() const override;
  virtual NullablePtr<const ASTScopeImpl> getLookupLimitForDecl() const;
};

class GenericTypeScope : public GenericTypeOrExtensionScope {
public:
  GenericTypeScope(const Portion *p) : GenericTypeOrExtensionScope(p) {}
  virtual ~GenericTypeScope() {}
  SourceRange moveStartPastExtendedNominal(SourceRange) const override;

protected:
  NullablePtr<const GenericParamList> genericParams() const override;
};

class IterableTypeScope : public GenericTypeScope {
  /// Because of \c parseDelayedDecl members can get added after the tree is
  /// constructed, and they can be out of order. Detect this happening by
  /// remembering the member count.
  unsigned memberCount = 0;

public:
  IterableTypeScope(const Portion *p) : GenericTypeScope(p) {}
  virtual ~IterableTypeScope() {}

  virtual SourceRange getBraces() const = 0;
  bool shouldHaveABody() const override { return true; }
  bool doesDeclHaveABody() const override;
  void expandBody(ScopeCreator &) override;

protected:
  void beCurrent() override;
  bool isCurrentIfWasExpanded() const override;

public:
  void makeWholeCurrent();
  bool isWholeCurrent() const;
  void makeBodyCurrent();
  bool isBodyCurrent() const;
  NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion() override;
  SourceRange sourceRangeForDeferredExpansion() const override;

  void countBodies(ScopeCreator &) const;
};

class NominalTypeScope final : public IterableTypeScope {
public:
  NominalTypeDecl *decl;
  NominalTypeScope(const Portion *p, NominalTypeDecl *e)
      : IterableTypeScope(p), decl(e) {}
  virtual ~NominalTypeScope() {}

  std::string declKindName() const override { return "NominalType"; }
  NullablePtr<IterableDeclContext> getIterableDeclContext() const override {
    return decl;
  }
  NullablePtr<NominalTypeDecl>
  getCorrespondingNominalTypeDecl() const override {
    return decl;
  }
  GenericContext *getGenericContext() const override { return decl; }
  Decl *getDecl() const override { return decl; }

  SourceRange getBraces() const override;
  NullablePtr<const ASTScopeImpl> getLookupLimitForDecl() const override;

  void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) override;
  ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                               ScopeCreator &) override;
};

class ExtensionScope final : public IterableTypeScope {
public:
  ExtensionDecl *const decl;
  ExtensionScope(const Portion *p, ExtensionDecl *e)
      : IterableTypeScope(p), decl(e) {}
  virtual ~ExtensionScope() {}

  GenericContext *getGenericContext() const override { return decl; }
  NullablePtr<IterableDeclContext> getIterableDeclContext() const override {
    return decl;
  }
  NullablePtr<NominalTypeDecl> getCorrespondingNominalTypeDecl() const override;
  std::string declKindName() const override { return "Extension"; }
  SourceRange getBraces() const override;
  SourceRange moveStartPastExtendedNominal(SourceRange) const override;
  ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                               ScopeCreator &) override;
  void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) override;
  Decl *getDecl() const override { return decl; }
  NullablePtr<const ASTScopeImpl> getLookupLimitForDecl() const override;
protected:
  NullablePtr<const GenericParamList> genericParams() const override;
};

class TypeAliasScope final : public GenericTypeScope {
public:
  TypeAliasDecl *const decl;
  TypeAliasScope(const Portion *p, TypeAliasDecl *e)
      : GenericTypeScope(p), decl(e) {}
  virtual ~TypeAliasScope() {}

  std::string declKindName() const override { return "TypeAlias"; }
  ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                               ScopeCreator &) override;
  GenericContext *getGenericContext() const override { return decl; }
  Decl *getDecl() const override { return decl; }
};

class OpaqueTypeScope final : public GenericTypeScope {
public:
  OpaqueTypeDecl *const decl;
  OpaqueTypeScope(const Portion *p, OpaqueTypeDecl *e)
      : GenericTypeScope(p), decl(e) {}
  virtual ~OpaqueTypeScope() {}

  std::string declKindName() const override { return "OpaqueType"; }
  GenericContext *getGenericContext() const override { return decl; }
  Decl *getDecl() const override { return decl; }
};

/// Since each generic parameter can "see" the preceeding ones,
/// (e.g. <A, B: A>) -- it's not legal but that's how lookup behaves --
/// Each GenericParamScope scopes just ONE parameter, and we next
/// each one within the previous one.
///
/// Here's a wrinkle: for a Subscript, the caller expects this scope (based on
/// source loc) to match requested DeclContexts for starting lookup in EITHER
/// the getter or setter AbstractFunctionDecl (context)
class GenericParamScope final : public ASTScopeImpl {
public:
  /// The declaration that has generic parameters.
  Decl *const holder;
  /// The generic parameters themselves.
  GenericParamList *const paramList;
  /// The index of the current parameter.
  const unsigned index;

  GenericParamScope(Decl *holder, GenericParamList *paramList, unsigned index)
      : holder(holder), paramList(paramList), index(index) {}
  virtual ~GenericParamScope() {}

  /// Actually holder is always a GenericContext, need to test if
  /// ProtocolDecl or SubscriptDecl but will refactor later.
  NullablePtr<DeclContext> getDeclContext() const override;
  NullablePtr<const void> getReferrent() const override;
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override;

  NullablePtr<const void> addressForPrinting() const override {
    return paramList;
  }

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
  bool doesContextMatchStartingContext(const DeclContext *) const override;
  Optional<bool>
  resolveIsCascadingUseForThisScope(Optional<bool>) const override;
};

/// Concrete class for a function/initializer/deinitializer
class AbstractFunctionDeclScope final : public ASTScopeImpl {
public:
  AbstractFunctionDecl *const decl;
  AbstractFunctionDeclScope(AbstractFunctionDecl *e) : decl(e) {}
  virtual ~AbstractFunctionDeclScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  virtual NullablePtr<DeclContext> getDeclContext() const override;

  virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }

  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override;

  NullablePtr<const void> getReferrent() const override;

  static bool shouldCreateAccessorScope(const AccessorDecl *);

protected:
  SourceRange
  getSourceRangeOfEnclosedParamsOfASTNode(bool omitAssertions) const override;

private:
  static SourceLoc getParmsSourceLocOfAFD(AbstractFunctionDecl *);

protected:
  NullablePtr<const GenericParamList> genericParams() const override;

  Optional<bool>
  resolveIsCascadingUseForThisScope(Optional<bool>) const override;
};

/// The parameters for an abstract function (init/func/deinit)., subscript, and
/// enum element
class ParameterListScope final : public ASTScopeImpl {
public:
  ParameterList *const params;
  /// For get functions in subscript declarations,
  /// a lookup into the subscript parameters must count as the get func context.
  const NullablePtr<DeclContext> matchingContext;

  ParameterListScope(ParameterList *params,
                     NullablePtr<DeclContext> matchingContext)
      : params(params), matchingContext(matchingContext) {}
  virtual ~ParameterListScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);
  SourceLoc fixupEndForBadInput(SourceRange) const;

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual NullablePtr<DeclContext> getDeclContext() const override;

  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override;
  NullablePtr<const void> addressForPrinting() const override { return params; }
};

class AbstractFunctionBodyScope : public ASTScopeImpl {
public:
  AbstractFunctionDecl *const decl;

  /// \c Parser::parseAbstractFunctionBodyDelayed can call \c
  /// AbstractFunctionDecl::setBody after the tree has been constructed. So if
  /// this changes, have to rebuild body.
  NullablePtr<BraceStmt> bodyWhenLastExpanded;

  AbstractFunctionBodyScope(AbstractFunctionDecl *e) : decl(e) {}
  virtual ~AbstractFunctionBodyScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
  void beCurrent() override;
  bool isCurrentIfWasExpanded() const override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
  void expandBody(ScopeCreator &);

public:
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual NullablePtr<DeclContext> getDeclContext() const override {
    return decl;
  }
  virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }
  static bool isAMethod(const AbstractFunctionDecl *);

  NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued() override;

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
  Optional<bool>
  resolveIsCascadingUseForThisScope(Optional<bool>) const override;

public:
  NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion() override;
  SourceRange sourceRangeForDeferredExpansion() const override;
};

/// Body of methods, functions in types.
class MethodBodyScope final : public AbstractFunctionBodyScope {
public:
  MethodBodyScope(AbstractFunctionDecl *e) : AbstractFunctionBodyScope(e) {}
  std::string getClassName() const override;
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer consumer) const override;

  Optional<NullablePtr<DeclContext>> computeSelfDCForParent() const override;
};

/// Body of "pure" functions, functions without an implicit "self".
class PureFunctionBodyScope final : public AbstractFunctionBodyScope {
public:
  PureFunctionBodyScope(AbstractFunctionDecl *e)
      : AbstractFunctionBodyScope(e) {}
  std::string getClassName() const override;
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer consumer) const override;
};

class DefaultArgumentInitializerScope final : public ASTScopeImpl {
public:
  ParamDecl *const decl;

  DefaultArgumentInitializerScope(ParamDecl *e) : decl(e) {}
  ~DefaultArgumentInitializerScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

public:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual NullablePtr<DeclContext> getDeclContext() const override;
  virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }

protected:
  Optional<bool>
  resolveIsCascadingUseForThisScope(Optional<bool>) const override;
};

/// Consider:
///  @_propertyWrapper
///  struct WrapperWithInitialValue {
///  }
///  struct HasWrapper {
///    @WrapperWithInitialValue var y = 17
///  }
/// Lookup has to be able to find the use of WrapperWithInitialValue, that's
/// what this scope is for. Because the source positions are screwy.

class AttachedPropertyWrapperScope final : public ASTScopeImpl {
public:
  VarDecl *const decl;
  /// Because we have to avoid request cycles, we approximate the test for an
  /// AttachedPropertyWrapper with one based on source location. We might get
  /// false positives, that that doesn't hurt anything. However, the result of
  /// the conservative source range computation doesn't seem to be stable. So
  /// keep the original here, and use it for source range queries.
  /// rdar://55263708

  const SourceRange sourceRangeWhenCreated;

  AttachedPropertyWrapperScope(VarDecl *e)
      : decl(e), sourceRangeWhenCreated(getSourceRangeOfVarDecl(e)) {
    ASTScopeAssert(sourceRangeWhenCreated.isValid(),
                   "VarDecls must have ranges to be looked-up");
  }
  virtual ~AttachedPropertyWrapperScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  NullablePtr<const void> addressForPrinting() const override { return decl; }
  virtual NullablePtr<DeclContext> getDeclContext() const override;

  static SourceRange getSourceRangeOfVarDecl(const VarDecl *);

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
};

/// PatternBindingDecl's (PBDs) are tricky (See the comment for \c
/// PatternBindingDecl):
///
/// A PBD contains a list of "patterns", e.g.
///   var (a, b) = foo(), (c,d) = bar() which has two patterns.
///
/// For each pattern, there will be potentially three scopes:
/// always one for the declarations, maybe one for the initializers, and maybe
/// one for users of that pattern.
///
/// If a PBD occurs in code, its initializer can access all prior declarations.
/// Thus, a new scope must be created, nested in the scope of the PBD.
/// In contrast, if a PBD occurs in a type declaration body, its initializer
/// cannot access prior declarations in that body.
///
/// As a further complication, we get VarDecls and their accessors in deferred
/// which really must go into one of the PBD scopes. So we discard them in
/// createIfNeeded, and special-case their creation in
/// addVarDeclScopesAndTheirAccessors.

class AbstractPatternEntryScope : public ASTScopeImpl {
public:
  PatternBindingDecl *const decl;
  const unsigned patternEntryIndex;
  const DeclVisibilityKind vis;

  AbstractPatternEntryScope(PatternBindingDecl *, unsigned entryIndex,
                            DeclVisibilityKind);
  virtual ~AbstractPatternEntryScope() {}

  const PatternBindingEntry &getPatternEntry() const;
  Pattern *getPattern() const;

protected:
  void printSpecifics(llvm::raw_ostream &out) const override;
  void forEachVarDeclWithLocalizableAccessors(
      ScopeCreator &scopeCreator, function_ref<void(VarDecl *)> foundOne) const;

public:
  bool isLastEntry() const;
  NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }
};

class PatternEntryDeclScope final : public AbstractPatternEntryScope {
  const Expr *initWhenLastExpanded;
  unsigned varCountWhenLastExpanded = 0;

public:
  PatternEntryDeclScope(PatternBindingDecl *pbDecl, unsigned entryIndex,
                        DeclVisibilityKind vis)
      : AbstractPatternEntryScope(pbDecl, entryIndex, vis) {}
  virtual ~PatternEntryDeclScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
  void beCurrent() override;
  bool isCurrentIfWasExpanded() const override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

  NullablePtr<const void> getReferrent() const override;

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
};

class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
  // Should be able to remove this when rdar://53921703 is accomplished.
  Expr *initAsWrittenWhenCreated;

public:
  PatternEntryInitializerScope(PatternBindingDecl *pbDecl, unsigned entryIndex,
                               DeclVisibilityKind vis)
      : AbstractPatternEntryScope(pbDecl, entryIndex, vis),
        initAsWrittenWhenCreated(
            pbDecl->getPatternList()[entryIndex].getOriginalInit()) {}
  virtual ~PatternEntryInitializerScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual NullablePtr<DeclContext> getDeclContext() const override;

  Optional<NullablePtr<DeclContext>> computeSelfDCForParent() const override;

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;

  Optional<bool>
  resolveIsCascadingUseForThisScope(Optional<bool>) const override;
};

/// The scope introduced by a conditional clause in an if/guard/while
/// statement.
/// Since there may be more than one "let foo = ..." in (e.g.) an "if",
/// we allocate a matrushka of these.
class ConditionalClauseScope final : public ASTScopeImpl {
public:
  LabeledConditionalStmt *const stmt;
  const unsigned index;
  const SourceLoc endLoc; // cannot get it from the stmt

  ConditionalClauseScope(LabeledConditionalStmt *stmt, unsigned index,
                         SourceLoc endLoc)
      : stmt(stmt), index(index), endLoc(endLoc) {}

  virtual ~ConditionalClauseScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;

protected:
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

private:
  ArrayRef<StmtConditionElement> getCond() const;
  const StmtConditionElement &getStmtConditionElement() const;
};

/// If, while, & guard statements all start with a conditional clause, then some
/// later part of the statement, (then, body, or after the guard) circumvents
/// the normal lookup rule to pass the lookup scope into the deepest conditional
/// clause.
class ConditionalClausePatternUseScope final : public ASTScopeImpl {
  Pattern *const pattern;
  const SourceLoc startLoc;

public:
  ConditionalClausePatternUseScope(Pattern *pattern, SourceLoc startLoc)
      : pattern(pattern), startLoc(startLoc) {}

  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  std::string getClassName() const override;

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
  void printSpecifics(llvm::raw_ostream &out) const override;
};


/// Capture lists may contain initializer expressions
/// No local bindings here (other than closures in initializers);
/// rather include these in the params or body local bindings
class CaptureListScope final : public ASTScopeImpl {
public:
  CaptureListExpr *const expr;
  CaptureListScope(CaptureListExpr *e) : expr(e) {}
  virtual ~CaptureListScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  NullablePtr<DeclContext> getDeclContext() const override;
  NullablePtr<Expr> getExprIfAny() const override { return expr; }
  Expr *getExpr() const { return expr; }
  NullablePtr<const void> getReferrent() const override;
};

// In order for compatibility with existing lookup, closures are represented
// by multiple scopes: An overall scope (including the part before the "in"
// and a body scope, including the part after the "in"
class AbstractClosureScope : public ASTScopeImpl {
public:
  NullablePtr<CaptureListExpr> captureList;
  ClosureExpr *const closureExpr;

  AbstractClosureScope(ClosureExpr *closureExpr,
                       NullablePtr<CaptureListExpr> captureList)
      : captureList(captureList), closureExpr(closureExpr) {}
  virtual ~AbstractClosureScope() {}

  NullablePtr<ClosureExpr> getClosureIfClosureScope() const override;
  NullablePtr<DeclContext> getDeclContext() const override {
    return closureExpr;
  }
  NullablePtr<const void> addressForPrinting() const override {
    return closureExpr;
  }
};

class WholeClosureScope final : public AbstractClosureScope {
  const BraceStmt *bodyWhenLastExpanded;

public:
  WholeClosureScope(ClosureExpr *closureExpr,
                    NullablePtr<CaptureListExpr> captureList)
      : AbstractClosureScope(closureExpr, captureList) {}
  virtual ~WholeClosureScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
  void beCurrent() override;
  bool isCurrentIfWasExpanded() const override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  NullablePtr<Expr> getExprIfAny() const override { return closureExpr; }
  Expr *getExpr() const { return closureExpr; }
  NullablePtr<const void> getReferrent() const override;
};

/// For a closure with named parameters, this scope does the local bindings.
/// Absent if no "in".
class ClosureParametersScope final : public AbstractClosureScope {
public:
  ClosureParametersScope(ClosureExpr *closureExpr,
                         NullablePtr<CaptureListExpr> captureList)
      : AbstractClosureScope(closureExpr, captureList) {}
  virtual ~ClosureParametersScope() {}

  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
  Optional<bool> resolveIsCascadingUseForThisScope(
      Optional<bool> isCascadingUse) const override;
};

// The body encompasses the code in the closure; the part after the "in" if
// there is an "in"
class ClosureBodyScope final : public AbstractClosureScope {
public:
  ClosureBodyScope(ClosureExpr *closureExpr,
                   NullablePtr<CaptureListExpr> captureList)
      : AbstractClosureScope(closureExpr, captureList) {}
  virtual ~ClosureBodyScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  Optional<bool> resolveIsCascadingUseForThisScope(
      Optional<bool> isCascadingUse) const override;
};

class TopLevelCodeScope final : public ASTScopeImpl {
public:
  TopLevelCodeDecl *const decl;
  BraceStmt *bodyWhenLastExpanded;

  TopLevelCodeScope(TopLevelCodeDecl *e) : decl(e) {}
  virtual ~TopLevelCodeScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
  void beCurrent() override;
  bool isCurrentIfWasExpanded() const override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);
  std::vector<ASTScopeImpl *> rescueBodyScopesToReuse();

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual NullablePtr<DeclContext> getDeclContext() const override {
    return decl;
  }
  virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }
  NullablePtr<const void> getReferrent() const override;

  NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued() override;
};

/// The \c _@specialize attribute.
class SpecializeAttributeScope final : public ASTScopeImpl {
public:
  SpecializeAttr *const specializeAttr;
  AbstractFunctionDecl *const whatWasSpecialized;

  SpecializeAttributeScope(SpecializeAttr *specializeAttr,
                           AbstractFunctionDecl *whatWasSpecialized)
      : specializeAttr(specializeAttr), whatWasSpecialized(whatWasSpecialized) {
  }
  virtual ~SpecializeAttributeScope() {}

  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  NullablePtr<const void> addressForPrinting() const override {
    return specializeAttr;
  }

  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override;

  NullablePtr<DeclAttribute> getDeclAttributeIfAny() const override {
    return specializeAttr;
  }
  NullablePtr<const void> getReferrent() const override;

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
};

// SWIFT_ENABLE_TENSORFLOW
/// A `@differentiable` attribute scope.
/// This exists because `@differentiable` attribute may have a where clause
/// referring to generic parameters from some generic context.
class DifferentiableAttributeScope final : public ASTScopeImpl {
public:
  DifferentiableAttr *const differentiableAttr;
  ValueDecl *const attributedDeclaration;

  DifferentiableAttributeScope(DifferentiableAttr *diffAttr,
                               ValueDecl *decl)
      : differentiableAttr(diffAttr), attributedDeclaration(decl) {
  }
  virtual ~DifferentiableAttributeScope() {}

  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  NullablePtr<const void> addressForPrinting() const override {
    return differentiableAttr;
  }

  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override;

  NullablePtr<DeclAttribute> getDeclAttributeIfAny() const override {
    return differentiableAttr;
  }
  NullablePtr<const void> getReferrent() const override;

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
  bool doesContextMatchStartingContext(const DeclContext *) const override;
};
// SWIFT_ENABLE_TENSORFLOW END

class SubscriptDeclScope final : public ASTScopeImpl {
public:
  SubscriptDecl *const decl;

  SubscriptDeclScope(SubscriptDecl *e) : decl(e) {}
  virtual ~SubscriptDeclScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  virtual NullablePtr<DeclContext> getDeclContext() const override {
    return decl;
  }
  virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }
  NullablePtr<const void> getReferrent() const override;

protected:
  SourceRange
  getSourceRangeOfEnclosedParamsOfASTNode(bool omitAssertions) const override;

  NullablePtr<const GenericParamList> genericParams() const override;
  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override {
    return decl;
  }
public:
  bool isThisAnAbstractStorageDecl() const override { return true; }
};

class VarDeclScope final : public ASTScopeImpl {

public:
  VarDecl *const decl;
  VarDeclScope(VarDecl *e) : decl(e) {}
  virtual ~VarDeclScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  void printSpecifics(llvm::raw_ostream &out) const override;

public:
  virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }
  NullablePtr<const void> getReferrent() const override;
  NullablePtr<AbstractStorageDecl>
  getEnclosingAbstractStorageDecl() const override {
    return decl;
  }
  bool isThisAnAbstractStorageDecl() const override { return true; }
};

class EnumElementScope : public ASTScopeImpl {
  EnumElementDecl *const decl;

public:
  EnumElementScope(EnumElementDecl *e) : decl(e) {}

  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

  std::string getClassName() const override;
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  NullablePtr<DeclContext> getDeclContext() const override { return decl; }
  NullablePtr<Decl> getDeclIfAny() const override { return decl; }
  Decl *getDecl() const { return decl; }

protected:
  SourceRange
  getSourceRangeOfEnclosedParamsOfASTNode(bool omitAssertions) const override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
};

class AbstractStmtScope : public ASTScopeImpl {
public:
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual Stmt *getStmt() const = 0;
  NullablePtr<Stmt> getStmtIfAny() const override { return getStmt(); }
  NullablePtr<const void> getReferrent() const override;
};

class LabeledConditionalStmtScope : public AbstractStmtScope {
public:
  Stmt *getStmt() const override;
  virtual LabeledConditionalStmt *getLabeledConditionalStmt() const = 0;

  /// If a condition is present, create the martuska.
  /// Return the lookupParent for the use scope.
  ASTScopeImpl *createCondScopes();

protected:
  /// Return the lookupParent required to search these.
  ASTScopeImpl *createNestedConditionalClauseScopes(ScopeCreator &,
                                                    const Stmt *afterConds);
};

class IfStmtScope final : public LabeledConditionalStmtScope {
public:
  IfStmt *const stmt;
  IfStmtScope(IfStmt *e) : stmt(e) {}
  virtual ~IfStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  LabeledConditionalStmt *getLabeledConditionalStmt() const override;
};

class WhileStmtScope final : public LabeledConditionalStmtScope {
public:
  WhileStmt *const stmt;
  WhileStmtScope(WhileStmt *e) : stmt(e) {}
  virtual ~WhileStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  LabeledConditionalStmt *getLabeledConditionalStmt() const override;
};

class GuardStmtScope final : public LabeledConditionalStmtScope {
public:
  GuardStmt *const stmt;
  GuardStmtScope(GuardStmt *e) : stmt(e) {}
  virtual ~GuardStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  LabeledConditionalStmt *getLabeledConditionalStmt() const override;
};

/// A scope after a guard statement that follows lookups into the conditions
/// Also for:
///  The insertion point of the last statement of an active clause in an #if
///  must be the lookup parent
/// of any following scopes. But the active clause may not be the last clause.
/// In sort, this is another case where the lookup parent cannot follow the same
/// nesting as the source order. IfConfigUseScope implements this twist. It
/// follows the IfConfig, wraps all subsequent scopes, and redirects the lookup.
class LookupParentDiversionScope final : public ASTScopeImpl {
public:
  ASTScopeImpl *const lookupParent;
  const SourceLoc startLoc;

  LookupParentDiversionScope(ASTScopeImpl *lookupParent, SourceLoc startLoc)
      : lookupParent(lookupParent), startLoc(startLoc) {}

  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  std::string getClassName() const override;

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
  NullablePtr<const ASTScopeImpl> getLookupParent() const override {
    return lookupParent;
  }
};

class RepeatWhileScope final : public AbstractStmtScope {
public:
  RepeatWhileStmt *const stmt;
  RepeatWhileScope(RepeatWhileStmt *e) : stmt(e) {}
  virtual ~RepeatWhileScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  Stmt *getStmt() const override { return stmt; }
};

class DoCatchStmtScope final : public AbstractStmtScope {
public:
  DoCatchStmt *const stmt;
  DoCatchStmtScope(DoCatchStmt *e) : stmt(e) {}
  virtual ~DoCatchStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  Stmt *getStmt() const override { return stmt; }
};

class SwitchStmtScope final : public AbstractStmtScope {
public:
  SwitchStmt *const stmt;
  SwitchStmtScope(SwitchStmt *e) : stmt(e) {}
  virtual ~SwitchStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  Stmt *getStmt() const override { return stmt; }
};

class ForEachStmtScope final : public AbstractStmtScope {
public:
  ForEachStmt *const stmt;
  ForEachStmtScope(ForEachStmt *e) : stmt(e) {}
  virtual ~ForEachStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  Stmt *getStmt() const override { return stmt; }
};

class ForEachPatternScope final : public ASTScopeImpl {
public:
  ForEachStmt *const stmt;
  ForEachPatternScope(ForEachStmt *e) : stmt(e) {}
  virtual ~ForEachPatternScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
};

class CatchStmtScope final : public AbstractStmtScope {
public:
  CatchStmt *const stmt;
  CatchStmtScope(CatchStmt *e) : stmt(e) {}
  virtual ~CatchStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  Stmt *getStmt() const override { return stmt; }

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             ASTScopeImpl::DeclConsumer) const override;
};

class CaseStmtScope final : public AbstractStmtScope {
public:
  CaseStmt *const stmt;
  CaseStmtScope(CaseStmt *e) : stmt(e) {}
  virtual ~CaseStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  Stmt *getStmt() const override { return stmt; }

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             ASTScopeImpl::DeclConsumer) const override;
};

class BraceStmtScope final : public AbstractStmtScope {

public:
  BraceStmt *const stmt;
  BraceStmtScope(BraceStmt *e) : stmt(e) {}
  virtual ~BraceStmtScope() {}

protected:
  ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
  AnnotatedInsertionPoint
  expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &);

public:
  std::string getClassName() const override;
  SourceRange
  getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
  virtual NullablePtr<DeclContext> getDeclContext() const override;

  NullablePtr<ClosureExpr> parentClosureIfAny() const; // public??
  Stmt *getStmt() const override { return stmt; }

protected:
  bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                             DeclConsumer) const override;
};
} // namespace ast_scope
} // namespace swift

#endif // SWIFT_AST_AST_SCOPE_H
