Skip to content

Commit b63ed2b

Browse files
authored
Merge pull request #80339 from hamishknight/macroscope
[ASTScope] Re-enable `checkSourceRangeBeforeAddingChild`
2 parents 2a7dbd8 + 6d89ed3 commit b63ed2b

File tree

8 files changed

+94
-39
lines changed

8 files changed

+94
-39
lines changed

include/swift/AST/ASTScope.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
239239
NullablePtr<Stmt> getStmtIfAny() const;
240240
NullablePtr<Expr> getExprIfAny() const;
241241

242+
/// Whether this scope is for a decl attribute.
243+
bool isDeclAttribute() const;
244+
242245
#pragma mark - debugging and printing
243246

244247
public:
@@ -264,7 +267,9 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
264267
void dumpOneScopeMapLocation(std::pair<unsigned, unsigned> lineColumn);
265268

266269
private:
267-
llvm::raw_ostream &verificationError() const;
270+
[[noreturn]]
271+
void abortWithVerificationError(
272+
llvm::function_ref<void(llvm::raw_ostream &)> messageFn) const;
268273

269274
#pragma mark - Scope tree creation
270275
public:

lib/AST/ASTScope.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,20 @@ NullablePtr<Expr> ASTScopeImpl::getExprIfAny() const {
297297
}
298298
}
299299

300+
bool ASTScopeImpl::isDeclAttribute() const {
301+
switch (getKind()) {
302+
#define DECL_ATTRIBUTE_SCOPE_NODE(Name) \
303+
case ScopeKind::Name: return true;
304+
#define SCOPE_NODE(Name)
305+
#include "swift/AST/ASTScopeNodes.def"
306+
307+
#define DECL_ATTRIBUTE_SCOPE_NODE(Name)
308+
#define SCOPE_NODE(Name) case ScopeKind::Name:
309+
#include "swift/AST/ASTScopeNodes.def"
310+
return false;
311+
}
312+
}
313+
300314
SourceManager &ASTScopeImpl::getSourceManager() const {
301315
return getASTContext().SourceMgr;
302316
}

lib/AST/ASTScopeCreation.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,12 @@ ASTScopeImpl *ScopeCreator::addToScopeTreeAndReturnInsertionPoint(
610610
void ScopeCreator::addChildrenForParsedAccessors(
611611
AbstractStorageDecl *asd, ASTScopeImpl *parent) {
612612
asd->visitParsedAccessors([&](AccessorDecl *ad) {
613+
// Ignore accessors added by macro expansions.
614+
// TODO: This ought to be the default behavior of `visitParsedAccessors`,
615+
// we ought to have a different entrypoint for clients that care about
616+
// the semantic set of "explicit" accessors.
617+
if (ad->isInMacroExpansionInContext())
618+
return;
613619
assert(asd == ad->getStorage());
614620
this->addToScopeTree(ad, parent);
615621
});
@@ -666,11 +672,16 @@ ScopeCreator::addPatternBindingToScopeTree(PatternBindingDecl *patternBinding,
666672
if (auto *var = patternBinding->getSingleVar())
667673
addChildrenForKnownAttributes(var, parentScope);
668674

675+
// Check to see if we have a local binding. Note we need to exclude bindings
676+
// in `@abi` attributes here since they may be in a local DeclContext, but
677+
// their scope shouldn't extend past the attribute.
669678
bool isLocalBinding = false;
670-
for (auto i : range(patternBinding->getNumPatternEntries())) {
671-
if (auto *varDecl = patternBinding->getAnchoringVarDecl(i)) {
672-
isLocalBinding = varDecl->getDeclContext()->isLocalContext();
673-
break;
679+
if (!isa<ABIAttributeScope>(parentScope)) {
680+
for (auto i : range(patternBinding->getNumPatternEntries())) {
681+
if (auto *varDecl = patternBinding->getAnchoringVarDecl(i)) {
682+
isLocalBinding = varDecl->getDeclContext()->isLocalContext();
683+
break;
684+
}
674685
}
675686
}
676687

@@ -703,7 +714,7 @@ void ASTScopeImpl::addChild(ASTScopeImpl *child, ASTContext &ctx) {
703714
child->parentAndWasExpanded.setPointer(this);
704715

705716
#ifndef NDEBUG
706-
// checkSourceRangeBeforeAddingChild(child, ctx);
717+
checkSourceRangeBeforeAddingChild(child, ctx);
707718
#endif
708719

709720
// If this is the first time we've added children, notify the ASTContext

lib/AST/ASTScopePrinting.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,17 @@ void ASTScopeImpl::dumpOneScopeMapLocation(
6969
}
7070
}
7171

72-
llvm::raw_ostream &ASTScopeImpl::verificationError() const {
73-
return llvm::errs() << "ASTScopeImpl verification error in source file '"
74-
<< getSourceFile()->getFilename() << "': ";
72+
void ASTScopeImpl::abortWithVerificationError(
73+
llvm::function_ref<void(llvm::raw_ostream &)> messageFn) const {
74+
llvm::SmallString<0> errorStr;
75+
llvm::raw_svector_ostream out(errorStr);
76+
77+
out << "ASTScopeImpl verification error in source file '"
78+
<< getSourceFile()->getFilename() << "':\n";
79+
messageFn(out);
80+
81+
llvm::PrettyStackTraceString trace(errorStr.c_str());
82+
abort();
7583
}
7684

7785
#pragma mark printing

lib/AST/ASTScopeSourceRange.cpp

+27-26
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,15 @@ using namespace ast_scope;
3939

4040
static SourceLoc getLocAfterExtendedNominal(const ExtensionDecl *);
4141

42-
/// Retrieve the character-based source range for the given source range.
43-
static SourceRange getCharSourceRange(
44-
SourceManager &sourceMgr, SourceRange range
45-
){
46-
range.End = Lexer::getLocForEndOfToken(sourceMgr, range.End);
47-
return range;
48-
}
49-
5042
void ASTScopeImpl::checkSourceRangeBeforeAddingChild(ASTScopeImpl *child,
5143
const ASTContext &ctx) const {
44+
// Ignore attributes on extensions, currently they exist outside of the
45+
// extension's source range due to the way we've setup the scope for
46+
// extension binding.
47+
// FIXME: We ought to fix the source range for extension scopes.
48+
if (isa<ExtensionScope>(this) && child->isDeclAttribute())
49+
return;
50+
5251
// Ignore debugger bindings - they're a special mix of user code and implicit
5352
// wrapper code that is too difficult to check for consistency.
5453
if (auto d = getDeclIfAny().getPtrOrNull())
@@ -60,14 +59,14 @@ void ASTScopeImpl::checkSourceRangeBeforeAddingChild(ASTScopeImpl *child,
6059

6160
auto range = getCharSourceRangeOfScope(sourceMgr);
6261

63-
std::function<bool(SourceRange)> containedInParent;
64-
containedInParent = [&](SourceRange childCharRange) {
62+
auto containedInParent = [&](SourceRange childCharRange) {
6563
// HACK: For code completion. Handle replaced range.
64+
// Note that the replaced SourceRanges here are already disguised
65+
// CharSourceRanges, we don't need to adjust them. We use `rangeContains`
66+
// since we're only interested in comparing within a single buffer.
6667
for (const auto &pair : sourceMgr.getReplacedRanges()) {
67-
auto originalRange = getCharSourceRange(sourceMgr, pair.first);
68-
auto newRange = getCharSourceRange(sourceMgr, pair.second);
69-
if (sourceMgr.encloses(range, originalRange) &&
70-
sourceMgr.encloses(newRange, childCharRange))
68+
if (sourceMgr.rangeContains(range, pair.first) &&
69+
sourceMgr.rangeContains(pair.second, childCharRange))
7170
return true;
7271
}
7372

@@ -77,11 +76,12 @@ void ASTScopeImpl::checkSourceRangeBeforeAddingChild(ASTScopeImpl *child,
7776
auto childCharRange = child->getCharSourceRangeOfScope(sourceMgr);
7877

7978
if (!containedInParent(childCharRange)) {
80-
auto &out = verificationError() << "child not contained in its parent:\n";
81-
child->print(out);
82-
out << "\n***Parent node***\n";
83-
this->print(out);
84-
abort();
79+
abortWithVerificationError([&](llvm::raw_ostream &out) {
80+
out << "child not contained in its parent:\n";
81+
child->print(out);
82+
out << "\n***Parent node***\n";
83+
this->print(out);
84+
});
8585
}
8686

8787
if (!storedChildren.empty()) {
@@ -90,13 +90,14 @@ void ASTScopeImpl::checkSourceRangeBeforeAddingChild(ASTScopeImpl *child,
9090
sourceMgr).End;
9191

9292
if (!sourceMgr.isAtOrBefore(endOfPreviousChild, childCharRange.Start)) {
93-
auto &out = verificationError() << "child overlaps previous child:\n";
94-
child->print(out);
95-
out << "\n***Previous child\n";
96-
previousChild->print(out);
97-
out << "\n***Parent node***\n";
98-
this->print(out);
99-
abort();
93+
abortWithVerificationError([&](llvm::raw_ostream &out) {
94+
out << "child overlaps previous child:\n";
95+
child->print(out);
96+
out << "\n***Previous child\n";
97+
previousChild->print(out);
98+
out << "\n***Parent node***\n";
99+
this->print(out);
100+
});
100101
}
101102
}
102103
}

lib/AST/Decl.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -1008,11 +1008,21 @@ SourceRange Decl::getSourceRangeIncludingAttrs() const {
10081008
}
10091009

10101010
bool Decl::isInMacroExpansionInContext() const {
1011-
auto *dc = getDeclContext();
1012-
auto parentFile = dc->getParentSourceFile();
10131011
auto *mod = getModuleContext();
10141012
auto *file = mod->getSourceFileContainingLocation(getStartLoc());
10151013

1014+
auto parentFile = [&]() {
1015+
// For accessors, the storage decl is the more accurate thing to check
1016+
// since the entire property/subscript could be macro-generated, in which
1017+
// case the accessor shouldn't be considered "added by macro expansion".
1018+
if (auto *accessor = dyn_cast<AccessorDecl>(this)) {
1019+
auto storageLoc = accessor->getStorage()->getLoc();
1020+
if (storageLoc.isValid())
1021+
return mod->getSourceFileContainingLocation(storageLoc);
1022+
}
1023+
return getDeclContext()->getParentSourceFile();
1024+
}();
1025+
10161026
// Decls in macro expansions always have a source file. The source
10171027
// file can be null if the decl is implicit or has an invalid
10181028
// source location.

lib/Basic/SourceLoc.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -841,11 +841,11 @@ static bool isBeforeInSource(
841841
SourceLoc firstLocInLCA = firstMismatch == firstAncestors.end()
842842
? firstLoc
843843
: sourceMgr.getGeneratedSourceInfo(*firstMismatch)
844-
->originalSourceRange.getEnd();
844+
->originalSourceRange.getStart();
845845
SourceLoc secondLocInLCA = secondMismatch == secondAncestors.end()
846846
? secondLoc
847847
: sourceMgr.getGeneratedSourceInfo(*secondMismatch)
848-
->originalSourceRange.getEnd();
848+
->originalSourceRange.getStart();
849849
return sourceMgr.isBeforeInBuffer(firstLocInLCA, secondLocInLCA) ||
850850
(allowEqual && firstLocInLCA == secondLocInLCA);
851851
}

lib/Sema/TypeCheckMacros.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,12 @@ static CharSourceRange getExpansionInsertionRange(MacroRole role,
984984
closure->getEndLoc()));
985985
}
986986

987+
// If the function has a body, that's what's being replaced.
988+
auto *AFD = cast<AbstractFunctionDecl>(target.get<Decl *>());
989+
if (auto range = AFD->getBodySourceRange())
990+
return Lexer::getCharSourceRangeFromSourceRange(sourceMgr, range);
991+
992+
// Otherwise we have no body, just use the end of the decl.
987993
SourceLoc afterDeclLoc =
988994
Lexer::getLocForEndOfToken(sourceMgr, target.getEndLoc());
989995
return CharSourceRange(afterDeclLoc, 0);

0 commit comments

Comments
 (0)