Skip to content

Commit f752844

Browse files
authored
[index] Make sure to walk the accessor bodies of local properties (#19102)
[index] Make sure to walk the accessor bodies of local properties Otherwise we'll miss global symbols references. rdar://42301005
1 parent fb8adb0 commit f752844

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

lib/Index/Index.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
151151
};
152152
SmallVector<Entity, 6> EntitiesStack;
153153
SmallVector<Expr *, 8> ExprStack;
154+
SmallVector<const AccessorDecl *, 4> ManuallyVisitedAccessorStack;
154155
bool Cancelled = false;
155156

156157
struct NameAndUSR {
@@ -253,7 +254,10 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
253254
: IdxConsumer(IdxConsumer), SrcMgr(Ctx.SourceMgr), BufferID(BufferID),
254255
enableWarnings(IdxConsumer.enableWarnings()) {}
255256

256-
~IndexSwiftASTWalker() override { assert(Cancelled || EntitiesStack.empty()); }
257+
~IndexSwiftASTWalker() override {
258+
assert(Cancelled || EntitiesStack.empty());
259+
assert(Cancelled || ManuallyVisitedAccessorStack.empty());
260+
}
257261

258262
void visitModule(ModuleDecl &Mod, StringRef Hash);
259263
void visitDeclContext(DeclContext *DC);
@@ -270,8 +274,8 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
270274
if (AvailableAttr::isUnavailable(D))
271275
return false;
272276
if (auto *AD = dyn_cast<AccessorDecl>(D)) {
273-
auto *Parent = getParentDecl();
274-
if (Parent && Parent != AD->getStorage())
277+
if (ManuallyVisitedAccessorStack.empty() ||
278+
ManuallyVisitedAccessorStack.back() != AD)
275279
return false; // already handled as part of the var decl.
276280
}
277281
if (auto *VD = dyn_cast<ValueDecl>(D)) {
@@ -511,7 +515,12 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
511515
void IndexSwiftASTWalker::visitDeclContext(DeclContext *Context) {
512516
IsModuleFile = false;
513517
isSystemModule = Context->getParentModule()->isSystemModule();
518+
auto accessor = dyn_cast<AccessorDecl>(Context);
519+
if (accessor)
520+
ManuallyVisitedAccessorStack.push_back(accessor);
514521
walk(Context);
522+
if (accessor)
523+
ManuallyVisitedAccessorStack.pop_back();
515524
}
516525

517526
void IndexSwiftASTWalker::visitModule(ModuleDecl &Mod, StringRef KnownHash) {
@@ -957,14 +966,30 @@ bool IndexSwiftASTWalker::report(ValueDecl *D) {
957966
accessor->getAccessorKind() == AccessorKind::Set))
958967
continue;
959968

969+
ManuallyVisitedAccessorStack.push_back(accessor);
960970
SourceEntityWalker::walk(cast<Decl>(accessor));
971+
ManuallyVisitedAccessorStack.pop_back();
961972
if (Cancelled)
962973
return false;
963974
}
964975
} else if (auto NTD = dyn_cast<NominalTypeDecl>(D)) {
965976
if (!reportInheritedTypeRefs(NTD->getInherited(), NTD))
966977
return false;
967978
}
979+
} else {
980+
// Even if we don't record a local property we still need to walk its
981+
// accessor bodies.
982+
if (auto StoreD = dyn_cast<AbstractStorageDecl>(D)) {
983+
for (auto accessor : StoreD->getAllAccessors()) {
984+
if (accessor->isImplicit())
985+
continue;
986+
ManuallyVisitedAccessorStack.push_back(accessor);
987+
SourceEntityWalker::walk(cast<Decl>(accessor));
988+
ManuallyVisitedAccessorStack.pop_back();
989+
if (Cancelled)
990+
return false;
991+
}
992+
}
968993
}
969994

970995
return !Cancelled;

test/Index/expressions.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,33 @@ func test(_ o: P1?) {
1515
test(o)
1616
}
1717
}
18+
19+
func foo() {} // CHECK: [[@LINE]]:6 | function/Swift | foo() | [[foo_USR:.*]] | Def
20+
21+
func test1() { // CHECK: [[@LINE]]:6 | function/Swift | test1() | [[test1_USR:.*]] | Def
22+
func local_func() {
23+
// FIXME: Saying that 'test1' is the caller of 'foo' is inaccurate, but we'd need
24+
// to switch to recording local symbols in order to model this properly.
25+
foo() // CHECK: [[@LINE]]:5 | function/Swift | foo() | [[foo_USR]] | Ref,Call,RelCall,RelCont | rel: 1
26+
// CHECK-NEXT: RelCall,RelCont | function/Swift | test1() | [[test1_USR]]
27+
}
28+
29+
var local_prop: Int {
30+
get {
31+
foo() // CHECK: [[@LINE]]:7 | function/Swift | foo() | [[foo_USR]] | Ref,Call,RelCall,RelCont | rel: 1
32+
// CHECK-NEXT: RelCall,RelCont | function/Swift | test1() | [[test1_USR]]
33+
return 0
34+
}
35+
set {
36+
foo() // CHECK: [[@LINE]]:7 | function/Swift | foo() | [[foo_USR]] | Ref,Call,RelCall,RelCont | rel: 1
37+
// CHECK-NEXT: RelCall,RelCont | function/Swift | test1() | [[test1_USR]]
38+
}
39+
}
40+
41+
struct LocalS {
42+
func meth() {
43+
foo() // CHECK: [[@LINE]]:7 | function/Swift | foo() | [[foo_USR]] | Ref,Call,RelCall,RelCont | rel: 1
44+
// CHECK-NEXT: RelCall,RelCont | function/Swift | test1() | [[test1_USR]]
45+
}
46+
}
47+
}

test/Index/kinds.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,11 @@ _ = ImplCtors()
247247
// CHECK: [[@LINE-1]]:5 | constructor/Swift | init() | [[ImplCtors_init_USR]] | Ref,Call | rel: 0
248248
_ = ImplCtors(x:0)
249249
// CHECK: [[@LINE-1]]:5 | constructor/Swift | init(x:) | [[ImplCtors_init_with_param_USR]] | Ref,Call | rel: 0
250+
251+
var globalCompProp: Int // CHECK: [[@LINE]]:5 | variable/Swift | [[globalCompProp:.*]] | Def
252+
{ // CHECK: [[@LINE]]:1 | function/acc-get/Swift | getter:globalCompProp |
253+
// CHECK-NEXT: RelChild,RelAcc | variable/Swift | [[globalCompProp]]
254+
// Check that the accessor def is not showing up twice.
255+
// CHECK-NOT: [[@LINE-3]]:1 | function/acc-get/Swift
256+
return 0
257+
}

0 commit comments

Comments
 (0)