Skip to content

[indexer] Fix crash in initVarRefIndexSymbols by handling references from 'import var ...' #7072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/AST/SourceEntityWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ bool SemaAnnotator::handleImports(ImportDecl *Import) {
auto Decls = Import->getDecls();
if (Decls.size() == 1) {
// FIXME: ImportDecl should store a DeclNameLoc.
// FIXME: Handle overloaded funcs too by passing a reference for each?
if (!passReference(Decls.front(), Type(), DeclNameLoc(Import->getEndLoc()),
SemaReferenceKind::DeclRef))
return false;
Expand Down
34 changes: 22 additions & 12 deletions lib/Index/Index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
bool initIndexSymbol(ValueDecl *D, SourceLoc Loc, bool IsRef,
IndexSymbol &Info);
bool initFuncDeclIndexSymbol(ValueDecl *D, IndexSymbol &Info);
bool initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE, ValueDecl *D,
bool initFuncRefIndexSymbol(Expr *CurrentE, Expr *ParentE, ValueDecl *D,
SourceLoc Loc, IndexSymbol &Info);
bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
IndexSymbol &Info);
Expand Down Expand Up @@ -662,15 +662,15 @@ bool IndexSwiftASTWalker::reportPseudoAccessor(AbstractStorageDecl *D,
if (IsRef) {
IndexSymbol Info;

// initCallRefIndexSymbol uses the top of the entities stack as the caller,
// initFuncRefIndexSymbol uses the top of the entities stack as the caller,
// but in this case the top of the stack is the referenced
// AbstractStorageDecl.
assert(getParentDecl() == D);
auto PreviousTop = EntitiesStack.pop_back_val();
bool initCallFailed = initCallRefIndexSymbol(ExprStack.back(), getParentExpr(), D, Loc, Info);
bool initFailed = initFuncRefIndexSymbol(getCurrentExpr(), getParentExpr(), D, Loc, Info);
EntitiesStack.push_back(PreviousTop);

if (initCallFailed)
if (initFailed)
return true; // continue walking.
if (updateInfo(Info))
return true;
Expand Down Expand Up @@ -793,7 +793,7 @@ bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
return true; // keep walking

if (isa<AbstractFunctionDecl>(D)) {
if (initCallRefIndexSymbol(getCurrentExpr(), getParentExpr(), D, Loc, Info))
if (initFuncRefIndexSymbol(getCurrentExpr(), getParentExpr(), D, Loc, Info))
return true;
} else if (isa<AbstractStorageDecl>(D)) {
if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info))
Expand All @@ -809,11 +809,10 @@ bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
}

// Report the accessors that were utilized.
if (isa<AbstractStorageDecl>(D)) {
if (AbstractStorageDecl *ASD = dyn_cast<AbstractStorageDecl>(D)) {
bool UsesGetter = Info.roles & (SymbolRoleSet)SymbolRole::Read;
bool UsesSetter = Info.roles & (SymbolRoleSet)SymbolRole::Write;

AbstractStorageDecl *ASD = cast<AbstractStorageDecl>(D);
if (UsesGetter)
if (!reportPseudoAccessor(ASD, AccessorKind::IsGetter, /*IsRef=*/true,
Loc))
Expand Down Expand Up @@ -947,15 +946,23 @@ static bool isDynamicCall(Expr *BaseE, ValueDecl *D) {
return true;
}

bool IndexSwiftASTWalker::initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE,
bool IndexSwiftASTWalker::initFuncRefIndexSymbol(Expr *CurrentE, Expr *ParentE,
ValueDecl *D, SourceLoc Loc,
IndexSymbol &Info) {
if (!ParentE)
return true;

if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
return true;

if (!CurrentE)
return false;

// FIXME: the below check maintains existing indexing behaviour with
// pseudo/accessor output but seems incorrect. E.g otherGlobal in:
// let global = otherGlobal
// will not have a parent expression so no accessor call is reported
if (!ParentE)
return true;

Info.roles |= (unsigned)SymbolRole::Call;

Decl *ParentD = getParentDecl();
Expand Down Expand Up @@ -995,10 +1002,13 @@ bool IndexSwiftASTWalker::initCallRefIndexSymbol(Expr *CurrentE, Expr *ParentE,

bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc, IndexSymbol &Info) {

if (!(CurrentE->getReferencedDecl() == D))
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
return true;

if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
if (!CurrentE)
return false;

if (!(CurrentE->getReferencedDecl() == D))
return true;

AccessKind Kind = CurrentE->hasLValueAccessKind() ? CurrentE->getLValueAccessKind() : AccessKind::Read;
Expand Down
2 changes: 2 additions & 0 deletions test/Index/Inputs/imported_swift_module.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
public func importedFunc() {}
public var importedGlobal: Int = 0
11 changes: 10 additions & 1 deletion test/Index/roles.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
// RUN: rm -rf %t
// RUN: mkdir -p %t
//
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/imported_swift_module.swift
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s -I %t | %FileCheck %s

import func imported_swift_module.importedFunc
// CHECK: [[@LINE-1]]:35 | function/Swift | importedFunc() | s:F21imported_swift_module12importedFuncFT_T_ | Ref | rel: 0
import var imported_swift_module.importedGlobal
// CHECK: [[@LINE-1]]:34 | variable/Swift | importedGlobal | s:v21imported_swift_module14importedGlobalSi | Ref | rel: 0

// Definition
let x = 2
Expand Down
7 changes: 7 additions & 0 deletions test/SourceKit/Indexing/index_func_import.swift.response
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
}
],
key.entities: [
{
key.kind: source.lang.swift.ref.function.free,
key.name: "globalFunc()",
key.usr: "s:F11test_module10globalFuncFT_T_",
key.line: 8,
key.column: 25
},
{
key.kind: source.lang.swift.decl.function.free,
key.name: "test()",
Expand Down