@@ -47,7 +47,26 @@ void ASTScopeImpl::unqualifiedLookup(
4747
4848const ASTScopeImpl *ASTScopeImpl::findStartingScopeForLookup (
4949 SourceFile *sourceFile, const SourceLoc loc) {
50- auto *const fileScope = sourceFile->getScope ().impl ;
50+ auto *fileScope = sourceFile->getScope ().impl ;
51+
52+ // Workaround for bad locations; just return the file scope.
53+ if (loc.isInvalid ())
54+ return fileScope;
55+
56+ // Some callers get the actual source file wrong. Look for the actual
57+ // source file containing this location.
58+ auto actualSF =
59+ sourceFile->getParentModule ()->getSourceFileContainingLocation (loc);
60+
61+ // If there is no source file containing this location, just return the
62+ // scope we have.
63+ if (!actualSF)
64+ return fileScope;
65+
66+ // Grab the new file scope.
67+ if (actualSF != sourceFile)
68+ fileScope = actualSF->getScope ().impl ;
69+
5170 const auto *innermost = fileScope->findInnermostEnclosingScope (
5271 sourceFile->getParentModule (), loc, nullptr );
5372 ASTScopeAssert (innermost->getWasExpanded (),
@@ -79,11 +98,11 @@ ASTScopeImpl *ASTScopeImpl::findInnermostEnclosingScopeImpl(
7998// / If the \p loc is in a new buffer but \p range is not, consider the location
8099// / is at the start of replaced range. Otherwise, returns \p loc as is.
81100static SourceLoc translateLocForReplacedRange (SourceManager &sourceMgr,
82- CharSourceRange range ,
101+ SourceLoc rangeStart ,
83102 SourceLoc loc) {
84103 for (const auto &pair : sourceMgr.getReplacedRanges ()) {
85104 if (sourceMgr.rangeContainsTokenLoc (pair.second , loc) &&
86- !sourceMgr.rangeContainsTokenLoc (pair.second , range. getStart () )) {
105+ !sourceMgr.rangeContainsTokenLoc (pair.second , rangeStart )) {
87106 return pair.first .Start ;
88107 }
89108 }
@@ -94,89 +113,23 @@ NullablePtr<ASTScopeImpl>
94113ASTScopeImpl::findChildContaining (ModuleDecl *parentModule,
95114 SourceLoc loc,
96115 SourceManager &sourceMgr) const {
97- auto *locSourceFile = parentModule->getSourceFileContainingLocation (loc);
116+ if (loc.isInvalid ())
117+ return nullptr ;
98118
99119 // Use binary search to find the child that contains this location.
100120 auto *const *child = llvm::lower_bound (
101121 getChildren (), loc,
102122 [&](const ASTScopeImpl *scope, SourceLoc loc) {
103123 auto rangeOfScope = scope->getCharSourceRangeOfScope (sourceMgr);
104- ASTScopeAssert (!sourceMgr.isBeforeInBuffer (rangeOfScope.getEnd (),
105- rangeOfScope.getStart ()),
106- " Source range is backwards" );
107-
108- // If the scope source range and the loc are in two different source
109- // files, one or both of them are in a macro expansion buffer.
110-
111- // Note that `scope->getSourceFile()` returns the root of the source tree,
112- // not the source file containing the location of the ASTScope.
113- auto scopeStart = scope->getSourceRangeOfThisASTNode ().Start ;
114- auto *scopeSourceFile = parentModule->getSourceFileContainingLocation (scopeStart);
115-
116- if (scopeSourceFile != locSourceFile) {
117- // To compare a source location that is possibly inside a macro expansion
118- // with a source range that is also possibly in a macro expansion (not
119- // necessarily the same one as before) we need to find the LCA in the
120- // source file tree of macro expansions, and compare the original source
121- // ranges within that common ancestor. We can't walk all the way up to the
122- // source file containing the parent scope we're searching the children of,
123- // because two independent (possibly nested) macro expansions can have the
124- // same original source range in that file; freestanding and peer macros
125- // mean that we can have arbitrarily nested macro expansions that all add
126- // declarations to the same scope, that all originate from a single macro
127- // invocation in the original source file.
128-
129- // A map from enclosing source files to original source ranges of the macro
130- // expansions within that file, recording the chain of macro expansions for
131- // the given scope.
132- llvm::SmallDenseMap<const SourceFile *, CharSourceRange>
133- scopeExpansions;
134-
135- // Walk up the chain of macro expansion buffers for the scope, recording the
136- // original source range of the macro expansion along the way using generated
137- // source info.
138- auto *scopeExpansion = scopeSourceFile;
139- scopeExpansions[scopeExpansion] =
140- Lexer::getCharSourceRangeFromSourceRange (
141- sourceMgr, scope->getSourceRangeOfThisASTNode ());
142- while (auto *ancestor = scopeExpansion->getEnclosingSourceFile ()) {
143- auto generatedInfo =
144- sourceMgr.getGeneratedSourceInfo (*scopeExpansion->getBufferID ());
145- scopeExpansions[ancestor] = generatedInfo->originalSourceRange ;
146- scopeExpansion = ancestor;
147- }
148-
149- // Walk up the chain of macro expansion buffers for the source loc we're
150- // searching for to find the LCA using `scopeExpansions`.
151- auto *potentialLCA = locSourceFile;
152- auto expansionLoc = loc;
153- while (potentialLCA) {
154- auto scopeExpansion = scopeExpansions.find (potentialLCA);
155- if (scopeExpansion != scopeExpansions.end ()) {
156- // Take the original expansion range within the LCA of the loc and
157- // the scope to compare.
158- rangeOfScope = scopeExpansion->second ;
159- loc = expansionLoc;
160- break ;
161- }
162-
163- auto generatedInfo =
164- sourceMgr.getGeneratedSourceInfo (*potentialLCA->getBufferID ());
165- if (generatedInfo)
166- expansionLoc = generatedInfo->originalSourceRange .getStart ();
167- potentialLCA = potentialLCA->getEnclosingSourceFile ();
168- }
169- }
170-
171- loc = translateLocForReplacedRange (sourceMgr, rangeOfScope, loc);
172- return (rangeOfScope.getEnd () == loc ||
173- sourceMgr.isBeforeInBuffer (rangeOfScope.getEnd (), loc));
124+ loc = translateLocForReplacedRange (sourceMgr, rangeOfScope.Start , loc);
125+ return sourceMgr.isAtOrBefore (rangeOfScope.End , loc);
174126 });
175127
176128 if (child != getChildren ().end ()) {
177129 auto rangeOfScope = (*child)->getCharSourceRangeOfScope (sourceMgr);
178- loc = translateLocForReplacedRange (sourceMgr, rangeOfScope, loc);
179- if (rangeOfScope.contains (loc))
130+ loc = translateLocForReplacedRange (sourceMgr, rangeOfScope.Start , loc);
131+ if (sourceMgr.isAtOrBefore (rangeOfScope.Start , loc) &&
132+ sourceMgr.isBefore (loc, rangeOfScope.End ))
180133 return *child;
181134 }
182135
0 commit comments