Skip to content

Commit d6f8d8c

Browse files
committed
[IDE] Avoid macro expansions in getEquivalentDeclContextFromSourceFile
Unfortunately haven't been able to come up with a test case for this, but there seem to be cases where we're incorrectly picking up a macro-expanded accessor from the cached AST when searching for the original decl. Make sure we only consider decls that have been written by the user. rdar://151926231
1 parent 4ae4d77 commit d6f8d8c

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

lib/IDETool/IDEInspectionInstance.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,23 @@ template <typename Range> Decl *getElementAt(const Range &Decls, unsigned N) {
9090
return nullptr;
9191
}
9292

93+
static ArrayRef<AccessorDecl *>
94+
getParsedAccessors(AbstractStorageDecl *ASD,
95+
SmallVectorImpl<AccessorDecl *> &scratch) {
96+
ASSERT(scratch.empty());
97+
ASD->visitParsedAccessors([&](auto *AD) {
98+
// Ignore accessors added by macro expansions.
99+
// TODO: This ought to be the default behavior of `visitParsedAccessors`,
100+
// we ought to have a different entrypoint for clients that care about
101+
// the semantic set of "explicit" accessors.
102+
if (AD->isInMacroExpansionInContext())
103+
return;
104+
105+
scratch.push_back(AD);
106+
});
107+
return scratch;
108+
}
109+
93110
/// Find the equivalent \c DeclContext with \p DC from \p SF AST.
94111
/// This assumes the AST which contains \p DC has exact the same structure with
95112
/// \p SF.
@@ -117,7 +134,10 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
117134
auto *storage = accessor->getStorage();
118135
if (!storage)
119136
return nullptr;
120-
auto accessorN = findIndexInRange(accessor, storage->getAllAccessors());
137+
138+
SmallVector<AccessorDecl *, 4> scratch;
139+
auto accessorN =
140+
findIndexInRange(accessor, getParsedAccessors(storage, scratch));
121141
if (!accessorN)
122142
return nullptr;
123143
IndexStack.push_back(*accessorN);
@@ -128,7 +148,7 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
128148
N = findIndexInRange(D, parentSF->getTopLevelDecls());
129149
} else if (auto parentIDC = dyn_cast_or_null<IterableDeclContext>(
130150
parentDC->getAsDecl())) {
131-
N = findIndexInRange(D, parentIDC->getMembers());
151+
N = findIndexInRange(D, parentIDC->getParsedMembers());
132152
} else {
133153
#ifndef NDEBUG
134154
llvm_unreachable("invalid DC kind for finding equivalent DC (indexpath)");
@@ -155,15 +175,16 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
155175
if (auto parentSF = dyn_cast<SourceFile>(newDC))
156176
D = getElementAt(parentSF->getTopLevelDecls(), N);
157177
else if (auto parentIDC = dyn_cast<IterableDeclContext>(newDC->getAsDecl()))
158-
D = getElementAt(parentIDC->getMembers(), N);
178+
D = getElementAt(parentIDC->getParsedMembers(), N);
159179
else
160180
llvm_unreachable("invalid DC kind for finding equivalent DC (query)");
161181

162182
if (auto storage = dyn_cast_or_null<AbstractStorageDecl>(D)) {
163183
if (IndexStack.empty())
164184
return nullptr;
165185
auto accessorN = IndexStack.pop_back_val();
166-
D = getElementAt(storage->getAllAccessors(), accessorN);
186+
SmallVector<AccessorDecl *, 4> scratch;
187+
D = getElementAt(getParsedAccessors(storage, scratch), accessorN);
167188
}
168189

169190
newDC = dyn_cast_or_null<DeclContext>(D);
@@ -358,7 +379,7 @@ bool IDEInspectionInstance::performCachedOperationIfPossible(
358379
nullptr
359380
}
360381
);
361-
SM.recordSourceFile(newBufferID, AFD->getParentSourceFile());
382+
SM.recordSourceFile(newBufferID, oldSF);
362383

363384
AFD->setBodyToBeReparsed(newBodyRange);
364385
oldSF->clearScope();

0 commit comments

Comments
 (0)