@@ -82,6 +82,15 @@ const ASTScopeImpl *ASTScopeImpl::findStartingScopeForLookup(
8282 // Someday, just use the assertion below. For now, print out lots of info for
8383 // debugging.
8484 if (!startingScope) {
85+
86+ // Be lenient in code completion mode. There are cases where the decl
87+ // context doesn't match with the ASTScope. e.g. dangling attributes.
88+ // FIXME: Create ASTScope tree even for invalid code.
89+ if (innermost &&
90+ startingContext->getASTContext ().SourceMgr .hasCodeCompletionBuffer ()) {
91+ return innermost;
92+ }
93+
8594 llvm::errs () << " ASTScopeImpl: resorting to startingScope hack, file: "
8695 << sourceFile->getFilename () << " \n " ;
8796 // The check is costly, and inactive lookups will end up here, so don't
@@ -143,6 +152,20 @@ bool ASTScopeImpl::checkSourceRangeOfThisASTNode() const {
143152 return true ;
144153}
145154
155+ // / If the \p loc is in a new buffer but \p range is not, consider the location
156+ // / is at the start of replaced range. Otherwise, returns \p loc as is.
157+ static SourceLoc translateLocForReplacedRange (SourceManager &sourceMgr,
158+ SourceRange range,
159+ SourceLoc loc) {
160+ if (const auto &replacedRange = sourceMgr.getReplacedRange ()) {
161+ if (sourceMgr.rangeContainsTokenLoc (replacedRange.New , loc) &&
162+ !sourceMgr.rangeContains (replacedRange.New , range)) {
163+ return replacedRange.Original .Start ;
164+ }
165+ }
166+ return loc;
167+ }
168+
146169NullablePtr<ASTScopeImpl>
147170ASTScopeImpl::findChildContaining (SourceLoc loc,
148171 SourceManager &sourceMgr) const {
@@ -152,24 +175,24 @@ ASTScopeImpl::findChildContaining(SourceLoc loc,
152175
153176 bool operator ()(const ASTScopeImpl *scope, SourceLoc loc) {
154177 ASTScopeAssert (scope->checkSourceRangeOfThisASTNode (), " Bad range." );
155- return -1 == ASTScopeImpl::compare (scope->getSourceRangeOfScope (), loc,
156- sourceMgr,
178+ auto rangeOfScope = scope->getSourceRangeOfScope ();
179+ loc = translateLocForReplacedRange (sourceMgr, rangeOfScope, loc);
180+ return -1 == ASTScopeImpl::compare (rangeOfScope, loc, sourceMgr,
157181 /* ensureDisjoint=*/ false );
158182 }
159183 bool operator ()(SourceLoc loc, const ASTScopeImpl *scope) {
160- ASTScopeAssert (scope->checkSourceRangeOfThisASTNode (), " Bad range." );
161- // Alternatively, we could check that loc < start-of-scope
162- return 0 >= ASTScopeImpl::compare (loc, scope->getSourceRangeOfScope (),
163- sourceMgr,
164- /* ensureDisjoint=*/ false );
184+ return !(*this )(scope, loc);
165185 }
166186 };
167187 auto *const *child = std::lower_bound (
168188 getChildren ().begin (), getChildren ().end (), loc, CompareLocs{sourceMgr});
169189
170- if (child != getChildren ().end () &&
171- sourceMgr.rangeContainsTokenLoc ((*child)->getSourceRangeOfScope (), loc))
172- return *child;
190+ if (child != getChildren ().end ()) {
191+ auto rangeOfScope = (*child)->getSourceRangeOfScope ();
192+ loc = translateLocForReplacedRange (sourceMgr, rangeOfScope, loc);
193+ if (sourceMgr.rangeContainsTokenLoc (rangeOfScope, loc))
194+ return *child;
195+ }
173196
174197 return nullptr ;
175198}
0 commit comments