Skip to content

Commit 771fd6e

Browse files
committed
ASTScope: Redo assertions to look at CharSourceRanges
1 parent 4252659 commit 771fd6e

File tree

5 files changed

+52
-139
lines changed

5 files changed

+52
-139
lines changed

include/swift/AST/ASTScope.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,10 @@ class ASTScopeImpl {
273273

274274
protected:
275275
SourceManager &getSourceManager() const;
276-
bool hasValidSourceRange() const;
277-
bool hasValidSourceRangeOfIgnoredASTNodes() const;
278-
bool precedesInSource(const ASTScopeImpl *) const;
279-
bool verifyThatChildrenAreContainedWithin(SourceRange) const;
280-
bool verifyThatThisNodeComeAfterItsPriorSibling() const;
281276

282277
private:
283-
bool checkSourceRangeAfterExpansion(const ASTContext &) const;
278+
void checkSourceRangeBeforeAddingChild(ASTScopeImpl *child,
279+
const ASTContext &ctx) const;
284280

285281
#pragma mark common queries
286282
public:

lib/AST/ASTScopeCreation.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,6 @@ class ScopeCreator final {
334334

335335
ASTScopeImpl *insertionPoint =
336336
child->expandAndBeCurrentDetectingRecursion(*this);
337-
ASTScopeAssert(child->verifyThatThisNodeComeAfterItsPriorSibling(),
338-
"Ensure search will work");
339337
return insertionPoint;
340338
}
341339

@@ -881,6 +879,13 @@ ScopeCreator::addPatternBindingToScopeTree(PatternBindingDecl *patternBinding,
881879
#pragma mark creation helpers
882880

883881
void ASTScopeImpl::addChild(ASTScopeImpl *child, ASTContext &ctx) {
882+
ASTScopeAssert(!child->getParent(), "child should not already have parent");
883+
child->parent = this;
884+
885+
#ifndef NDEBUG
886+
checkSourceRangeBeforeAddingChild(child, ctx);
887+
#endif
888+
884889
// If this is the first time we've added children, notify the ASTContext
885890
// that there's a SmallVector that needs to be cleaned up.
886891
// FIXME: If we had access to SmallVector::isSmall(), we could do better.
@@ -889,8 +894,6 @@ void ASTScopeImpl::addChild(ASTScopeImpl *child, ASTContext &ctx) {
889894
haveAddedCleanup = true;
890895
}
891896
storedChildren.push_back(child);
892-
ASTScopeAssert(!child->getParent(), "child should not already have parent");
893-
child->parent = this;
894897
clearCachedSourceRangesOfMeAndAncestors();
895898
}
896899

@@ -926,8 +929,6 @@ ASTScopeImpl *ASTScopeImpl::expandAndBeCurrent(ScopeCreator &scopeCreator) {
926929

927930
setWasExpanded();
928931

929-
ASTScopeAssert(checkSourceRangeAfterExpansion(scopeCreator.getASTContext()),
930-
"Bad range.");
931932
return insertionPoint;
932933
}
933934

lib/AST/ASTScopePrinting.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,7 @@ static void printSourceRange(llvm::raw_ostream &out, const SourceRange range,
123123
}
124124

125125
void ASTScopeImpl::printRange(llvm::raw_ostream &out) const {
126-
if (!isSourceRangeCached(true))
127-
out << "(uncached) ";
128-
SourceRange range = computeSourceRangeOfScope(/*omitAssertions=*/true);
126+
SourceRange range = getSourceRangeOfThisASTNode(/*omitAssertions=*/true);
129127
printSourceRange(out, range, getSourceManager());
130128
}
131129

lib/AST/ASTScopeSourceRange.cpp

Lines changed: 41 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -79,113 +79,59 @@ ASTScopeImpl::widenSourceRangeForChildren(const SourceRange range,
7979
return r;
8080
}
8181

82-
bool ASTScopeImpl::checkSourceRangeAfterExpansion(const ASTContext &ctx) const {
83-
ASTScopeAssert(getSourceRangeOfThisASTNode().isValid() ||
84-
!getChildren().empty(),
85-
"need to be able to find source range");
86-
ASTScopeAssert(verifyThatChildrenAreContainedWithin(getSourceRangeOfScope()),
87-
"Search will fail");
88-
ASTScopeAssert(
89-
checkLazySourceRange(ctx),
90-
"Lazy scopes must have compatible ranges before and after expansion");
82+
void ASTScopeImpl::checkSourceRangeBeforeAddingChild(ASTScopeImpl *child,
83+
const ASTContext &ctx) const {
84+
auto &sourceMgr = ctx.SourceMgr;
9185

92-
return true;
93-
}
94-
95-
#pragma mark validation & debugging
86+
auto range = getCharSourceRangeOfScope(sourceMgr);
9687

97-
bool ASTScopeImpl::hasValidSourceRange() const {
98-
const auto sourceRange = getSourceRangeOfScope();
99-
return sourceRange.Start.isValid() && sourceRange.End.isValid() &&
100-
!getSourceManager().isBeforeInBuffer(sourceRange.End,
101-
sourceRange.Start);
102-
}
88+
auto childCharRange = child->getCharSourceRangeOfScope(sourceMgr);
10389

104-
bool ASTScopeImpl::hasValidSourceRangeOfIgnoredASTNodes() const {
105-
return sourceRangeOfIgnoredASTNodes.isValid();
106-
}
90+
bool childContainedInParent = [&]() {
91+
// HACK: For code completion. Handle replaced range.
92+
if (const auto &replacedRange = sourceMgr.getReplacedRange()) {
93+
auto originalRange = Lexer::getCharSourceRangeFromSourceRange(
94+
sourceMgr, replacedRange.Original);
95+
auto newRange = Lexer::getCharSourceRangeFromSourceRange(
96+
sourceMgr, replacedRange.New);
10797

108-
bool ASTScopeImpl::precedesInSource(const ASTScopeImpl *next) const {
109-
if (!hasValidSourceRange() || !next->hasValidSourceRange())
110-
return false;
111-
return !getSourceManager().isBeforeInBuffer(
112-
next->getSourceRangeOfScope().Start, getSourceRangeOfScope().End);
113-
}
98+
if (range.contains(originalRange) &&
99+
newRange.contains(childCharRange))
100+
return true;
101+
}
114102

115-
bool ASTScopeImpl::verifyThatChildrenAreContainedWithin(
116-
const SourceRange range) const {
117-
// assumes children are already in order
118-
if (getChildren().empty())
119-
return true;
120-
const SourceRange rangeOfChildren =
121-
SourceRange(getChildren().front()->getSourceRangeOfScope().Start,
122-
getChildren().back()->getSourceRangeOfScope().End);
123-
if (getSourceManager().rangeContains(range, rangeOfChildren))
124-
return true;
103+
return range.contains(childCharRange);
104+
}();
125105

126-
// HACK: For code completion. Handle replaced range.
127-
if (const auto &replacedRange = getSourceManager().getReplacedRange()) {
128-
if (getSourceManager().rangeContains(replacedRange.Original, range) &&
129-
getSourceManager().rangeContains(replacedRange.New, rangeOfChildren))
130-
return true;
106+
if (!childContainedInParent) {
107+
auto &out = verificationError() << "child not contained in its parent:\n";
108+
child->print(out);
109+
out << "\n***Parent node***\n";
110+
this->print(out);
111+
abort();
131112
}
132113

133-
auto &out = verificationError() << "children not contained in its parent\n";
134-
if (getChildren().size() == 1) {
135-
out << "\n***Only Child node***\n";
136-
getChildren().front()->print(out);
137-
} else {
138-
out << "\n***First Child node***\n";
139-
getChildren().front()->print(out);
140-
out << "\n***Last Child node***\n";
141-
getChildren().back()->print(out);
142-
}
143-
out << "\n***Parent node***\n";
144-
this->print(out);
145-
abort();
146-
}
147-
148-
bool ASTScopeImpl::verifyThatThisNodeComeAfterItsPriorSibling() const {
149-
auto priorSibling = getPriorSibling();
150-
if (!priorSibling)
151-
return true;
152-
if (priorSibling.get()->precedesInSource(this))
153-
return true;
154-
auto &out = verificationError() << "unexpected out-of-order nodes\n";
155-
out << "\n***Penultimate child node***\n";
156-
priorSibling.get()->print(out);
157-
out << "\n***Last Child node***\n";
158-
print(out);
159-
out << "\n***Parent node***\n";
160-
getParent().get()->print(out);
161-
// llvm::errs() << "\n\nsource:\n"
162-
// << getSourceManager()
163-
// .getRangeForBuffer(
164-
// getSourceFile()->getBufferID().getValue())
165-
// .str();
166-
ASTScope_unreachable("unexpected out-of-order nodes");
167-
return false;
168-
}
169-
170-
NullablePtr<ASTScopeImpl> ASTScopeImpl::getPriorSibling() const {
171-
auto parent = getParent();
172-
if (!parent)
173-
return nullptr;
174-
auto const &siblingsAndMe = parent.get()->getChildren();
175-
// find myIndex, which is probably the last one
176-
int myIndex = -1;
177-
for (int i = siblingsAndMe.size() - 1; i >= 0; --i) {
178-
if (siblingsAndMe[i] == this) {
179-
myIndex = i;
180-
break;
114+
if (!storedChildren.empty()) {
115+
auto previousChild = storedChildren.back();
116+
auto endOfPreviousChild = previousChild->getCharSourceRangeOfScope(
117+
sourceMgr).getEnd();
118+
119+
if (childCharRange.getStart() != endOfPreviousChild &&
120+
!sourceMgr.isBeforeInBuffer(endOfPreviousChild,
121+
childCharRange.getStart())) {
122+
auto &out = verificationError() << "child overlaps previous child:\n";
123+
child->print(out);
124+
out << "\n***Previous child\n";
125+
previousChild->print(out);
126+
out << "\n***Parent node***\n";
127+
this->print(out);
128+
abort();
181129
}
182130
}
183-
ASTScopeAssert(myIndex != -1, "I have been disowned!");
184-
if (myIndex == 0)
185-
return nullptr;
186-
return siblingsAndMe[myIndex - 1];
187131
}
188132

133+
#pragma mark validation & debugging
134+
189135
bool ASTScopeImpl::doesRangeMatch(unsigned start, unsigned end, StringRef file,
190136
StringRef className) {
191137
if (!className.empty() && className != getClassName())
@@ -509,34 +455,6 @@ void ASTScopeImpl::computeAndCacheSourceRangeOfScope(
509455
cachedSourceRange = computeSourceRangeOfScope(omitAssertions);
510456
}
511457

512-
bool ASTScopeImpl::checkLazySourceRange(const ASTContext &ctx) const {
513-
const auto unexpandedRange = sourceRangeForDeferredExpansion();
514-
const auto expandedRange = computeSourceRangeOfScopeWithChildASTNodes();
515-
if (unexpandedRange.isInvalid() || expandedRange.isInvalid())
516-
return true;
517-
if (unexpandedRange == expandedRange)
518-
return true;
519-
520-
llvm::errs() << "*** Lazy range problem. Parent unexpanded: ***\n";
521-
unexpandedRange.print(llvm::errs(), getSourceManager(), false);
522-
llvm::errs() << "\n";
523-
if (!getChildren().empty()) {
524-
llvm::errs() << "*** vs last child: ***\n";
525-
auto b = getChildren().back()->computeSourceRangeOfScope();
526-
b.print(llvm::errs(), getSourceManager(), false);
527-
llvm::errs() << "\n";
528-
}
529-
else if (hasValidSourceRangeOfIgnoredASTNodes()) {
530-
llvm::errs() << "*** vs ignored AST nodes: ***\n";
531-
sourceRangeOfIgnoredASTNodes.print(llvm::errs(), getSourceManager(), false);
532-
llvm::errs() << "\n";
533-
}
534-
print(llvm::errs(), 0, false);
535-
llvm::errs() << "\n";
536-
537-
return false;
538-
}
539-
540458
SourceRange
541459
ASTScopeImpl::computeSourceRangeOfScope(const bool omitAssertions) const {
542460
// If we don't need to consider children, it's cheaper

test/NameLookup/scope_map_top_level.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var i: Int = b.my_identity()
2626

2727

2828
// CHECK-EXPANDED: ***Complete scope map***
29-
// CHECK-EXPANDED-NEXT: ASTSourceFileScope {{.*}}, (uncached) [1:1 - 61:1] 'SOURCE_DIR{{[/\\]}}test{{[/\\]}}NameLookup{{[/\\]}}scope_map_top_level.swift'
29+
// CHECK-EXPANDED-NEXT: ASTSourceFileScope {{.*}} [1:1 - 61:1] 'SOURCE_DIR{{[/\\]}}test{{[/\\]}}NameLookup{{[/\\]}}scope_map_top_level.swift'
3030
// CHECK-EXPANDED-NEXT: |-NominalTypeDeclScope {{.*}}, [4:1 - 4:13]
3131
// CHECK-EXPANDED-NEXT: `-NominalTypeBodyScope {{.*}}, [4:11 - 4:13]
3232
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [6:1 - 61:1]

0 commit comments

Comments
 (0)