mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -38,6 +38,16 @@
|
|||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallVector.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 {
|
namespace swift {
|
||||||
|
|
||||||
#pragma mark Forward-references
|
#pragma mark Forward-references
|
||||||
@@ -125,10 +135,10 @@ private:
|
|||||||
/// Must clear source range change whenever this changes
|
/// Must clear source range change whenever this changes
|
||||||
Children storedChildren;
|
Children storedChildren;
|
||||||
|
|
||||||
/// Because expansion returns an insertion point,
|
bool wasExpanded = false;
|
||||||
/// if a scope is reexpanded, the children added NOT by expansion must be
|
|
||||||
/// rescued and reused.
|
/// For use-before-def, ASTAncestor scopes may be added to a BraceStmt.
|
||||||
unsigned childrenCountWhenLastExpanded = 0;
|
unsigned astAncestorScopeCount = 0;
|
||||||
|
|
||||||
/// Can clear storedChildren, so must remember this
|
/// Can clear storedChildren, so must remember this
|
||||||
bool haveAddedCleanup = false;
|
bool haveAddedCleanup = false;
|
||||||
@@ -162,7 +172,7 @@ public:
|
|||||||
void *operator new(size_t bytes, const ASTContext &ctx,
|
void *operator new(size_t bytes, const ASTContext &ctx,
|
||||||
unsigned alignment = alignof(ASTScopeImpl));
|
unsigned alignment = alignof(ASTScopeImpl));
|
||||||
void *operator new(size_t Bytes, void *Mem) {
|
void *operator new(size_t Bytes, void *Mem) {
|
||||||
assert(Mem);
|
ASTScopeAssert(Mem, "Allocation failed");
|
||||||
return Mem;
|
return Mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,12 +190,13 @@ protected:
|
|||||||
|
|
||||||
public: // for addReusedBodyScopes
|
public: // for addReusedBodyScopes
|
||||||
void addChild(ASTScopeImpl *child, ASTContext &);
|
void addChild(ASTScopeImpl *child, ASTContext &);
|
||||||
std::vector<ASTScopeImpl *> rescueYoungestChildren(unsigned count);
|
std::vector<ASTScopeImpl *> rescueASTAncestorScopesForReuseFromMe();
|
||||||
|
|
||||||
/// When reexpanding, do we always create a new body?
|
/// When reexpanding, do we always create a new body?
|
||||||
virtual NullablePtr<ASTScopeImpl> getParentOfRescuedScopes();
|
virtual NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued();
|
||||||
std::vector<ASTScopeImpl *> rescueScopesToReuse();
|
std::vector<ASTScopeImpl *>
|
||||||
void addReusedScopes(ArrayRef<ASTScopeImpl *>);
|
rescueASTAncestorScopesForReuseFromMeOrDescendants();
|
||||||
|
void replaceASTAncestorScopes(ArrayRef<ASTScopeImpl *>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void removeChildren();
|
void removeChildren();
|
||||||
@@ -196,6 +207,8 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void preOrderDo(function_ref<void(ASTScopeImpl *)>);
|
void preOrderDo(function_ref<void(ASTScopeImpl *)>);
|
||||||
|
/// Like preorderDo but without myself.
|
||||||
|
void preOrderChildrenDo(function_ref<void(ASTScopeImpl *)>);
|
||||||
void postOrderDo(function_ref<void(ASTScopeImpl *)>);
|
void postOrderDo(function_ref<void(ASTScopeImpl *)>);
|
||||||
|
|
||||||
#pragma mark - source ranges
|
#pragma mark - source ranges
|
||||||
@@ -219,6 +232,12 @@ public:
|
|||||||
bool doesRangeMatch(unsigned start, unsigned end, StringRef file = "",
|
bool doesRangeMatch(unsigned start, unsigned end, StringRef file = "",
|
||||||
StringRef className = "");
|
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:
|
private:
|
||||||
SourceRange computeSourceRangeOfScope(bool omitAssertions = false) const;
|
SourceRange computeSourceRangeOfScope(bool omitAssertions = false) const;
|
||||||
SourceRange
|
SourceRange
|
||||||
@@ -253,6 +272,8 @@ public:
|
|||||||
void ensureSourceRangesAreCorrectWhenAddingDescendants(function_ref<void()>);
|
void ensureSourceRangesAreCorrectWhenAddingDescendants(function_ref<void()>);
|
||||||
|
|
||||||
public: // public for debugging
|
public: // public for debugging
|
||||||
|
/// Returns source range of this node alone, without factoring in any
|
||||||
|
/// children.
|
||||||
virtual SourceRange
|
virtual SourceRange
|
||||||
getSourceRangeOfThisASTNode(bool omitAssertions = false) const = 0;
|
getSourceRangeOfThisASTNode(bool omitAssertions = false) const = 0;
|
||||||
|
|
||||||
@@ -314,10 +335,17 @@ public:
|
|||||||
/// Return the scope into which to place subsequent decls
|
/// Return the scope into which to place subsequent decls
|
||||||
ASTScopeImpl *expandAndBeCurrent(ScopeCreator &);
|
ASTScopeImpl *expandAndBeCurrent(ScopeCreator &);
|
||||||
|
|
||||||
|
unsigned getASTAncestorScopeCount() const { return astAncestorScopeCount; }
|
||||||
|
bool getWasExpanded() const { return wasExpanded; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void resetASTAncestorScopeCount() { astAncestorScopeCount = 0; }
|
||||||
|
void increaseASTAncestorScopeCount(unsigned c) { astAncestorScopeCount += c; }
|
||||||
|
void setWasExpanded() { wasExpanded = true; }
|
||||||
virtual ASTScopeImpl *expandSpecifically(ScopeCreator &) = 0;
|
virtual ASTScopeImpl *expandSpecifically(ScopeCreator &) = 0;
|
||||||
virtual void beCurrent();
|
virtual void beCurrent();
|
||||||
virtual bool isCurrent() const;
|
bool isCurrent() const;
|
||||||
|
virtual bool isCurrentIfWasExpanded() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Compare the pre-expasion range with the post-expansion range and return
|
/// Compare the pre-expasion range with the post-expansion range and return
|
||||||
@@ -328,6 +356,8 @@ public:
|
|||||||
/// Some scopes can be expanded lazily.
|
/// Some scopes can be expanded lazily.
|
||||||
/// Such scopes must: not change their source ranges after expansion, and
|
/// Such scopes must: not change their source ranges after expansion, and
|
||||||
/// their expansion must return an insertion point outside themselves.
|
/// 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 NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion();
|
||||||
virtual SourceRange sourceRangeForDeferredExpansion() const;
|
virtual SourceRange sourceRangeForDeferredExpansion() const;
|
||||||
|
|
||||||
@@ -356,9 +386,6 @@ private:
|
|||||||
|
|
||||||
virtual ScopeCreator &getScopeCreator();
|
virtual ScopeCreator &getScopeCreator();
|
||||||
|
|
||||||
protected:
|
|
||||||
void setChildrenCountWhenLastExpanded();
|
|
||||||
|
|
||||||
#pragma mark - - creation queries
|
#pragma mark - - creation queries
|
||||||
public:
|
public:
|
||||||
virtual bool isThisAnAbstractStorageDecl() const { return false; }
|
virtual bool isThisAnAbstractStorageDecl() const { return false; }
|
||||||
@@ -506,6 +533,7 @@ public:
|
|||||||
/// The number of \c Decls in the \c SourceFile that were already seen.
|
/// The number of \c Decls in the \c SourceFile that were already seen.
|
||||||
/// Since parsing can be interleaved with type-checking, on every
|
/// Since parsing can be interleaved with type-checking, on every
|
||||||
/// lookup, look at creating scopes for any \c Decls beyond this number.
|
/// lookup, look at creating scopes for any \c Decls beyond this number.
|
||||||
|
/// rdar://55562483 Unify with numberOfChildrenWhenLastExpanded
|
||||||
int numberOfDeclsAlreadySeen = 0;
|
int numberOfDeclsAlreadySeen = 0;
|
||||||
|
|
||||||
ASTSourceFileScope(SourceFile *SF, ScopeCreator *scopeCreator);
|
ASTSourceFileScope(SourceFile *SF, ScopeCreator *scopeCreator);
|
||||||
@@ -521,7 +549,9 @@ public:
|
|||||||
NullablePtr<DeclContext> getDeclContext() const override;
|
NullablePtr<DeclContext> getDeclContext() const override;
|
||||||
|
|
||||||
void addNewDeclsToScopeTree();
|
void addNewDeclsToScopeTree();
|
||||||
void buildScopeTreeEagerly();
|
void buildFullyExpandedTree();
|
||||||
|
void
|
||||||
|
buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
|
||||||
|
|
||||||
const SourceFile *getSourceFile() const override;
|
const SourceFile *getSourceFile() const override;
|
||||||
NullablePtr<const void> addressForPrinting() const override { return SF; }
|
NullablePtr<const void> addressForPrinting() const override { return SF; }
|
||||||
@@ -552,7 +582,7 @@ public:
|
|||||||
void *operator new(size_t bytes, const ASTContext &ctx,
|
void *operator new(size_t bytes, const ASTContext &ctx,
|
||||||
unsigned alignment = alignof(ASTScopeImpl));
|
unsigned alignment = alignof(ASTScopeImpl));
|
||||||
void *operator new(size_t Bytes, void *Mem) {
|
void *operator new(size_t Bytes, void *Mem) {
|
||||||
assert(Mem);
|
ASTScopeAssert(Mem, "Allocation failed");
|
||||||
return Mem;
|
return Mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,12 +605,12 @@ public:
|
|||||||
virtual const Decl *
|
virtual const Decl *
|
||||||
getReferrentOfScope(const GenericTypeOrExtensionScope *s) const;
|
getReferrentOfScope(const GenericTypeOrExtensionScope *s) const;
|
||||||
|
|
||||||
virtual void beCurrent(IterableTypeScope *) const;
|
virtual void beCurrent(IterableTypeScope *) const = 0;
|
||||||
virtual bool isCurrent(const IterableTypeScope *) const;
|
virtual bool isCurrentIfWasExpanded(const IterableTypeScope *) const = 0;
|
||||||
virtual NullablePtr<ASTScopeImpl>
|
virtual NullablePtr<ASTScopeImpl>
|
||||||
insertionPointForDeferredExpansion(IterableTypeScope *) const;
|
insertionPointForDeferredExpansion(IterableTypeScope *) const = 0;
|
||||||
virtual SourceRange
|
virtual SourceRange
|
||||||
sourceRangeForDeferredExpansion(const IterableTypeScope *) const;
|
sourceRangeForDeferredExpansion(const IterableTypeScope *) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// For the whole Decl scope of a GenericType or an Extension
|
// For the whole Decl scope of a GenericType or an Extension
|
||||||
@@ -601,6 +631,24 @@ public:
|
|||||||
|
|
||||||
const Decl *
|
const Decl *
|
||||||
getReferrentOfScope(const GenericTypeOrExtensionScope *s) const override;
|
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
|
/// GenericTypeOrExtension = GenericType or Extension
|
||||||
@@ -639,6 +687,14 @@ public:
|
|||||||
|
|
||||||
SourceRange getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *,
|
SourceRange getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *,
|
||||||
bool omitAssertions) const override;
|
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
|
/// Behavior specific to representing the Body of a NominalTypeDecl or
|
||||||
@@ -655,7 +711,7 @@ public:
|
|||||||
bool omitAssertions) const override;
|
bool omitAssertions) const override;
|
||||||
|
|
||||||
void beCurrent(IterableTypeScope *) const override;
|
void beCurrent(IterableTypeScope *) const override;
|
||||||
bool isCurrent(const IterableTypeScope *) const override;
|
bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;
|
||||||
NullablePtr<ASTScopeImpl>
|
NullablePtr<ASTScopeImpl>
|
||||||
insertionPointForDeferredExpansion(IterableTypeScope *) const override;
|
insertionPointForDeferredExpansion(IterableTypeScope *) const override;
|
||||||
SourceRange
|
SourceRange
|
||||||
@@ -694,6 +750,17 @@ public:
|
|||||||
SourceRange
|
SourceRange
|
||||||
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
|
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;
|
virtual GenericContext *getGenericContext() const = 0;
|
||||||
std::string getClassName() const override;
|
std::string getClassName() const override;
|
||||||
virtual std::string declKindName() const = 0;
|
virtual std::string declKindName() const = 0;
|
||||||
@@ -732,6 +799,8 @@ class GenericTypeScope : public GenericTypeOrExtensionScope {
|
|||||||
public:
|
public:
|
||||||
GenericTypeScope(const Portion *p) : GenericTypeOrExtensionScope(p) {}
|
GenericTypeScope(const Portion *p) : GenericTypeOrExtensionScope(p) {}
|
||||||
virtual ~GenericTypeScope() {}
|
virtual ~GenericTypeScope() {}
|
||||||
|
SourceRange moveStartPastExtendedNominal(SourceRange) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NullablePtr<const GenericParamList> genericParams() const override;
|
NullablePtr<const GenericParamList> genericParams() const override;
|
||||||
};
|
};
|
||||||
@@ -753,9 +822,11 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void beCurrent() override;
|
void beCurrent() override;
|
||||||
bool isCurrent() const override;
|
bool isCurrentIfWasExpanded() const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void makeWholeCurrent();
|
||||||
|
bool isWholeCurrent() const;
|
||||||
void makeBodyCurrent();
|
void makeBodyCurrent();
|
||||||
bool isBodyCurrent() const;
|
bool isBodyCurrent() const;
|
||||||
NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion() override;
|
NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion() override;
|
||||||
@@ -804,6 +875,7 @@ public:
|
|||||||
NullablePtr<NominalTypeDecl> getCorrespondingNominalTypeDecl() const override;
|
NullablePtr<NominalTypeDecl> getCorrespondingNominalTypeDecl() const override;
|
||||||
std::string declKindName() const override { return "Extension"; }
|
std::string declKindName() const override { return "Extension"; }
|
||||||
SourceRange getBraces() const override;
|
SourceRange getBraces() const override;
|
||||||
|
SourceRange moveStartPastExtendedNominal(SourceRange) const override;
|
||||||
ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
|
ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
|
||||||
ScopeCreator &) override;
|
ScopeCreator &) override;
|
||||||
void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) override;
|
void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) override;
|
||||||
@@ -984,7 +1056,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
||||||
void beCurrent() override;
|
void beCurrent() override;
|
||||||
bool isCurrent() const override;
|
bool isCurrentIfWasExpanded() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
|
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
|
||||||
@@ -1000,7 +1072,7 @@ public:
|
|||||||
Decl *getDecl() const { return decl; }
|
Decl *getDecl() const { return decl; }
|
||||||
static bool isAMethod(const AbstractFunctionDecl *);
|
static bool isAMethod(const AbstractFunctionDecl *);
|
||||||
|
|
||||||
NullablePtr<ASTScopeImpl> getParentOfRescuedScopes() override;
|
NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
|
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
|
||||||
@@ -1076,11 +1148,14 @@ public:
|
|||||||
/// false positives, that that doesn't hurt anything. However, the result of
|
/// false positives, that that doesn't hurt anything. However, the result of
|
||||||
/// the conservative source range computation doesn't seem to be stable. So
|
/// the conservative source range computation doesn't seem to be stable. So
|
||||||
/// keep the original here, and use it for source range queries.
|
/// keep the original here, and use it for source range queries.
|
||||||
|
/// rdar://55263708
|
||||||
|
|
||||||
const SourceRange sourceRangeWhenCreated;
|
const SourceRange sourceRangeWhenCreated;
|
||||||
|
|
||||||
AttachedPropertyWrapperScope(VarDecl *e)
|
AttachedPropertyWrapperScope(VarDecl *e)
|
||||||
: decl(e), sourceRangeWhenCreated(getSourceRangeOfVarDecl(e)) {
|
: decl(e), sourceRangeWhenCreated(getSourceRangeOfVarDecl(e)) {
|
||||||
assert(sourceRangeWhenCreated.isValid());
|
ASTScopeAssert(sourceRangeWhenCreated.isValid(),
|
||||||
|
"VarDecls must have ranges to be looked-up");
|
||||||
}
|
}
|
||||||
virtual ~AttachedPropertyWrapperScope() {}
|
virtual ~AttachedPropertyWrapperScope() {}
|
||||||
|
|
||||||
@@ -1157,7 +1232,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
||||||
void beCurrent() override;
|
void beCurrent() override;
|
||||||
bool isCurrent() const override;
|
bool isCurrentIfWasExpanded() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AnnotatedInsertionPoint
|
AnnotatedInsertionPoint
|
||||||
@@ -1331,7 +1406,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
||||||
void beCurrent() override;
|
void beCurrent() override;
|
||||||
bool isCurrent() const override;
|
bool isCurrentIfWasExpanded() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
|
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
|
||||||
@@ -1402,7 +1477,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
|
||||||
void beCurrent() override;
|
void beCurrent() override;
|
||||||
bool isCurrent() const override;
|
bool isCurrentIfWasExpanded() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AnnotatedInsertionPoint
|
AnnotatedInsertionPoint
|
||||||
@@ -1420,7 +1495,7 @@ public:
|
|||||||
Decl *getDecl() const { return decl; }
|
Decl *getDecl() const { return decl; }
|
||||||
NullablePtr<const void> getReferrent() const override;
|
NullablePtr<const void> getReferrent() const override;
|
||||||
|
|
||||||
NullablePtr<ASTScopeImpl> getParentOfRescuedScopes() override;
|
NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The \c _@specialize attribute.
|
/// The \c _@specialize attribute.
|
||||||
|
|||||||
@@ -592,9 +592,11 @@ class ASTScope {
|
|||||||
public:
|
public:
|
||||||
ASTScope(SourceFile *);
|
ASTScope(SourceFile *);
|
||||||
|
|
||||||
/// Cannot be lazy during type-checking because it mutates the AST.
|
void
|
||||||
/// So build eagerly before type-checking
|
buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
|
||||||
void buildScopeTreeEagerly();
|
|
||||||
|
/// Flesh out the tree for dumping
|
||||||
|
void buildFullyExpandedTree();
|
||||||
|
|
||||||
/// \return the scopes traversed
|
/// \return the scopes traversed
|
||||||
static llvm::SmallVector<const ast_scope::ASTScopeImpl *, 0>
|
static llvm::SmallVector<const ast_scope::ASTScopeImpl *, 0>
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ namespace swift {
|
|||||||
bool DisableParserLookup = false;
|
bool DisableParserLookup = false;
|
||||||
|
|
||||||
/// Should we compare to ASTScope-based resolution for debugging?
|
/// Should we compare to ASTScope-based resolution for debugging?
|
||||||
bool CompareToASTScopeLookup = false;
|
bool CrosscheckUnqualifiedLookup = false;
|
||||||
|
|
||||||
/// Should we stress ASTScope-based resolution for debugging?
|
/// Should we stress ASTScope-based resolution for debugging?
|
||||||
bool StressASTScopeLookup = false;
|
bool StressASTScopeLookup = false;
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ def disable_target_os_checking :
|
|||||||
Flag<["-"], "disable-target-os-checking">,
|
Flag<["-"], "disable-target-os-checking">,
|
||||||
HelpText<"Disable checking the target OS of serialized modules">;
|
HelpText<"Disable checking the target OS of serialized modules">;
|
||||||
|
|
||||||
def compare_to_astscope_lookup : Flag<["-"], "compare-to-astscope-lookup">,
|
def crosscheck_unqualified_lookup : Flag<["-"], "crosscheck-unqualified-lookup">,
|
||||||
HelpText<"Compare legacy to ASTScope-based unqualified name lookup (for debugging)">;
|
HelpText<"Compare legacy DeclContext- to ASTScope-based unqualified name lookup (for debugging)">;
|
||||||
|
|
||||||
def stress_astscope_lookup : Flag<["-"], "stress-astscope-lookup">,
|
def stress_astscope_lookup : Flag<["-"], "stress-astscope-lookup">,
|
||||||
HelpText<"Stress ASTScope-based unqualified name lookup (for testing)">;
|
HelpText<"Stress ASTScope-based unqualified name lookup (for testing)">;
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ NullablePtr<DeclContext> BraceStmtScope::getDeclContext() const {
|
|||||||
NullablePtr<DeclContext>
|
NullablePtr<DeclContext>
|
||||||
DefaultArgumentInitializerScope::getDeclContext() const {
|
DefaultArgumentInitializerScope::getDeclContext() const {
|
||||||
auto *dc = decl->getDefaultArgumentInitContext();
|
auto *dc = decl->getDefaultArgumentInitContext();
|
||||||
assert(dc && "If scope exists, this must exist");
|
ASTScopeAssert(dc, "If scope exists, this must exist");
|
||||||
return dc;
|
return dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +268,9 @@ ExtensionScope::getCorrespondingNominalTypeDecl() const {
|
|||||||
|
|
||||||
void ASTScopeImpl::preOrderDo(function_ref<void(ASTScopeImpl *)> fn) {
|
void ASTScopeImpl::preOrderDo(function_ref<void(ASTScopeImpl *)> fn) {
|
||||||
fn(this);
|
fn(this);
|
||||||
|
preOrderChildrenDo(fn);
|
||||||
|
}
|
||||||
|
void ASTScopeImpl::preOrderChildrenDo(function_ref<void(ASTScopeImpl *)> fn) {
|
||||||
for (auto *child : getChildren())
|
for (auto *child : getChildren())
|
||||||
child->preOrderDo(fn);
|
child->preOrderDo(fn);
|
||||||
}
|
}
|
||||||
@@ -286,3 +289,22 @@ const StmtConditionElement &
|
|||||||
ConditionalClauseScope::getStmtConditionElement() const {
|
ConditionalClauseScope::getStmtConditionElement() const {
|
||||||
return getCond()[index];
|
return getCond()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned ASTScopeImpl::countDescendants() const {
|
||||||
|
unsigned count = 0;
|
||||||
|
const_cast<ASTScopeImpl *>(this)->preOrderDo(
|
||||||
|
[&](ASTScopeImpl *) { ++count; });
|
||||||
|
return count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can fail if a subscope is lazy and not reexpanded
|
||||||
|
void ASTScopeImpl::assertThatTreeDoesNotShrink(function_ref<void()> fn) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
unsigned beforeCount = countDescendants();
|
||||||
|
#endif
|
||||||
|
fn();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
unsigned afterCount = countDescendants();
|
||||||
|
ASTScopeAssert(beforeCount <= afterCount, "shrank?!");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -186,27 +186,9 @@ class ScopeCreator final {
|
|||||||
/// For allocating scopes.
|
/// For allocating scopes.
|
||||||
ASTContext &ctx;
|
ASTContext &ctx;
|
||||||
|
|
||||||
public:
|
|
||||||
/// Because type checking can mutate the AST, eagerly build the tree, then
|
|
||||||
/// freeze it
|
|
||||||
enum class Temperature {
|
|
||||||
Warm, // Can be lazy
|
|
||||||
Freezing, // Should expand everything eagerly
|
|
||||||
Frozen // No more changes, except when Decls are added to the source file
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// Because type checking can mutate the AST, eagerly build the tree, then
|
|
||||||
/// freeze it
|
|
||||||
Temperature temperature = Temperature::Warm;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTSourceFileScope *const sourceFileScope;
|
ASTSourceFileScope *const sourceFileScope;
|
||||||
ASTContext &getASTContext() const { return ctx; }
|
ASTContext &getASTContext() const { return ctx; }
|
||||||
bool getIsFrozen() const { return temperature == Temperature::Frozen; }
|
|
||||||
bool getIsFreezing() const { return temperature == Temperature::Freezing; }
|
|
||||||
void beFreezing() { temperature = Temperature::Freezing; }
|
|
||||||
void beFrozen() { temperature = Temperature::Frozen; }
|
|
||||||
|
|
||||||
/// The AST can have duplicate nodes, and we don't want to create scopes for
|
/// The AST can have duplicate nodes, and we don't want to create scopes for
|
||||||
/// those.
|
/// those.
|
||||||
@@ -223,15 +205,25 @@ public:
|
|||||||
|
|
||||||
/// Given an array of ASTNodes or Decl pointers, add them
|
/// Given an array of ASTNodes or Decl pointers, add them
|
||||||
/// Return the resultant insertionPoint
|
/// Return the resultant insertionPoint
|
||||||
ASTScopeImpl *addSiblingsToScopeTree(ASTScopeImpl *const insertionPoint,
|
ASTScopeImpl *
|
||||||
ArrayRef<ASTNode> nodesOrDeclsToAdd) {
|
addSiblingsToScopeTree(ASTScopeImpl *const insertionPoint,
|
||||||
|
ASTScopeImpl *const organicInsertionPoint,
|
||||||
|
ArrayRef<ASTNode> nodesOrDeclsToAdd) {
|
||||||
auto *ip = insertionPoint;
|
auto *ip = insertionPoint;
|
||||||
for (auto nd : expandIfConfigClausesThenCullAndSortElementsOrMembers(
|
for (auto nd : expandIfConfigClausesThenCullAndSortElementsOrMembers(
|
||||||
nodesOrDeclsToAdd)) {
|
nodesOrDeclsToAdd)) {
|
||||||
if (shouldThisNodeBeScopedWhenFoundInSourceFileBraceStmtOrType(nd))
|
if (!shouldThisNodeBeScopedWhenFoundInSourceFileBraceStmtOrType(nd)) {
|
||||||
ip = addToScopeTreeAndReturnInsertionPoint(nd, ip).getPtrOr(ip);
|
// FIXME: Could the range get lost if the node is ever reexpanded?
|
||||||
else
|
|
||||||
ip->widenSourceRangeForIgnoredASTNode(nd);
|
ip->widenSourceRangeForIgnoredASTNode(nd);
|
||||||
|
} else {
|
||||||
|
const unsigned preCount = ip->getChildren().size();
|
||||||
|
auto *const newIP =
|
||||||
|
addToScopeTreeAndReturnInsertionPoint(nd, ip).getPtrOr(ip);
|
||||||
|
if (ip != organicInsertionPoint)
|
||||||
|
ip->increaseASTAncestorScopeCount(ip->getChildren().size() -
|
||||||
|
preCount);
|
||||||
|
ip = newIP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
@@ -301,9 +293,9 @@ public:
|
|||||||
// IDE/complete_property_delegate_attribute.swift fails because we try to
|
// IDE/complete_property_delegate_attribute.swift fails because we try to
|
||||||
// expand a member whose source range is backwards.
|
// expand a member whose source range is backwards.
|
||||||
(void)SM;
|
(void)SM;
|
||||||
assert((d->getStartLoc().isInvalid() ||
|
ASTScopeAssert(d->getStartLoc().isInvalid() ||
|
||||||
!SM.isBeforeInBuffer(d->getEndLoc(), d->getStartLoc())) &&
|
!SM.isBeforeInBuffer(d->getEndLoc(), d->getStartLoc()),
|
||||||
"end-before-start will break tree search via location");
|
"end-before-start will break tree search via location");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,8 +306,8 @@ public:
|
|||||||
template <typename Scope, typename... Args>
|
template <typename Scope, typename... Args>
|
||||||
ASTScopeImpl *constructExpandAndInsertUncheckable(ASTScopeImpl *parent,
|
ASTScopeImpl *constructExpandAndInsertUncheckable(ASTScopeImpl *parent,
|
||||||
Args... args) {
|
Args... args) {
|
||||||
assert(!Scope(args...).getReferrent() &&
|
ASTScopeAssert(!Scope(args...).getReferrent(),
|
||||||
"Not checking for duplicate ASTNode but class supports it");
|
"Not checking for duplicate ASTNode but class supports it");
|
||||||
return constructExpandAndInsert<Scope>(parent, args...);
|
return constructExpandAndInsert<Scope>(parent, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,8 +315,9 @@ public:
|
|||||||
NullablePtr<ASTScopeImpl>
|
NullablePtr<ASTScopeImpl>
|
||||||
ifUniqueConstructExpandAndInsert(ASTScopeImpl *parent, Args... args) {
|
ifUniqueConstructExpandAndInsert(ASTScopeImpl *parent, Args... args) {
|
||||||
Scope dryRun(args...);
|
Scope dryRun(args...);
|
||||||
assert(dryRun.getReferrent() &&
|
ASTScopeAssert(
|
||||||
"Checking for duplicate ASTNode but class does not support it");
|
dryRun.getReferrent(),
|
||||||
|
"Checking for duplicate ASTNode but class does not support it");
|
||||||
if (scopedNodes.insert(&dryRun))
|
if (scopedNodes.insert(&dryRun))
|
||||||
return constructExpandAndInsert<Scope>(parent, args...);
|
return constructExpandAndInsert<Scope>(parent, args...);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -335,7 +328,7 @@ public:
|
|||||||
Args... args) {
|
Args... args) {
|
||||||
if (auto s = ifUniqueConstructExpandAndInsert<Scope>(parent, args...))
|
if (auto s = ifUniqueConstructExpandAndInsert<Scope>(parent, args...))
|
||||||
return s.get();
|
return s.get();
|
||||||
llvm_unreachable("Scope should have been unique");
|
ASTScope_unreachable("Scope should have been unique");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -348,8 +341,8 @@ private:
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
ASTScopeImpl *insertionPoint = child->expandAndBeCurrent(*this);
|
ASTScopeImpl *insertionPoint = child->expandAndBeCurrent(*this);
|
||||||
assert(child->verifyThatThisNodeComeAfterItsPriorSibling() &&
|
ASTScopeAssert(child->verifyThatThisNodeComeAfterItsPriorSibling(),
|
||||||
"Ensure search will work");
|
"Ensure search will work");
|
||||||
return insertionPoint;
|
return insertionPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,6 +381,7 @@ private:
|
|||||||
|
|
||||||
// A safe way to discover this, without creating a circular request.
|
// A safe way to discover this, without creating a circular request.
|
||||||
// Cannot call getAttachedPropertyWrappers.
|
// Cannot call getAttachedPropertyWrappers.
|
||||||
|
// rdar://55263708
|
||||||
static bool hasAttachedPropertyWrapper(VarDecl *vd) {
|
static bool hasAttachedPropertyWrapper(VarDecl *vd) {
|
||||||
return AttachedPropertyWrapperScope::getSourceRangeOfVarDecl(vd).isValid();
|
return AttachedPropertyWrapperScope::getSourceRangeOfVarDecl(vd).isValid();
|
||||||
}
|
}
|
||||||
@@ -489,9 +483,8 @@ private:
|
|||||||
expansion.push_back(cond);
|
expansion.push_back(cond);
|
||||||
if (clause.isActive) {
|
if (clause.isActive) {
|
||||||
// rdar://53922172
|
// rdar://53922172
|
||||||
assert(isInAnActiveNode && "Clause should not be marked "
|
ASTScopeAssert(isInAnActiveNode, "Clause should not be marked active "
|
||||||
"active unless it's context is "
|
"unless it's context is active");
|
||||||
"active");
|
|
||||||
// get inactive nodes that nest in active clauses
|
// get inactive nodes that nest in active clauses
|
||||||
for (auto n : clause.Elements) {
|
for (auto n : clause.Elements) {
|
||||||
if (auto *const d = n.dyn_cast<Decl *>())
|
if (auto *const d = n.dyn_cast<Decl *>())
|
||||||
@@ -514,8 +507,9 @@ private:
|
|||||||
// When working on rdar://53971116 may have to cull more.
|
// When working on rdar://53971116 may have to cull more.
|
||||||
std::vector<ASTNode> culled;
|
std::vector<ASTNode> culled;
|
||||||
llvm::copy_if(input, std::back_inserter(culled), [&](ASTNode n) {
|
llvm::copy_if(input, std::back_inserter(culled), [&](ASTNode n) {
|
||||||
assert(!n.isDecl(DeclKind::Accessor) &&
|
ASTScopeAssert(
|
||||||
"Should not find accessors in iterable types or brace statements");
|
!n.isDecl(DeclKind::Accessor),
|
||||||
|
"Should not find accessors in iterable types or brace statements");
|
||||||
return isLocalizable(n) && !n.isDecl(DeclKind::Var) &&
|
return isLocalizable(n) && !n.isDecl(DeclKind::Var) &&
|
||||||
!n.isDecl(DeclKind::EnumCase);
|
!n.isDecl(DeclKind::EnumCase);
|
||||||
});
|
});
|
||||||
@@ -578,13 +572,13 @@ private:
|
|||||||
dumpPBD(pbd, "prev");
|
dumpPBD(pbd, "prev");
|
||||||
if (auto *pbd = dyn_cast<PatternBindingDecl>(d)) {
|
if (auto *pbd = dyn_cast<PatternBindingDecl>(d)) {
|
||||||
dumpPBD(pbd, "curr");
|
dumpPBD(pbd, "curr");
|
||||||
llvm_unreachable("found colliding pattern binding decls");
|
ASTScope_unreachable("found colliding pattern binding decls");
|
||||||
}
|
}
|
||||||
llvm::errs() << "Two same kind decls at same loc: \n";
|
llvm::errs() << "Two same kind decls at same loc: \n";
|
||||||
lastD->dump(llvm::errs());
|
lastD->dump(llvm::errs());
|
||||||
llvm::errs() << "and\n";
|
llvm::errs() << "and\n";
|
||||||
d->dump(llvm::errs());
|
d->dump(llvm::errs());
|
||||||
llvm_unreachable("Two same kind decls; unexpected kinds");
|
ASTScope_unreachable("Two same kind decls; unexpected kinds");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +612,8 @@ private:
|
|||||||
dumpRangeable(n2, llvm::errs());
|
dumpRangeable(n2, llvm::errs());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(startOrder * endOrder != -1 && "Start order contradicts end order");
|
ASTScopeAssert(startOrder * endOrder != -1,
|
||||||
|
"Start order contradicts end order");
|
||||||
return startOrder + endOrder < 1;
|
return startOrder + endOrder < 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,18 +632,18 @@ public:
|
|||||||
// they get created directly by the pattern code.
|
// they get created directly by the pattern code.
|
||||||
// Doing otherwise distorts the source range
|
// Doing otherwise distorts the source range
|
||||||
// of their parents.
|
// of their parents.
|
||||||
assert(!n.isDecl(DeclKind::Accessor) && "Should not see accessors here");
|
ASTScopeAssert(!n.isDecl(DeclKind::Accessor),
|
||||||
|
"Should not see accessors here");
|
||||||
// Can occur in illegal code
|
// Can occur in illegal code
|
||||||
if (auto *const s = n.dyn_cast<Stmt *>()) {
|
if (auto *const s = n.dyn_cast<Stmt *>()) {
|
||||||
if (auto *const bs = dyn_cast<BraceStmt>(s))
|
if (auto *const bs = dyn_cast<BraceStmt>(s))
|
||||||
assert(bs->getNumElements() == 0 && "Might mess up insertion point");
|
ASTScopeAssert(bs->getNumElements() == 0,
|
||||||
|
"Might mess up insertion point");
|
||||||
}
|
}
|
||||||
return !n.isDecl(DeclKind::Var);
|
return !n.isDecl(DeclKind::Var);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldBeLazy() const {
|
bool shouldBeLazy() const { return ctx.LangOpts.LazyASTScopes; }
|
||||||
return !getIsFreezing() && ctx.LangOpts.LazyASTScopes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// For debugging. Return true if scope tree contains all the decl contexts in
|
/// For debugging. Return true if scope tree contains all the decl contexts in
|
||||||
@@ -658,11 +653,9 @@ public:
|
|||||||
auto allDeclContexts = findLocalizableDeclContextsInAST();
|
auto allDeclContexts = findLocalizableDeclContextsInAST();
|
||||||
llvm::DenseMap<const DeclContext *, const ASTScopeImpl *> bogusDCs;
|
llvm::DenseMap<const DeclContext *, const ASTScopeImpl *> bogusDCs;
|
||||||
bool rebuilt = false;
|
bool rebuilt = false;
|
||||||
if (!getIsFrozen()) {
|
sourceFileScope->preOrderDo([&](ASTScopeImpl *scope) {
|
||||||
sourceFileScope->preOrderDo([&](ASTScopeImpl *scope) {
|
rebuilt |= scope->reexpandIfObsolete(*this);
|
||||||
rebuilt |= scope->reexpandIfObsolete(*this);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
sourceFileScope->postOrderDo([&](ASTScopeImpl *scope) {
|
sourceFileScope->postOrderDo([&](ASTScopeImpl *scope) {
|
||||||
if (auto *dc = scope->getDeclContext().getPtrOrNull()) {
|
if (auto *dc = scope->getDeclContext().getPtrOrNull()) {
|
||||||
auto iter = allDeclContexts.find(dc);
|
auto iter = allDeclContexts.find(dc);
|
||||||
@@ -731,7 +724,7 @@ public:
|
|||||||
void *operator new(size_t bytes, const ASTContext &ctx,
|
void *operator new(size_t bytes, const ASTContext &ctx,
|
||||||
unsigned alignment = alignof(ScopeCreator));
|
unsigned alignment = alignof(ScopeCreator));
|
||||||
void *operator new(size_t Bytes, void *Mem) {
|
void *operator new(size_t Bytes, void *Mem) {
|
||||||
assert(Mem);
|
ASTScopeAssert(Mem, "Allocation failed");
|
||||||
return Mem;
|
return Mem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -742,36 +735,46 @@ public:
|
|||||||
|
|
||||||
ASTScope::ASTScope(SourceFile *SF) : impl(createScopeTree(SF)) {}
|
ASTScope::ASTScope(SourceFile *SF) : impl(createScopeTree(SF)) {}
|
||||||
|
|
||||||
void ASTScope::buildScopeTreeEagerly() {
|
void ASTScope::buildFullyExpandedTree() { impl->buildFullyExpandedTree(); }
|
||||||
impl->buildScopeTreeEagerly();
|
|
||||||
|
void ASTScope::
|
||||||
|
buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals() {
|
||||||
|
impl->buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTSourceFileScope *ASTScope::createScopeTree(SourceFile *SF) {
|
ASTSourceFileScope *ASTScope::createScopeTree(SourceFile *SF) {
|
||||||
ScopeCreator *scopeCreator = new (SF->getASTContext()) ScopeCreator(SF);
|
ScopeCreator *scopeCreator = new (SF->getASTContext()) ScopeCreator(SF);
|
||||||
scopeCreator->sourceFileScope->addNewDeclsToScopeTree();
|
|
||||||
return scopeCreator->sourceFileScope;
|
return scopeCreator->sourceFileScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTSourceFileScope::buildScopeTreeEagerly() {
|
void ASTSourceFileScope::buildFullyExpandedTree() {
|
||||||
scopeCreator->beFreezing();
|
addNewDeclsToScopeTree();
|
||||||
// Eagerly expand any decls already in the tree.
|
preOrderChildrenDo(
|
||||||
preOrderDo([&](ASTScopeImpl *s) { s->reexpandIfObsolete(*scopeCreator); });
|
[&](ASTScopeImpl *s) { s->reexpandIfObsolete(*scopeCreator); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTSourceFileScope::
|
||||||
|
buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals() {
|
||||||
addNewDeclsToScopeTree();
|
addNewDeclsToScopeTree();
|
||||||
scopeCreator->beFrozen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTSourceFileScope::addNewDeclsToScopeTree() {
|
void ASTSourceFileScope::addNewDeclsToScopeTree() {
|
||||||
assert(SF && scopeCreator);
|
ASTScopeAssert(SF && scopeCreator,
|
||||||
|
"Must already have a SourceFile and a ScopeCreator.");
|
||||||
ArrayRef<Decl *> decls = SF->Decls;
|
ArrayRef<Decl *> decls = SF->Decls;
|
||||||
// Assume that decls are only added at the end, in source order
|
// Assume that decls are only added at the end, in source order
|
||||||
ArrayRef<Decl *> newDecls = decls.slice(numberOfDeclsAlreadySeen);
|
ArrayRef<Decl *> newDecls = decls.slice(numberOfDeclsAlreadySeen);
|
||||||
std::vector<ASTNode> newNodes(newDecls.begin(), newDecls.end());
|
std::vector<ASTNode> newNodes(newDecls.begin(), newDecls.end());
|
||||||
insertionPoint =
|
insertionPoint =
|
||||||
scopeCreator->addSiblingsToScopeTree(insertionPoint, newNodes);
|
scopeCreator->addSiblingsToScopeTree(insertionPoint, this, newNodes);
|
||||||
|
|
||||||
|
// TODO: use regular expansion machinery for ASTSourceFileScope
|
||||||
|
// rdar://55562483
|
||||||
numberOfDeclsAlreadySeen = SF->Decls.size();
|
numberOfDeclsAlreadySeen = SF->Decls.size();
|
||||||
|
setWasExpanded();
|
||||||
|
|
||||||
// Too slow to perform all the time:
|
// Too slow to perform all the time:
|
||||||
// assert(scopeCreator->containsAllDeclContextsFromAST() &&
|
// ASTScopeAssert(scopeCreator->containsAllDeclContextsFromAST(),
|
||||||
// "ASTScope tree missed some DeclContexts or made some up");
|
// "ASTScope tree missed some DeclContexts or made some up");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,7 +900,7 @@ public:
|
|||||||
#pragma mark special-case creation
|
#pragma mark special-case creation
|
||||||
|
|
||||||
ASTScopeImpl *visitSourceFile(SourceFile *, ASTScopeImpl *, ScopeCreator &) {
|
ASTScopeImpl *visitSourceFile(SourceFile *, ASTScopeImpl *, ScopeCreator &) {
|
||||||
llvm_unreachable("SourceFiles are orphans.");
|
ASTScope_unreachable("SourceFiles are orphans.");
|
||||||
}
|
}
|
||||||
|
|
||||||
NullablePtr<ASTScopeImpl> visitYieldStmt(YieldStmt *ys, ASTScopeImpl *p,
|
NullablePtr<ASTScopeImpl> visitYieldStmt(YieldStmt *ys, ASTScopeImpl *p,
|
||||||
@@ -975,8 +978,9 @@ public:
|
|||||||
NullablePtr<ASTScopeImpl> visitIfConfigDecl(IfConfigDecl *icd,
|
NullablePtr<ASTScopeImpl> visitIfConfigDecl(IfConfigDecl *icd,
|
||||||
ASTScopeImpl *p,
|
ASTScopeImpl *p,
|
||||||
ScopeCreator &scopeCreator) {
|
ScopeCreator &scopeCreator) {
|
||||||
llvm_unreachable("Should be handled inside of "
|
ASTScope_unreachable(
|
||||||
"expandIfConfigClausesThenCullAndSortElementsOrMembers");
|
"Should be handled inside of "
|
||||||
|
"expandIfConfigClausesThenCullAndSortElementsOrMembers");
|
||||||
}
|
}
|
||||||
|
|
||||||
NullablePtr<ASTScopeImpl> visitReturnStmt(ReturnStmt *rs, ASTScopeImpl *p,
|
NullablePtr<ASTScopeImpl> visitReturnStmt(ReturnStmt *rs, ASTScopeImpl *p,
|
||||||
@@ -1058,12 +1062,9 @@ void ASTScopeImpl::addChild(ASTScopeImpl *child, ASTContext &ctx) {
|
|||||||
haveAddedCleanup = true;
|
haveAddedCleanup = true;
|
||||||
}
|
}
|
||||||
storedChildren.push_back(child);
|
storedChildren.push_back(child);
|
||||||
assert(!child->getParent() && "child should not already have parent");
|
ASTScopeAssert(!child->getParent(), "child should not already have parent");
|
||||||
child->parent = this;
|
child->parent = this;
|
||||||
clearCachedSourceRangesOfMeAndAncestors();
|
clearCachedSourceRangesOfMeAndAncestors();
|
||||||
// It's possible that some callees do lookups back into the tree.
|
|
||||||
// So make sure childrenCountWhenLastExpanded is up to date.
|
|
||||||
setChildrenCountWhenLastExpanded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTScopeImpl::removeChildren() {
|
void ASTScopeImpl::removeChildren() {
|
||||||
@@ -1085,11 +1086,17 @@ void ASTScopeImpl::disownDescendants(ScopeCreator &scopeCreator) {
|
|||||||
ASTScopeImpl *ASTScopeImpl::expandAndBeCurrent(ScopeCreator &scopeCreator) {
|
ASTScopeImpl *ASTScopeImpl::expandAndBeCurrent(ScopeCreator &scopeCreator) {
|
||||||
auto *insertionPoint = expandSpecifically(scopeCreator);
|
auto *insertionPoint = expandSpecifically(scopeCreator);
|
||||||
if (scopeCreator.shouldBeLazy()) {
|
if (scopeCreator.shouldBeLazy()) {
|
||||||
assert(!insertionPointForDeferredExpansion() ||
|
ASTScopeAssert(!insertionPointForDeferredExpansion() ||
|
||||||
insertionPointForDeferredExpansion().get() == insertionPoint);
|
insertionPointForDeferredExpansion().get() ==
|
||||||
|
insertionPoint,
|
||||||
|
"In order for lookups into lazily-expanded scopes to be "
|
||||||
|
"accurate before expansion, the insertion point before "
|
||||||
|
"expansion must be the same as after expansion.");
|
||||||
}
|
}
|
||||||
|
setWasExpanded();
|
||||||
beCurrent();
|
beCurrent();
|
||||||
assert(checkSourceRangeAfterExpansion(scopeCreator.getASTContext()));
|
ASTScopeAssert(checkSourceRangeAfterExpansion(scopeCreator.getASTContext()),
|
||||||
|
"Bad range.");
|
||||||
return insertionPoint;
|
return insertionPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1179,9 +1186,9 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint(
|
|||||||
// we cannot make a scope for it, since no source range.
|
// we cannot make a scope for it, since no source range.
|
||||||
if (patternEntry.getOriginalInit() &&
|
if (patternEntry.getOriginalInit() &&
|
||||||
isLocalizable(patternEntry.getOriginalInit())) {
|
isLocalizable(patternEntry.getOriginalInit())) {
|
||||||
assert(
|
ASTScopeAssert(
|
||||||
!getSourceManager().isBeforeInBuffer(
|
!getSourceManager().isBeforeInBuffer(
|
||||||
patternEntry.getOriginalInit()->getStartLoc(), decl->getStartLoc()) &&
|
patternEntry.getOriginalInit()->getStartLoc(), decl->getStartLoc()),
|
||||||
"Original inits are always after the '='");
|
"Original inits are always after the '='");
|
||||||
scopeCreator
|
scopeCreator
|
||||||
.constructExpandAndInsertUncheckable<PatternEntryInitializerScope>(
|
.constructExpandAndInsertUncheckable<PatternEntryInitializerScope>(
|
||||||
@@ -1191,8 +1198,8 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint(
|
|||||||
forEachVarDeclWithLocalizableAccessors(scopeCreator, [&](VarDecl *var) {
|
forEachVarDeclWithLocalizableAccessors(scopeCreator, [&](VarDecl *var) {
|
||||||
scopeCreator.ifUniqueConstructExpandAndInsert<VarDeclScope>(this, var);
|
scopeCreator.ifUniqueConstructExpandAndInsert<VarDeclScope>(this, var);
|
||||||
});
|
});
|
||||||
assert(!handleUseBeforeDef &&
|
ASTScopeAssert(!handleUseBeforeDef,
|
||||||
"next line is wrong otherwise; would need a use scope");
|
"next line is wrong otherwise; would need a use scope");
|
||||||
|
|
||||||
return {getParent().get(), "When not handling use-before-def, succeeding "
|
return {getParent().get(), "When not handling use-before-def, succeeding "
|
||||||
"code just goes in the same scope as this one"};
|
"code just goes in the same scope as this one"};
|
||||||
@@ -1230,7 +1237,7 @@ ConditionalClauseScope::expandAScopeThatCreatesANewInsertionPoint(
|
|||||||
return {ccPatternUseScope,
|
return {ccPatternUseScope,
|
||||||
"Succeeding code must be in scope of conditional variables"};
|
"Succeeding code must be in scope of conditional variables"};
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unhandled StmtConditionKind in switch");
|
ASTScope_unreachable("Unhandled StmtConditionKind in switch");
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotatedInsertionPoint
|
AnnotatedInsertionPoint
|
||||||
@@ -1263,7 +1270,7 @@ BraceStmtScope::expandAScopeThatCreatesANewInsertionPoint(
|
|||||||
ScopeCreator &scopeCreator) {
|
ScopeCreator &scopeCreator) {
|
||||||
// TODO: remove the sort after performing rdar://53254395
|
// TODO: remove the sort after performing rdar://53254395
|
||||||
auto *insertionPoint =
|
auto *insertionPoint =
|
||||||
scopeCreator.addSiblingsToScopeTree(this, stmt->getElements());
|
scopeCreator.addSiblingsToScopeTree(this, this, stmt->getElements());
|
||||||
if (auto *s = scopeCreator.getASTContext().Stats)
|
if (auto *s = scopeCreator.getASTContext().Stats)
|
||||||
++s->getFrontendCounters().NumBraceStmtASTScopeExpansions;
|
++s->getFrontendCounters().NumBraceStmtASTScopeExpansions;
|
||||||
return {
|
return {
|
||||||
@@ -1289,7 +1296,7 @@ TopLevelCodeScope::expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &
|
|||||||
|
|
||||||
void ASTSourceFileScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
|
void ASTSourceFileScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
|
||||||
ScopeCreator &scopeCreator) {
|
ScopeCreator &scopeCreator) {
|
||||||
llvm_unreachable("expanded by addNewDeclsToScopeTree()");
|
ASTScope_unreachable("expanded by addNewDeclsToScopeTree()");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create child scopes for every declaration in a body.
|
// Create child scopes for every declaration in a body.
|
||||||
@@ -1484,7 +1491,8 @@ void DefaultArgumentInitializerScope::
|
|||||||
expandAScopeThatDoesNotCreateANewInsertionPoint(
|
expandAScopeThatDoesNotCreateANewInsertionPoint(
|
||||||
ScopeCreator &scopeCreator) {
|
ScopeCreator &scopeCreator) {
|
||||||
auto *initExpr = decl->getDefaultValue();
|
auto *initExpr = decl->getDefaultValue();
|
||||||
assert(initExpr);
|
ASTScopeAssert(initExpr,
|
||||||
|
"Default argument initializer must have an initializer.");
|
||||||
scopeCreator.addToScopeTree(initExpr, this);
|
scopeCreator.addToScopeTree(initExpr, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1599,8 +1607,8 @@ AbstractPatternEntryScope::AbstractPatternEntryScope(
|
|||||||
PatternBindingDecl *declBeingScoped, unsigned entryIndex,
|
PatternBindingDecl *declBeingScoped, unsigned entryIndex,
|
||||||
DeclVisibilityKind vis)
|
DeclVisibilityKind vis)
|
||||||
: decl(declBeingScoped), patternEntryIndex(entryIndex), vis(vis) {
|
: decl(declBeingScoped), patternEntryIndex(entryIndex), vis(vis) {
|
||||||
assert(entryIndex < declBeingScoped->getPatternList().size() &&
|
ASTScopeAssert(entryIndex < declBeingScoped->getPatternList().size(),
|
||||||
"out of bounds");
|
"out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractPatternEntryScope::forEachVarDeclWithLocalizableAccessors(
|
void AbstractPatternEntryScope::forEachVarDeclWithLocalizableAccessors(
|
||||||
@@ -1649,7 +1657,8 @@ bool ASTScopeImpl::isATypeDeclScope() const {
|
|||||||
void ScopeCreator::forEachClosureIn(
|
void ScopeCreator::forEachClosureIn(
|
||||||
Expr *expr, function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
|
Expr *expr, function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
|
||||||
foundClosure) {
|
foundClosure) {
|
||||||
assert(expr);
|
ASTScopeAssert(expr,
|
||||||
|
"If looking for closures, must have an expression to search.");
|
||||||
|
|
||||||
/// AST walker that finds top-level closures in an expression.
|
/// AST walker that finds top-level closures in an expression.
|
||||||
class ClosureFinder : public ASTWalker {
|
class ClosureFinder : public ASTWalker {
|
||||||
@@ -1720,7 +1729,7 @@ void GenericTypeOrExtensionScope::expandBody(ScopeCreator &) {}
|
|||||||
|
|
||||||
void IterableTypeScope::expandBody(ScopeCreator &scopeCreator) {
|
void IterableTypeScope::expandBody(ScopeCreator &scopeCreator) {
|
||||||
auto nodes = asNodeVector(getIterableDeclContext().get()->getMembers());
|
auto nodes = asNodeVector(getIterableDeclContext().get()->getMembers());
|
||||||
scopeCreator.addSiblingsToScopeTree(this, nodes);
|
scopeCreator.addSiblingsToScopeTree(this, this, nodes);
|
||||||
if (auto *s = scopeCreator.getASTContext().Stats)
|
if (auto *s = scopeCreator.getASTContext().Stats)
|
||||||
++s->getFrontendCounters().NumIterableTypeBodyASTScopeExpansions;
|
++s->getFrontendCounters().NumIterableTypeBodyASTScopeExpansions;
|
||||||
}
|
}
|
||||||
@@ -1728,19 +1737,22 @@ void IterableTypeScope::expandBody(ScopeCreator &scopeCreator) {
|
|||||||
#pragma mark - reexpandIfObsolete
|
#pragma mark - reexpandIfObsolete
|
||||||
|
|
||||||
bool ASTScopeImpl::reexpandIfObsolete(ScopeCreator &scopeCreator) {
|
bool ASTScopeImpl::reexpandIfObsolete(ScopeCreator &scopeCreator) {
|
||||||
if (scopeCreator.getIsFrozen() ||
|
if (isCurrent() &&
|
||||||
(isCurrent() &&
|
!scopeCreator.getASTContext().LangOpts.StressASTScopeLookup) {
|
||||||
!scopeCreator.getASTContext().LangOpts.StressASTScopeLookup))
|
ASTScopeAssert(getWasExpanded(), "Cannot be current if unexpanded.");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
reexpand(scopeCreator);
|
reexpand(scopeCreator);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTScopeImpl::reexpand(ScopeCreator &scopeCreator) {
|
void ASTScopeImpl::reexpand(ScopeCreator &scopeCreator) {
|
||||||
auto scopesToReuse = rescueScopesToReuse();
|
auto astAncestorScopes = rescueASTAncestorScopesForReuseFromMeOrDescendants();
|
||||||
disownDescendants(scopeCreator);
|
disownDescendants(scopeCreator);
|
||||||
|
// If the expansion recurses back into the tree for lookup, the ASTAncestor
|
||||||
|
// scopes will have already been rescued and won't be found! HERE
|
||||||
expandAndBeCurrent(scopeCreator);
|
expandAndBeCurrent(scopeCreator);
|
||||||
addReusedScopes(scopesToReuse);
|
replaceASTAncestorScopes(astAncestorScopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark getScopeCreator
|
#pragma mark getScopeCreator
|
||||||
@@ -1800,8 +1812,15 @@ NullablePtr<ASTScopeImpl>
|
|||||||
IterableTypeScope::insertionPointForDeferredExpansion() {
|
IterableTypeScope::insertionPointForDeferredExpansion() {
|
||||||
return portion->insertionPointForDeferredExpansion(this);
|
return portion->insertionPointForDeferredExpansion(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NullablePtr<ASTScopeImpl>
|
NullablePtr<ASTScopeImpl>
|
||||||
Portion::insertionPointForDeferredExpansion(IterableTypeScope *) const {
|
GenericTypeOrExtensionWholePortion::insertionPointForDeferredExpansion(
|
||||||
|
IterableTypeScope *s) const {
|
||||||
|
return s->getParent().get();
|
||||||
|
}
|
||||||
|
NullablePtr<ASTScopeImpl>
|
||||||
|
GenericTypeOrExtensionWherePortion::insertionPointForDeferredExpansion(
|
||||||
|
IterableTypeScope *) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
NullablePtr<ASTScopeImpl>
|
NullablePtr<ASTScopeImpl>
|
||||||
@@ -1810,23 +1829,46 @@ IterableTypeBodyPortion::insertionPointForDeferredExpansion(
|
|||||||
return s->getParent().get();
|
return s->getParent().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTScopeImpl::isCurrent() const {
|
||||||
|
return getWasExpanded() && isCurrentIfWasExpanded();
|
||||||
|
}
|
||||||
|
|
||||||
void ASTScopeImpl::beCurrent() {}
|
void ASTScopeImpl::beCurrent() {}
|
||||||
bool ASTScopeImpl::isCurrent() const { return true; }
|
bool ASTScopeImpl::isCurrentIfWasExpanded() const { return true; }
|
||||||
|
|
||||||
void IterableTypeScope::beCurrent() { portion->beCurrent(this); }
|
void IterableTypeScope::beCurrent() { portion->beCurrent(this); }
|
||||||
bool IterableTypeScope::isCurrent() const { return portion->isCurrent(this); }
|
bool IterableTypeScope::isCurrentIfWasExpanded() const {
|
||||||
|
return portion->isCurrentIfWasExpanded(this);
|
||||||
void Portion::beCurrent(IterableTypeScope *) const {}
|
}
|
||||||
bool Portion::isCurrent(const IterableTypeScope *) const { return true; }
|
|
||||||
|
|
||||||
|
void GenericTypeOrExtensionWholePortion::beCurrent(IterableTypeScope *s) const {
|
||||||
|
s->makeWholeCurrent();
|
||||||
|
}
|
||||||
|
bool GenericTypeOrExtensionWholePortion::isCurrentIfWasExpanded(
|
||||||
|
const IterableTypeScope *s) const {
|
||||||
|
return s->isWholeCurrent();
|
||||||
|
}
|
||||||
|
void GenericTypeOrExtensionWherePortion::beCurrent(IterableTypeScope *) const {}
|
||||||
|
bool GenericTypeOrExtensionWherePortion::isCurrentIfWasExpanded(
|
||||||
|
const IterableTypeScope *) const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void IterableTypeBodyPortion::beCurrent(IterableTypeScope *s) const {
|
void IterableTypeBodyPortion::beCurrent(IterableTypeScope *s) const {
|
||||||
s->makeBodyCurrent();
|
s->makeBodyCurrent();
|
||||||
}
|
}
|
||||||
bool IterableTypeBodyPortion::isCurrent(const IterableTypeScope *s) const {
|
bool IterableTypeBodyPortion::isCurrentIfWasExpanded(
|
||||||
|
const IterableTypeScope *s) const {
|
||||||
return s->isBodyCurrent();
|
return s->isBodyCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IterableTypeScope::makeWholeCurrent() {
|
||||||
|
ASTScopeAssert(getWasExpanded(), "Should have been expanded");
|
||||||
|
}
|
||||||
|
bool IterableTypeScope::isWholeCurrent() const {
|
||||||
|
// Whole starts out unexpanded, and is lazily built but will have at least a
|
||||||
|
// body scope child
|
||||||
|
return getWasExpanded();
|
||||||
|
}
|
||||||
void IterableTypeScope::makeBodyCurrent() {
|
void IterableTypeScope::makeBodyCurrent() {
|
||||||
memberCount = getIterableDeclContext().get()->getMemberCount();
|
memberCount = getIterableDeclContext().get()->getMemberCount();
|
||||||
}
|
}
|
||||||
@@ -1837,13 +1879,12 @@ bool IterableTypeScope::isBodyCurrent() const {
|
|||||||
void AbstractFunctionBodyScope::beCurrent() {
|
void AbstractFunctionBodyScope::beCurrent() {
|
||||||
bodyWhenLastExpanded = decl->getBody(false);
|
bodyWhenLastExpanded = decl->getBody(false);
|
||||||
}
|
}
|
||||||
bool AbstractFunctionBodyScope::isCurrent() const {
|
bool AbstractFunctionBodyScope::isCurrentIfWasExpanded() const {
|
||||||
return bodyWhenLastExpanded == decl->getBody(false);
|
return bodyWhenLastExpanded == decl->getBody(false);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopLevelCodeScope::beCurrent() { bodyWhenLastExpanded = decl->getBody(); }
|
void TopLevelCodeScope::beCurrent() { bodyWhenLastExpanded = decl->getBody(); }
|
||||||
bool TopLevelCodeScope::isCurrent() const {
|
bool TopLevelCodeScope::isCurrentIfWasExpanded() const {
|
||||||
return bodyWhenLastExpanded == decl->getBody();
|
return bodyWhenLastExpanded == decl->getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1862,11 +1903,12 @@ void PatternEntryDeclScope::beCurrent() {
|
|||||||
return;
|
return;
|
||||||
varCountWhenLastExpanded = countVars(getPatternEntry());
|
varCountWhenLastExpanded = countVars(getPatternEntry());
|
||||||
}
|
}
|
||||||
bool PatternEntryDeclScope::isCurrent() const {
|
bool PatternEntryDeclScope::isCurrentIfWasExpanded() const {
|
||||||
if (initWhenLastExpanded != getPatternEntry().getOriginalInit())
|
if (initWhenLastExpanded != getPatternEntry().getOriginalInit())
|
||||||
return false;
|
return false;
|
||||||
if (assumeVarsDoNotGetAdded && varCountWhenLastExpanded) {
|
if (assumeVarsDoNotGetAdded && varCountWhenLastExpanded) {
|
||||||
assert(varCountWhenLastExpanded == countVars(getPatternEntry()));
|
ASTScopeAssert(varCountWhenLastExpanded == countVars(getPatternEntry()),
|
||||||
|
"Vars were not supposed to be added to a pattern entry.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return countVars(getPatternEntry()) == varCountWhenLastExpanded;
|
return countVars(getPatternEntry()) == varCountWhenLastExpanded;
|
||||||
@@ -1875,62 +1917,69 @@ bool PatternEntryDeclScope::isCurrent() const {
|
|||||||
void WholeClosureScope::beCurrent() {
|
void WholeClosureScope::beCurrent() {
|
||||||
bodyWhenLastExpanded = closureExpr->getBody();
|
bodyWhenLastExpanded = closureExpr->getBody();
|
||||||
}
|
}
|
||||||
bool WholeClosureScope::isCurrent() const {
|
bool WholeClosureScope::isCurrentIfWasExpanded() const {
|
||||||
return bodyWhenLastExpanded == closureExpr->getBody();
|
return bodyWhenLastExpanded == closureExpr->getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark getParentOfRescuedScopes
|
#pragma mark getParentOfASTAncestorScopesToBeRescued
|
||||||
NullablePtr<ASTScopeImpl> ASTScopeImpl::getParentOfRescuedScopes() {
|
NullablePtr<ASTScopeImpl>
|
||||||
|
ASTScopeImpl::getParentOfASTAncestorScopesToBeRescued() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
NullablePtr<ASTScopeImpl>
|
NullablePtr<ASTScopeImpl>
|
||||||
AbstractFunctionBodyScope::getParentOfRescuedScopes() {
|
AbstractFunctionBodyScope::getParentOfASTAncestorScopesToBeRescued() {
|
||||||
// Reexpansion always creates a new body as the first child
|
// Reexpansion always creates a new body as the first child
|
||||||
|
// That body contains the scopes to be rescued.
|
||||||
return getChildren().empty() ? nullptr : getChildren().front();
|
return getChildren().empty() ? nullptr : getChildren().front();
|
||||||
}
|
}
|
||||||
NullablePtr<ASTScopeImpl> TopLevelCodeScope::getParentOfRescuedScopes() {
|
NullablePtr<ASTScopeImpl>
|
||||||
|
TopLevelCodeScope::getParentOfASTAncestorScopesToBeRescued() {
|
||||||
// Reexpansion always creates a new body as the first child
|
// Reexpansion always creates a new body as the first child
|
||||||
|
// That body contains the scopes to be rescued.
|
||||||
return getChildren().empty() ? nullptr : getChildren().front();
|
return getChildren().empty() ? nullptr : getChildren().front();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark rescuing & reusing
|
#pragma mark rescuing & reusing
|
||||||
std::vector<ASTScopeImpl *> ASTScopeImpl::rescueScopesToReuse() {
|
std::vector<ASTScopeImpl *>
|
||||||
if (auto *p = getParentOfRescuedScopes().getPtrOrNull()) {
|
ASTScopeImpl::rescueASTAncestorScopesForReuseFromMeOrDescendants() {
|
||||||
return p->rescueYoungestChildren(p->getChildren().size() -
|
if (auto *p = getParentOfASTAncestorScopesToBeRescued().getPtrOrNull()) {
|
||||||
p->childrenCountWhenLastExpanded);
|
return p->rescueASTAncestorScopesForReuseFromMe();
|
||||||
}
|
}
|
||||||
|
ASTScopeAssert(
|
||||||
|
getASTAncestorScopeCount() == 0,
|
||||||
|
"If receives ASTAncestor scopes, must know where to find parent");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTScopeImpl::addReusedScopes(ArrayRef<ASTScopeImpl *> scopesToAdd) {
|
void ASTScopeImpl::replaceASTAncestorScopes(
|
||||||
auto *p = getParentOfRescuedScopes().getPtrOrNull();
|
ArrayRef<ASTScopeImpl *> scopesToAdd) {
|
||||||
|
auto *p = getParentOfASTAncestorScopesToBeRescued().getPtrOrNull();
|
||||||
if (!p) {
|
if (!p) {
|
||||||
assert(scopesToAdd.empty() && "Non-empty body disappeared?!");
|
ASTScopeAssert(scopesToAdd.empty(), "Non-empty body disappeared?!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto &ctx = getASTContext();
|
auto &ctx = getASTContext();
|
||||||
for (auto *s : scopesToAdd) {
|
for (auto *s : scopesToAdd) {
|
||||||
p->addChild(s, ctx);
|
p->addChild(s, ctx);
|
||||||
assert(s->verifyThatThisNodeComeAfterItsPriorSibling() &&
|
ASTScopeAssert(s->verifyThatThisNodeComeAfterItsPriorSibling(),
|
||||||
"Ensure search will work");
|
"Ensure search will work");
|
||||||
}
|
}
|
||||||
|
p->increaseASTAncestorScopeCount(scopesToAdd.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ASTScopeImpl *>
|
std::vector<ASTScopeImpl *>
|
||||||
ASTScopeImpl::rescueYoungestChildren(const unsigned int count) {
|
ASTScopeImpl::rescueASTAncestorScopesForReuseFromMe() {
|
||||||
std::vector<ASTScopeImpl *> youngestChildren;
|
std::vector<ASTScopeImpl *> astAncestorScopes;
|
||||||
for (unsigned i = getChildren().size() - count; i < getChildren().size(); ++i)
|
for (unsigned i = getChildren().size() - getASTAncestorScopeCount();
|
||||||
youngestChildren.push_back(getChildren()[i]);
|
i < getChildren().size(); ++i)
|
||||||
|
astAncestorScopes.push_back(getChildren()[i]);
|
||||||
// So they don't get disowned and children cleared.
|
// So they don't get disowned and children cleared.
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < getASTAncestorScopeCount(); ++i) {
|
||||||
storedChildren.back()->emancipate();
|
storedChildren.back()->emancipate();
|
||||||
storedChildren.pop_back();
|
storedChildren.pop_back();
|
||||||
}
|
}
|
||||||
return youngestChildren;
|
resetASTAncestorScopeCount();
|
||||||
}
|
return astAncestorScopes;
|
||||||
|
|
||||||
void ASTScopeImpl::setChildrenCountWhenLastExpanded() {
|
|
||||||
childrenCountWhenLastExpanded = getChildren().size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractFunctionDeclScope::shouldCreateAccessorScope(
|
bool AbstractFunctionDeclScope::shouldCreateAccessorScope(
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ const ASTScopeImpl *ASTScopeImpl::findStartingScopeForLookup(
|
|||||||
return fileScope; // operators always at file scope
|
return fileScope; // operators always at file scope
|
||||||
|
|
||||||
const auto innermost = fileScope->findInnermostEnclosingScope(loc, nullptr);
|
const auto innermost = fileScope->findInnermostEnclosingScope(loc, nullptr);
|
||||||
|
ASTScopeAssert(innermost->getWasExpanded(),
|
||||||
|
"If looking in a scope, it must have been expanded.");
|
||||||
|
|
||||||
// The legacy lookup code gets passed both a SourceLoc and a starting context.
|
// The legacy lookup code gets passed both a SourceLoc and a starting context.
|
||||||
// However, our ultimate intent is for clients to not have to pass in a
|
// However, our ultimate intent is for clients to not have to pass in a
|
||||||
@@ -95,10 +97,12 @@ const ASTScopeImpl *ASTScopeImpl::findStartingScopeForLookup(
|
|||||||
// fileScope->dump();
|
// fileScope->dump();
|
||||||
llvm::errs() << "\n\n";
|
llvm::errs() << "\n\n";
|
||||||
|
|
||||||
assert(fileScope->crossCheckWithAST());
|
// Might distort things
|
||||||
|
// if (fileScope->crossCheckWithAST())
|
||||||
|
// llvm::errs() << "Tree creation missed some DeclContexts.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(startingScope && "ASTScopeImpl: could not find startingScope");
|
ASTScopeAssert(startingScope, "ASTScopeImpl: could not find startingScope");
|
||||||
return startingScope;
|
return startingScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +127,8 @@ const ASTScopeImpl *ASTScopeImpl::findInnermostEnclosingScopeImpl(
|
|||||||
bool ASTScopeImpl::checkSourceRangeOfThisASTNode() const {
|
bool ASTScopeImpl::checkSourceRangeOfThisASTNode() const {
|
||||||
const auto r = getSourceRangeOfThisASTNode();
|
const auto r = getSourceRangeOfThisASTNode();
|
||||||
(void)r;
|
(void)r;
|
||||||
assert(!getSourceManager().isBeforeInBuffer(r.End, r.Start));
|
ASTScopeAssert(!getSourceManager().isBeforeInBuffer(r.End, r.Start),
|
||||||
|
"Range is backwards.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,12 +140,12 @@ ASTScopeImpl::findChildContaining(SourceLoc loc,
|
|||||||
SourceManager &sourceMgr;
|
SourceManager &sourceMgr;
|
||||||
|
|
||||||
bool operator()(const ASTScopeImpl *scope, SourceLoc loc) {
|
bool operator()(const ASTScopeImpl *scope, SourceLoc loc) {
|
||||||
assert(scope->checkSourceRangeOfThisASTNode());
|
ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range.");
|
||||||
return sourceMgr.isBeforeInBuffer(scope->getSourceRangeOfScope().End,
|
return sourceMgr.isBeforeInBuffer(scope->getSourceRangeOfScope().End,
|
||||||
loc);
|
loc);
|
||||||
}
|
}
|
||||||
bool operator()(SourceLoc loc, const ASTScopeImpl *scope) {
|
bool operator()(SourceLoc loc, const ASTScopeImpl *scope) {
|
||||||
assert(scope->checkSourceRangeOfThisASTNode());
|
ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range.");
|
||||||
return sourceMgr.isBeforeInBuffer(loc,
|
return sourceMgr.isBeforeInBuffer(loc,
|
||||||
scope->getSourceRangeOfScope().End);
|
scope->getSourceRangeOfScope().End);
|
||||||
}
|
}
|
||||||
@@ -169,7 +174,7 @@ bool ASTScopeImpl::doesContextMatchStartingContext(
|
|||||||
if (auto p = getParent())
|
if (auto p = getParent())
|
||||||
return p.get()->doesContextMatchStartingContext(context);
|
return p.get()->doesContextMatchStartingContext(context);
|
||||||
// Topmost scope always has a context, the SourceFile.
|
// Topmost scope always has a context, the SourceFile.
|
||||||
llvm_unreachable("topmost scope always has a context, the SourceFile");
|
ASTScope_unreachable("topmost scope always has a context, the SourceFile");
|
||||||
}
|
}
|
||||||
|
|
||||||
// For a SubscriptDecl with generic parameters, the call tries to do lookups
|
// For a SubscriptDecl with generic parameters, the call tries to do lookups
|
||||||
@@ -383,7 +388,7 @@ bool AbstractFunctionBodyScope::lookupLocalsOrMembers(
|
|||||||
|
|
||||||
bool MethodBodyScope::lookupLocalsOrMembers(
|
bool MethodBodyScope::lookupLocalsOrMembers(
|
||||||
ArrayRef<const ASTScopeImpl *> history, DeclConsumer consumer) const {
|
ArrayRef<const ASTScopeImpl *> history, DeclConsumer consumer) const {
|
||||||
assert(isAMethod(decl));
|
ASTScopeAssert(isAMethod(decl), "Asking for members of a non-method.");
|
||||||
if (AbstractFunctionBodyScope::lookupLocalsOrMembers(history, consumer))
|
if (AbstractFunctionBodyScope::lookupLocalsOrMembers(history, consumer))
|
||||||
return true;
|
return true;
|
||||||
return consumer.consume({decl->getImplicitSelfDecl()},
|
return consumer.consume({decl->getImplicitSelfDecl()},
|
||||||
@@ -392,7 +397,9 @@ bool MethodBodyScope::lookupLocalsOrMembers(
|
|||||||
|
|
||||||
bool PureFunctionBodyScope::lookupLocalsOrMembers(
|
bool PureFunctionBodyScope::lookupLocalsOrMembers(
|
||||||
ArrayRef<const ASTScopeImpl *> history, DeclConsumer consumer) const {
|
ArrayRef<const ASTScopeImpl *> history, DeclConsumer consumer) const {
|
||||||
assert(!isAMethod(decl));
|
ASTScopeAssert(
|
||||||
|
!isAMethod(decl),
|
||||||
|
"Should have called lookupLocalsOrMembers instead of this function.");
|
||||||
if (AbstractFunctionBodyScope::lookupLocalsOrMembers(history, consumer))
|
if (AbstractFunctionBodyScope::lookupLocalsOrMembers(history, consumer))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -491,7 +498,7 @@ bool ASTScopeImpl::lookupLocalBindingsInPattern(Pattern *p,
|
|||||||
NullablePtr<DeclContext>
|
NullablePtr<DeclContext>
|
||||||
GenericTypeOrExtensionWhereOrBodyPortion::computeSelfDC(
|
GenericTypeOrExtensionWhereOrBodyPortion::computeSelfDC(
|
||||||
ArrayRef<const ASTScopeImpl *> history) {
|
ArrayRef<const ASTScopeImpl *> history) {
|
||||||
assert(history.size() != 0 && "includes current scope");
|
ASTScopeAssert(history.size() != 0, "includes current scope");
|
||||||
size_t i = history.size() - 1; // skip last entry (this scope)
|
size_t i = history.size() - 1; // skip last entry (this scope)
|
||||||
while (i != 0) {
|
while (i != 0) {
|
||||||
Optional<NullablePtr<DeclContext>> maybeSelfDC =
|
Optional<NullablePtr<DeclContext>> maybeSelfDC =
|
||||||
@@ -632,7 +639,7 @@ Optional<bool> GenericParamScope::resolveIsCascadingUseForThisScope(
|
|||||||
Optional<bool> isCascadingUse) const {
|
Optional<bool> isCascadingUse) const {
|
||||||
if (auto *dc = getDeclContext().getPtrOrNull())
|
if (auto *dc = getDeclContext().getPtrOrNull())
|
||||||
return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, dc);
|
return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, dc);
|
||||||
llvm_unreachable("generic what?");
|
ASTScope_unreachable("generic what?");
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<bool> AbstractFunctionDeclScope::resolveIsCascadingUseForThisScope(
|
Optional<bool> AbstractFunctionDeclScope::resolveIsCascadingUseForThisScope(
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ using namespace ast_scope;
|
|||||||
static SourceLoc getStartOfFirstParam(ClosureExpr *closure);
|
static SourceLoc getStartOfFirstParam(ClosureExpr *closure);
|
||||||
static SourceLoc getLocEncompassingPotentialLookups(const SourceManager &,
|
static SourceLoc getLocEncompassingPotentialLookups(const SourceManager &,
|
||||||
SourceLoc endLoc);
|
SourceLoc endLoc);
|
||||||
|
static SourceLoc getLocAfterExtendedNominal(const ExtensionDecl *);
|
||||||
|
|
||||||
SourceRange ASTScopeImpl::widenSourceRangeForIgnoredASTNodes(
|
SourceRange ASTScopeImpl::widenSourceRangeForIgnoredASTNodes(
|
||||||
const SourceRange range) const {
|
const SourceRange range) const {
|
||||||
@@ -53,7 +54,7 @@ SourceRange
|
|||||||
ASTScopeImpl::widenSourceRangeForChildren(const SourceRange range,
|
ASTScopeImpl::widenSourceRangeForChildren(const SourceRange range,
|
||||||
const bool omitAssertions) const {
|
const bool omitAssertions) const {
|
||||||
if (getChildren().empty()) {
|
if (getChildren().empty()) {
|
||||||
assert(omitAssertions || range.Start.isValid());
|
ASTScopeAssert(omitAssertions || range.Start.isValid(), "Bad range.");
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
const auto childStart =
|
const auto childStart =
|
||||||
@@ -61,7 +62,7 @@ ASTScopeImpl::widenSourceRangeForChildren(const SourceRange range,
|
|||||||
const auto childEnd =
|
const auto childEnd =
|
||||||
getChildren().back()->getSourceRangeOfScope(omitAssertions).End;
|
getChildren().back()->getSourceRangeOfScope(omitAssertions).End;
|
||||||
auto childRange = SourceRange(childStart, childEnd);
|
auto childRange = SourceRange(childStart, childEnd);
|
||||||
assert(omitAssertions || childRange.isValid());
|
ASTScopeAssert(omitAssertions || childRange.isValid(), "Bad range.");
|
||||||
|
|
||||||
if (range.isInvalid())
|
if (range.isInvalid())
|
||||||
return childRange;
|
return childRange;
|
||||||
@@ -71,12 +72,14 @@ ASTScopeImpl::widenSourceRangeForChildren(const SourceRange range,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ASTScopeImpl::checkSourceRangeAfterExpansion(const ASTContext &ctx) const {
|
bool ASTScopeImpl::checkSourceRangeAfterExpansion(const ASTContext &ctx) const {
|
||||||
assert((getSourceRangeOfThisASTNode().isValid() || !getChildren().empty()) &&
|
ASTScopeAssert(getSourceRangeOfThisASTNode().isValid() ||
|
||||||
"need to be able to find source range");
|
!getChildren().empty(),
|
||||||
assert(verifyThatChildrenAreContainedWithin(getSourceRangeOfScope()) &&
|
"need to be able to find source range");
|
||||||
"Search will fail");
|
ASTScopeAssert(verifyThatChildrenAreContainedWithin(getSourceRangeOfScope()),
|
||||||
assert(checkLazySourceRange(ctx) &&
|
"Search will fail");
|
||||||
"Lazy scopes must have compatible ranges before and after expansion");
|
ASTScopeAssert(
|
||||||
|
checkLazySourceRange(ctx),
|
||||||
|
"Lazy scopes must have compatible ranges before and after expansion");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -144,7 +147,7 @@ bool ASTScopeImpl::verifyThatThisNodeComeAfterItsPriorSibling() const {
|
|||||||
// .getRangeForBuffer(
|
// .getRangeForBuffer(
|
||||||
// getSourceFile()->getBufferID().getValue())
|
// getSourceFile()->getBufferID().getValue())
|
||||||
// .str();
|
// .str();
|
||||||
llvm_unreachable("unexpected out-of-order nodes");
|
ASTScope_unreachable("unexpected out-of-order nodes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +164,7 @@ NullablePtr<ASTScopeImpl> ASTScopeImpl::getPriorSibling() const {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(myIndex != -1 && "I have been disowned!");
|
ASTScopeAssert(myIndex != -1, "I have been disowned!");
|
||||||
if (myIndex == 0)
|
if (myIndex == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return siblingsAndMe[myIndex - 1];
|
return siblingsAndMe[myIndex - 1];
|
||||||
@@ -263,10 +266,15 @@ SourceRange GenericParamScope::getSourceRangeOfThisASTNode(
|
|||||||
// is visible from the start of the body.
|
// is visible from the start of the body.
|
||||||
if (auto *protoDecl = dyn_cast<ProtocolDecl>(nOrE))
|
if (auto *protoDecl = dyn_cast<ProtocolDecl>(nOrE))
|
||||||
return SourceRange(protoDecl->getBraces().Start, protoDecl->getEndLoc());
|
return SourceRange(protoDecl->getBraces().Start, protoDecl->getEndLoc());
|
||||||
auto startLoc = paramList->getSourceRange().Start;
|
const auto startLoc = paramList->getSourceRange().Start;
|
||||||
if (startLoc.isInvalid())
|
const auto validStartLoc =
|
||||||
startLoc = holder->getStartLoc();
|
startLoc.isValid() ? startLoc : holder->getStartLoc();
|
||||||
return SourceRange(startLoc, holder->getEndLoc());
|
// Since ExtensionScope (whole portion) range doesn't start till after the
|
||||||
|
// extended nominal, the range here must be pushed back, too.
|
||||||
|
if (auto const *const ext = dyn_cast<ExtensionDecl>(holder)) {
|
||||||
|
return SourceRange(getLocAfterExtendedNominal(ext), ext->getEndLoc());
|
||||||
|
}
|
||||||
|
return SourceRange(validStartLoc, holder->getEndLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRange ASTSourceFileScope::getSourceRangeOfThisASTNode(
|
SourceRange ASTSourceFileScope::getSourceRangeOfThisASTNode(
|
||||||
@@ -294,12 +302,28 @@ SourceRange GenericTypeOrExtensionWholePortion::getChildlessSourceRangeOf(
|
|||||||
auto *d = scope->getDecl();
|
auto *d = scope->getDecl();
|
||||||
auto r = d->getSourceRangeIncludingAttrs();
|
auto r = d->getSourceRangeIncludingAttrs();
|
||||||
if (r.Start.isValid()) {
|
if (r.Start.isValid()) {
|
||||||
assert(r.End.isValid());
|
ASTScopeAssert(r.End.isValid(), "Start valid imples end valid.");
|
||||||
return r;
|
return scope->moveStartPastExtendedNominal(r);
|
||||||
}
|
}
|
||||||
return d->getSourceRange();
|
return d->getSourceRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceRange
|
||||||
|
ExtensionScope::moveStartPastExtendedNominal(const SourceRange sr) const {
|
||||||
|
const auto start = getLocAfterExtendedNominal(decl);
|
||||||
|
// Illegal code can have an endLoc that is before the end of the
|
||||||
|
// ExtendedNominal, so push the end back, too, in that case.
|
||||||
|
const auto end =
|
||||||
|
getSourceManager().isBeforeInBuffer(sr.End, start) ? start : sr.End;
|
||||||
|
return SourceRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceRange
|
||||||
|
GenericTypeScope::moveStartPastExtendedNominal(const SourceRange sr) const {
|
||||||
|
// There is no extended nominal
|
||||||
|
return sr;
|
||||||
|
}
|
||||||
|
|
||||||
SourceRange GenericTypeOrExtensionWherePortion::getChildlessSourceRangeOf(
|
SourceRange GenericTypeOrExtensionWherePortion::getChildlessSourceRangeOf(
|
||||||
const GenericTypeOrExtensionScope *scope, const bool omitAssertions) const {
|
const GenericTypeOrExtensionScope *scope, const bool omitAssertions) const {
|
||||||
return scope->getGenericContext()->getTrailingWhereClause()->getSourceRange();
|
return scope->getGenericContext()->getTrailingWhereClause()->getSourceRange();
|
||||||
@@ -314,7 +338,7 @@ SourceRange IterableTypeBodyPortion::getChildlessSourceRangeOf(
|
|||||||
return e->getBraces();
|
return e->getBraces();
|
||||||
if (omitAssertions)
|
if (omitAssertions)
|
||||||
return SourceRange();
|
return SourceRange();
|
||||||
llvm_unreachable("No body!");
|
ASTScope_unreachable("No body!");
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceRange AbstractFunctionDeclScope::getSourceRangeOfThisASTNode(
|
SourceRange AbstractFunctionDeclScope::getSourceRangeOfThisASTNode(
|
||||||
@@ -323,7 +347,7 @@ SourceRange AbstractFunctionDeclScope::getSourceRangeOfThisASTNode(
|
|||||||
// them at the start location of the accessor.
|
// them at the start location of the accessor.
|
||||||
auto r = decl->getSourceRangeIncludingAttrs();
|
auto r = decl->getSourceRangeIncludingAttrs();
|
||||||
if (r.Start.isValid()) {
|
if (r.Start.isValid()) {
|
||||||
assert(r.End.isValid());
|
ASTScopeAssert(r.End.isValid(), "Start valid imples end valid.");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return decl->getBodySourceRange();
|
return decl->getBodySourceRange();
|
||||||
@@ -335,9 +359,9 @@ SourceRange ParameterListScope::getSourceRangeOfThisASTNode(
|
|||||||
getSourceRangeOfEnclosedParamsOfASTNode(omitAssertions);
|
getSourceRangeOfEnclosedParamsOfASTNode(omitAssertions);
|
||||||
auto r = SourceRange(rangeForGoodInput.Start,
|
auto r = SourceRange(rangeForGoodInput.Start,
|
||||||
fixupEndForBadInput(rangeForGoodInput));
|
fixupEndForBadInput(rangeForGoodInput));
|
||||||
assert(getSourceManager().rangeContains(
|
ASTScopeAssert(getSourceManager().rangeContains(
|
||||||
getParent().get()->getSourceRangeOfThisASTNode(true), r) &&
|
getParent().get()->getSourceRangeOfThisASTNode(true), r),
|
||||||
"Parameters not within function?!");
|
"Parameters not within function?!");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,8 +448,8 @@ CaptureListScope::getSourceRangeOfThisASTNode(const bool omitAssertions) const {
|
|||||||
SourceRange ClosureParametersScope::getSourceRangeOfThisASTNode(
|
SourceRange ClosureParametersScope::getSourceRangeOfThisASTNode(
|
||||||
const bool omitAssertions) const {
|
const bool omitAssertions) const {
|
||||||
if (!omitAssertions)
|
if (!omitAssertions)
|
||||||
assert(closureExpr->getInLoc().isValid() &&
|
ASTScopeAssert(closureExpr->getInLoc().isValid(),
|
||||||
"We don't create these if no in loc");
|
"We don't create these if no in loc");
|
||||||
return SourceRange(getStartOfFirstParam(closureExpr),
|
return SourceRange(getStartOfFirstParam(closureExpr),
|
||||||
closureExpr->getInLoc());
|
closureExpr->getInLoc());
|
||||||
}
|
}
|
||||||
@@ -459,7 +483,9 @@ ASTScopeImpl::getSourceRangeOfScope(const bool omitAssertions) const {
|
|||||||
|
|
||||||
bool ASTScopeImpl::isSourceRangeCached(const bool omitAssertions) const {
|
bool ASTScopeImpl::isSourceRangeCached(const bool omitAssertions) const {
|
||||||
const bool isCached = cachedSourceRange.hasValue();
|
const bool isCached = cachedSourceRange.hasValue();
|
||||||
assert(omitAssertions || isCached || ensureNoAncestorsSourceRangeIsCached());
|
ASTScopeAssert(omitAssertions || isCached ||
|
||||||
|
ensureNoAncestorsSourceRangeIsCached(),
|
||||||
|
"Cached ancestor's range likely is obsolete.");
|
||||||
return isCached;
|
return isCached;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +494,7 @@ bool ASTScopeImpl::ensureNoAncestorsSourceRangeIsCached() const {
|
|||||||
auto r = !p->isSourceRangeCached(true) &&
|
auto r = !p->isSourceRangeCached(true) &&
|
||||||
p->ensureNoAncestorsSourceRangeIsCached();
|
p->ensureNoAncestorsSourceRangeIsCached();
|
||||||
if (!r)
|
if (!r)
|
||||||
llvm_unreachable("found a violation");
|
ASTScope_unreachable("found a violation");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -554,8 +580,12 @@ static bool isInterpolatedStringLiteral(const Token& tok) {
|
|||||||
Segments.front().Kind != Lexer::StringSegment::Literal;
|
Segments.front().Kind != Lexer::StringSegment::Literal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If right brace is missing, the source range of the body will end
|
/// If right brace is missing, the source range of the body will end
|
||||||
// at the last token, which may be a one of the special cases below.
|
/// at the last token, which may be a one of the special cases below.
|
||||||
|
/// This work is only needed for *unexpanded* scopes because unioning the range
|
||||||
|
/// with the children will do the same thing for an expanded scope.
|
||||||
|
/// It is also needed for ignored \c ASTNodes, which may be, e.g. \c
|
||||||
|
/// InterpolatedStringLiterals
|
||||||
static SourceLoc getLocEncompassingPotentialLookups(const SourceManager &SM,
|
static SourceLoc getLocEncompassingPotentialLookups(const SourceManager &SM,
|
||||||
const SourceLoc endLoc) {
|
const SourceLoc endLoc) {
|
||||||
const auto tok = Lexer::getTokenAtLocation(SM, endLoc);
|
const auto tok = Lexer::getTokenAtLocation(SM, endLoc);
|
||||||
@@ -588,11 +618,33 @@ SourceRange AbstractFunctionBodyScope::sourceRangeForDeferredExpansion() const {
|
|||||||
return SourceRange(bsr.Start,
|
return SourceRange(bsr.Start,
|
||||||
endEvenIfNoCloseBraceAndEndsWithInterpolatedStringLiteral);
|
endEvenIfNoCloseBraceAndEndsWithInterpolatedStringLiteral);
|
||||||
}
|
}
|
||||||
SourceRange
|
|
||||||
Portion::sourceRangeForDeferredExpansion(const IterableTypeScope *) const {
|
SourceRange GenericTypeOrExtensionWholePortion::sourceRangeForDeferredExpansion(
|
||||||
|
const IterableTypeScope *s) const {
|
||||||
|
const auto rangeOfThisNodeWithoutChildren =
|
||||||
|
getChildlessSourceRangeOf(s, false);
|
||||||
|
const auto rangeExtendedForFinalToken = SourceRange(
|
||||||
|
rangeOfThisNodeWithoutChildren.Start,
|
||||||
|
getLocEncompassingPotentialLookups(s->getSourceManager(),
|
||||||
|
rangeOfThisNodeWithoutChildren.End));
|
||||||
|
const auto rangePastExtendedNominal =
|
||||||
|
s->moveStartPastExtendedNominal(rangeExtendedForFinalToken);
|
||||||
|
return rangePastExtendedNominal;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceRange GenericTypeOrExtensionWherePortion::sourceRangeForDeferredExpansion(
|
||||||
|
const IterableTypeScope *) const {
|
||||||
return SourceRange();
|
return SourceRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceRange IterableTypeBodyPortion::sourceRangeForDeferredExpansion(
|
||||||
|
const IterableTypeScope *s) const {
|
||||||
|
const auto bracesRange = getChildlessSourceRangeOf(s, false);
|
||||||
|
return SourceRange(bracesRange.Start,
|
||||||
|
getLocEncompassingPotentialLookups(s->getSourceManager(),
|
||||||
|
bracesRange.End));
|
||||||
|
}
|
||||||
|
|
||||||
SourceRange ASTScopeImpl::getEffectiveSourceRange(const ASTNode n) const {
|
SourceRange ASTScopeImpl::getEffectiveSourceRange(const ASTNode n) const {
|
||||||
if (const auto *d = n.dyn_cast<Decl *>())
|
if (const auto *d = n.dyn_cast<Decl *>())
|
||||||
return d->getSourceRange();
|
return d->getSourceRange();
|
||||||
@@ -696,12 +748,11 @@ AbstractFunctionDeclScope::getParmsSourceLocOfAFD(AbstractFunctionDecl *decl) {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark deferred scope source ranges
|
SourceLoc getLocAfterExtendedNominal(const ExtensionDecl *const ext) {
|
||||||
|
const auto *const etr = ext->getExtendedTypeRepr();
|
||||||
SourceRange IterableTypeBodyPortion::sourceRangeForDeferredExpansion(
|
if (!etr)
|
||||||
const IterableTypeScope *s) const {
|
return ext->getStartLoc();
|
||||||
const auto bracesRange = getChildlessSourceRangeOf(s, false);
|
const auto &SM = ext->getASTContext().SourceMgr;
|
||||||
const auto &SM = s->getSourceManager();
|
return Lexer::getCharSourceRangeFromSourceRange(SM, etr->getSourceRange())
|
||||||
return SourceRange(bracesRange.Start,
|
.getEnd();
|
||||||
getLocEncompassingPotentialLookups(SM, bracesRange.End));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,15 +227,15 @@ namespace {
|
|||||||
whereToLook, isCascadingUse.getValueOr(resolution)};
|
whereToLook, isCascadingUse.getValueOr(resolution)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool useASTScopesForExperimentalLookup() const;
|
bool useASTScopesForLookup() const;
|
||||||
|
|
||||||
/// For testing, assume this lookup is enabled:
|
/// For testing, assume this lookup is enabled:
|
||||||
bool useASTScopesForExperimentalLookupIfEnabled() const;
|
bool useASTScopesForLookupIfEnabled() const;
|
||||||
|
|
||||||
void lookUpTopLevelNamesInModuleScopeContext(DeclContext *);
|
void lookUpTopLevelNamesInModuleScopeContext(DeclContext *);
|
||||||
|
|
||||||
void experimentallyLookInASTScopes();
|
void lookInASTScopes();
|
||||||
|
|
||||||
/// Can lookup stop searching for results, assuming hasn't looked for outer
|
/// Can lookup stop searching for results, assuming hasn't looked for outer
|
||||||
/// results yet?
|
/// results yet?
|
||||||
@@ -473,7 +473,8 @@ UnqualifiedLookupFactory::UnqualifiedLookupFactory(
|
|||||||
void UnqualifiedLookupFactory::performUnqualifiedLookup() {
|
void UnqualifiedLookupFactory::performUnqualifiedLookup() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
++lookupCounter;
|
++lookupCounter;
|
||||||
stopForDebuggingIfStartingTargetLookup(false);
|
auto localCounter = lookupCounter;
|
||||||
|
(void)localCounter; // for debugging
|
||||||
#endif
|
#endif
|
||||||
FrontendStatsTracer StatsTracer(Ctx.Stats, "performUnqualifedLookup",
|
FrontendStatsTracer StatsTracer(Ctx.Stats, "performUnqualifedLookup",
|
||||||
DC->getParentSourceFile());
|
DC->getParentSourceFile());
|
||||||
@@ -482,30 +483,40 @@ void UnqualifiedLookupFactory::performUnqualifiedLookup() {
|
|||||||
|
|
||||||
ContextAndUnresolvedIsCascadingUse contextAndIsCascadingUse{
|
ContextAndUnresolvedIsCascadingUse contextAndIsCascadingUse{
|
||||||
DC, initialIsCascadingUse};
|
DC, initialIsCascadingUse};
|
||||||
const bool compareToASTScopes = Ctx.LangOpts.CompareToASTScopeLookup;
|
const bool crosscheckUnqualifiedLookup =
|
||||||
if (useASTScopesForExperimentalLookup() && !compareToASTScopes) {
|
Ctx.LangOpts.CrosscheckUnqualifiedLookup;
|
||||||
|
if (useASTScopesForLookup()) {
|
||||||
static bool haveWarned = false;
|
static bool haveWarned = false;
|
||||||
if (!haveWarned && Ctx.LangOpts.WarnIfASTScopeLookup) {
|
if (!haveWarned && Ctx.LangOpts.WarnIfASTScopeLookup) {
|
||||||
haveWarned = true;
|
haveWarned = true;
|
||||||
llvm::errs() << "WARNING: TRYING Scope exclusively\n";
|
llvm::errs() << "WARNING: TRYING Scope exclusively\n";
|
||||||
}
|
}
|
||||||
experimentallyLookInASTScopes();
|
lookInASTScopes();
|
||||||
return;
|
} else {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
stopForDebuggingIfStartingTargetLookup(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (Name.isOperator())
|
||||||
|
lookupOperatorInDeclContexts(contextAndIsCascadingUse);
|
||||||
|
else
|
||||||
|
lookupNamesIntroducedBy(contextAndIsCascadingUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Name.isOperator())
|
if (crosscheckUnqualifiedLookup && useASTScopesForLookupIfEnabled()) {
|
||||||
lookupOperatorInDeclContexts(contextAndIsCascadingUse);
|
|
||||||
else
|
|
||||||
lookupNamesIntroducedBy(contextAndIsCascadingUse);
|
|
||||||
|
|
||||||
if (compareToASTScopes && useASTScopesForExperimentalLookupIfEnabled()) {
|
|
||||||
ResultsVector results;
|
ResultsVector results;
|
||||||
size_t indexOfFirstOuterResult = 0;
|
size_t indexOfFirstOuterResult = 0;
|
||||||
UnqualifiedLookupFactory scopeLookup(Name, DC, Loc, options,
|
UnqualifiedLookupFactory altLookup(Name, DC, Loc, options, results,
|
||||||
results, indexOfFirstOuterResult);
|
indexOfFirstOuterResult);
|
||||||
scopeLookup.experimentallyLookInASTScopes();
|
if (!useASTScopesForLookup())
|
||||||
assert(verifyEqualTo(std::move(scopeLookup), "UnqualifedLookup",
|
altLookup.lookInASTScopes();
|
||||||
"Scope lookup"));
|
else if (Name.isOperator())
|
||||||
|
altLookup.lookupOperatorInDeclContexts(contextAndIsCascadingUse);
|
||||||
|
else
|
||||||
|
altLookup.lookupNamesIntroducedBy(contextAndIsCascadingUse);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
verifyEqualTo(std::move(altLookup), "main lookup", "alternate lookup"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,13 +541,11 @@ void UnqualifiedLookupFactory::lookUpTopLevelNamesInModuleScopeContext(
|
|||||||
recordCompletionOfAScope();
|
recordCompletionOfAScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnqualifiedLookupFactory::useASTScopesForExperimentalLookup() const {
|
bool UnqualifiedLookupFactory::useASTScopesForLookup() const {
|
||||||
return Ctx.LangOpts.EnableASTScopeLookup &&
|
return Ctx.LangOpts.EnableASTScopeLookup && useASTScopesForLookupIfEnabled();
|
||||||
useASTScopesForExperimentalLookupIfEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnqualifiedLookupFactory::useASTScopesForExperimentalLookupIfEnabled()
|
bool UnqualifiedLookupFactory::useASTScopesForLookupIfEnabled() const {
|
||||||
const {
|
|
||||||
if (!Loc.isValid())
|
if (!Loc.isValid())
|
||||||
return false;
|
return false;
|
||||||
const auto *const SF = DC->getParentSourceFile();
|
const auto *const SF = DC->getParentSourceFile();
|
||||||
@@ -1098,7 +1107,7 @@ UnqualifiedLookupFactory::ResultFinderForTypeContext::findSelfBounds(
|
|||||||
|
|
||||||
#pragma mark ASTScopeImpl support
|
#pragma mark ASTScopeImpl support
|
||||||
|
|
||||||
void UnqualifiedLookupFactory::experimentallyLookInASTScopes() {
|
void UnqualifiedLookupFactory::lookInASTScopes() {
|
||||||
|
|
||||||
ASTScopeDeclConsumerForUnqualifiedLookup consumer(*this);
|
ASTScopeDeclConsumerForUnqualifiedLookup consumer(*this);
|
||||||
|
|
||||||
@@ -1142,7 +1151,7 @@ bool ASTScopeDeclConsumerForUnqualifiedLookup::consume(
|
|||||||
// In order to preserve the behavior of the existing context-based lookup,
|
// In order to preserve the behavior of the existing context-based lookup,
|
||||||
// which finds all results for non-local variables at the top level instead
|
// which finds all results for non-local variables at the top level instead
|
||||||
// of stopping at the first one, ignore results at the top level that are
|
// of stopping at the first one, ignore results at the top level that are
|
||||||
// not local variables. The caller \c experimentallyLookInASTScopes will
|
// not local variables. The caller \c lookInASTScopes will
|
||||||
// then do the appropriate work when the scope lookup fails. In
|
// then do the appropriate work when the scope lookup fails. In
|
||||||
// FindLocalVal::visitBraceStmt, it sees PatternBindingDecls, not VarDecls,
|
// FindLocalVal::visitBraceStmt, it sees PatternBindingDecls, not VarDecls,
|
||||||
// so a VarDecl at top level would not be found by the context-based lookup.
|
// so a VarDecl at top level would not be found by the context-based lookup.
|
||||||
|
|||||||
@@ -337,7 +337,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
|||||||
Args.hasFlag(options::OPT_enable_astscope_lookup,
|
Args.hasFlag(options::OPT_enable_astscope_lookup,
|
||||||
options::OPT_disable_astscope_lookup, Opts.EnableASTScopeLookup) ||
|
options::OPT_disable_astscope_lookup, Opts.EnableASTScopeLookup) ||
|
||||||
Opts.DisableParserLookup;
|
Opts.DisableParserLookup;
|
||||||
Opts.CompareToASTScopeLookup |= Args.hasArg(OPT_compare_to_astscope_lookup);
|
Opts.CrosscheckUnqualifiedLookup |=
|
||||||
|
Args.hasArg(OPT_crosscheck_unqualified_lookup);
|
||||||
Opts.StressASTScopeLookup |= Args.hasArg(OPT_stress_astscope_lookup);
|
Opts.StressASTScopeLookup |= Args.hasArg(OPT_stress_astscope_lookup);
|
||||||
Opts.WarnIfASTScopeLookup |= Args.hasArg(OPT_warn_if_astscope_lookup);
|
Opts.WarnIfASTScopeLookup |= Args.hasArg(OPT_warn_if_astscope_lookup);
|
||||||
Opts.LazyASTScopes |= Args.hasArg(OPT_lazy_astscopes);
|
Opts.LazyASTScopes |= Args.hasArg(OPT_lazy_astscopes);
|
||||||
|
|||||||
@@ -749,13 +749,16 @@ static void dumpAndPrintScopeMap(CompilerInvocation &Invocation,
|
|||||||
|
|
||||||
if (Invocation.getFrontendOptions().DumpScopeMapLocations.empty()) {
|
if (Invocation.getFrontendOptions().DumpScopeMapLocations.empty()) {
|
||||||
llvm::errs() << "***Complete scope map***\n";
|
llvm::errs() << "***Complete scope map***\n";
|
||||||
|
scope.buildFullyExpandedTree();
|
||||||
scope.print(llvm::errs());
|
scope.print(llvm::errs());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Probe each of the locations, and dump what we find.
|
// Probe each of the locations, and dump what we find.
|
||||||
for (auto lineColumn :
|
for (auto lineColumn :
|
||||||
Invocation.getFrontendOptions().DumpScopeMapLocations)
|
Invocation.getFrontendOptions().DumpScopeMapLocations) {
|
||||||
|
scope.buildFullyExpandedTree();
|
||||||
scope.dumpOneScopeMapLocation(lineColumn);
|
scope.dumpOneScopeMapLocation(lineColumn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SourceFile *getPrimaryOrMainSourceFile(CompilerInvocation &Invocation,
|
static SourceFile *getPrimaryOrMainSourceFile(CompilerInvocation &Invocation,
|
||||||
|
|||||||
@@ -352,12 +352,14 @@ void swift::performTypeChecking(SourceFile &SF, TopLevelContext &TLC,
|
|||||||
if (SF.ASTStage == SourceFile::TypeChecked)
|
if (SF.ASTStage == SourceFile::TypeChecked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Eagerly build a scope tree before type checking
|
// Eagerly build the top-level scopes tree before type checking
|
||||||
// because type-checking mutates the AST and that throws off the scope-based
|
// because type-checking expressions mutates the AST and that throws off the
|
||||||
// lookups.
|
// scope-based lookups. Only the top-level scopes because extensions have not
|
||||||
|
// been bound yet.
|
||||||
if (SF.getASTContext().LangOpts.EnableASTScopeLookup &&
|
if (SF.getASTContext().LangOpts.EnableASTScopeLookup &&
|
||||||
SF.isSuitableForASTScopes())
|
SF.isSuitableForASTScopes())
|
||||||
SF.getScope().buildScopeTreeEagerly();
|
SF.getScope()
|
||||||
|
.buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
|
||||||
|
|
||||||
auto &Ctx = SF.getASTContext();
|
auto &Ctx = SF.getASTContext();
|
||||||
BufferIndirectlyCausingDiagnosticRAII cpr(SF);
|
BufferIndirectlyCausingDiagnosticRAII cpr(SF);
|
||||||
|
|||||||
@@ -27,31 +27,36 @@ var i: Int = b.my_identity()
|
|||||||
|
|
||||||
// CHECK-EXPANDED: ***Complete scope map***
|
// CHECK-EXPANDED: ***Complete scope map***
|
||||||
// CHECK-EXPANDED-NEXT: ASTSourceFileScope {{.*}}, (uncached) [1:1 - 6{{.*}}:1] 'SOURCE_DIR{{[/\\]}}test{{[/\\]}}NameBinding{{[/\\]}}scope_map_top_level.swift'
|
// CHECK-EXPANDED-NEXT: ASTSourceFileScope {{.*}}, (uncached) [1:1 - 6{{.*}}:1] 'SOURCE_DIR{{[/\\]}}test{{[/\\]}}NameBinding{{[/\\]}}scope_map_top_level.swift'
|
||||||
// CHECK-EXPANDED-NEXT: |-NominalTypeDeclScope {{.*}}, [4:1 - 4:13]
|
// CHECK-EXPANDED-NEXT: |-NominalTypeDeclScope {{.*}}, [4:1 - 4:13]
|
||||||
// CHECK-EXPANDED-NEXT: `-NominalTypeBodyScope {{.*}}, [4:11 - 4:13]
|
// CHECK-EXPANDED-NEXT: `-NominalTypeBodyScope {{.*}}, [4:11 - 4:13]
|
||||||
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [6:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [6:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [6:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [6:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [6:5 - 6:15] entry 0 'a'
|
// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [6:5 - 6:15] entry 0 'a'
|
||||||
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [6:15 - 6:15] entry 0 'a'
|
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [6:15 - 6:15] entry 0 'a'
|
||||||
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [8:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [8:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [8:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [8:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: `-GuardStmtScope {{.*}}, [8:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-GuardStmtScope {{.*}}, [8:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: |-ConditionalClauseScope, [8:7 - 8:22] index 0
|
// CHECK-EXPANDED-NEXT: |-ConditionalClauseScope, [8:7 - 8:22] index 0
|
||||||
// CHECK-EXPANDED-NEXT: `-ConditionalClausePatternUseScope, [8:22 - 8:22] let b?
|
// CHECK-EXPANDED-NEXT: `-ConditionalClausePatternUseScope, [8:22 - 8:22] let b{{\??}}
|
||||||
// CHECK-EXPANDED-NEXT: |-BraceStmtScope {{.*}}, [8:22 - 9:1]
|
// CHECK-EXPANDED-NEXT: |-BraceStmtScope {{.*}}, [8:22 - 9:1]
|
||||||
// CHECK-EXPANDED-NEXT: `-LookupParentDiversionScope, [9:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-LookupParentDiversionScope, [9:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: |-AbstractFunctionDeclScope {{.*}}, [11:1 - 11:13] 'foo()'
|
// CHECK-EXPANDED-NEXT: |-AbstractFunctionDeclScope {{.*}}, [11:1 - 11:13] 'foo()'
|
||||||
// CHECK-EXPANDED-NEXT: `-ParameterListScope {{.*}}, [11:9 - 11:13]
|
// CHECK-EXPANDED-NEXT: `-ParameterListScope {{.*}}, [11:9 - 11:13]
|
||||||
// CHECK-EXPANDED-NEXT: `-PureFunctionBodyScope {{.*}}, [11:12 - 11:13]
|
// CHECK-EXPANDED-NEXT: `-PureFunctionBodyScope {{.*}}, [11:12 - 11:13]
|
||||||
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [13:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [11:12 - 11:13]
|
||||||
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [13:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [13:1 - 21:28]
|
||||||
|
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [13:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [13:5 - 13:9] entry 0 'c'
|
// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [13:5 - 13:9] entry 0 'c'
|
||||||
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c'
|
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c'
|
||||||
// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15]
|
// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15]
|
||||||
// CHECK-EXPANDED-NEXT: |-ExtensionDeclScope {{.*}}, [17:1 - 19:1]
|
// CHECK-EXPANDED-NEXT: |-ExtensionDeclScope {{.*}}, [17:14 - 19:1]
|
||||||
// CHECK-EXPANDED-NEXT: `-ExtensionBodyScope {{.*}}, [17:15 - 19:1]
|
// CHECK-EXPANDED-NEXT: `-ExtensionBodyScope {{.*}}, [17:15 - 19:1]
|
||||||
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [21:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-AbstractFunctionDeclScope {{.*}}, [18:3 - 18:43] 'my_identity()'
|
||||||
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [21:1 - 21:28]
|
// CHECK-EXPANDED-NEXT: `-ParameterListScope {{.*}}, [18:19 - 18:43]
|
||||||
|
// CHECK-EXPANDED-NEXT: `-MethodBodyScope {{.*}}, [18:29 - 18:43]
|
||||||
|
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [18:29 - 18:43]
|
||||||
|
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [21:1 - 21:28]
|
||||||
|
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [21:1 - 21:28]
|
||||||
// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [21:5 - 21:28] entry 0 'i'
|
// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [21:5 - 21:28] entry 0 'i'
|
||||||
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [21:14 - 21:28] entry 0 'i'
|
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [21:14 - 21:28] entry 0 'i'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user