Skip to content

Commit

Permalink
Merge pull request #1550 from kballard/use-declname-for-scope
Browse files Browse the repository at this point in the history
[Parse] Fix lookup of foo(_:bar:) expressions
  • Loading branch information
DougGregor committed Mar 14, 2016
2 parents 2293d28 + 59df509 commit d525309
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 14 deletions.
4 changes: 2 additions & 2 deletions include/swift/AST/DiagnosticsSema.def
Expand Up @@ -367,8 +367,8 @@ ERROR(expr_selector_module_missing,none,
"import the 'ObjectiveC' module to use '#selector'", ())
ERROR(expr_selector_no_declaration,none,
"argument of '#selector' does not refer to an initializer or method", ())
ERROR(expr_selector_property,none,
"argument of '#selector' cannot refer to a property", ())
ERROR(expr_selector_var,none,
"argument of '#selector' cannot refer to a %select{property|parameter|variable}0", (int))
ERROR(expr_selector_not_method_or_init,none,
"argument of '#selector' does not refer to a method or initializer", ())
ERROR(expr_selector_not_objc,none,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Parse/Parser.h
Expand Up @@ -541,7 +541,7 @@ class Parser {
getScopeInfo().addToScope(D, *this);
}

ValueDecl *lookupInScope(Identifier Name) {
ValueDecl *lookupInScope(DeclName Name) {
return getScopeInfo().lookupValueName(Name);
}

Expand Down
6 changes: 3 additions & 3 deletions include/swift/Parse/Scope.h
Expand Up @@ -35,7 +35,7 @@ class ScopeInfo {
public:
typedef std::pair<unsigned, ValueDecl*> ValueScopeEntry;

typedef TreeScopedHashTable<Identifier, ValueScopeEntry> ScopedHTTy;
typedef TreeScopedHashTable<DeclName, ValueScopeEntry> ScopedHTTy;
typedef ScopedHTTy::ScopeTy ScopedHTScopeTy;
typedef ScopedHTTy::DetachedScopeTy ScopedHTDetachedScopeTy;

Expand All @@ -46,7 +46,7 @@ class ScopeInfo {
unsigned ResolvableDepth = 0;

public:
ValueDecl *lookupValueName(Identifier Name);
ValueDecl *lookupValueName(DeclName Name);

Scope *getCurrentScope() const { return CurScope; }

Expand Down Expand Up @@ -158,7 +158,7 @@ class Scope {
}
};

inline ValueDecl *ScopeInfo::lookupValueName(Identifier Name) {
inline ValueDecl *ScopeInfo::lookupValueName(DeclName Name) {
// FIXME: this check can go away when SIL parser parses everything in
// a toplevel scope.
if (!CurScope)
Expand Down
2 changes: 1 addition & 1 deletion lib/Parse/ParseExpr.cpp
Expand Up @@ -1587,7 +1587,7 @@ Expr *Parser::parseExprIdentifier() {
hasGenericArgumentList = !args.empty();
}

ValueDecl *D = lookupInScope(name.getBaseName());
ValueDecl *D = lookupInScope(name);
// FIXME: We want this to work: "var x = { x() }", but for now it's better
// to disallow it than to crash.
if (D) {
Expand Down
4 changes: 2 additions & 2 deletions lib/Parse/Scope.cpp
Expand Up @@ -112,7 +112,7 @@ void ScopeInfo::addToScope(ValueDecl *D, Parser &TheParser) {

// If we have a shadowed variable definition, check to see if we have a
// redefinition: two definitions in the same scope with the same name.
ScopedHTTy::iterator EntryI = HT.begin(CurScope->HTScope, D->getName());
ScopedHTTy::iterator EntryI = HT.begin(CurScope->HTScope, D->getFullName());

// A redefinition is a hit in the scoped table at the same depth.
if (EntryI != HT.end() && EntryI->first == CurScope->getDepth()) {
Expand All @@ -135,6 +135,6 @@ void ScopeInfo::addToScope(ValueDecl *D, Parser &TheParser) {
}

HT.insertIntoScope(CurScope->HTScope,
D->getName(),
D->getFullName(),
std::make_pair(CurScope->getDepth(), D));
}
19 changes: 14 additions & 5 deletions lib/Sema/CSApply.cpp
Expand Up @@ -3344,11 +3344,20 @@ namespace {
// complain.
auto func = dyn_cast<AbstractFunctionDecl>(foundDecl);
if (!func) {
tc.diagnose(E->getLoc(),
isa<VarDecl>(foundDecl)
? diag::expr_selector_property
: diag::expr_selector_not_method_or_init)
.highlight(subExpr->getSourceRange());
Optional<InFlightDiagnostic> diag;
if (auto VD = dyn_cast<VarDecl>(foundDecl)) {
diag.emplace(tc.diagnose(E->getLoc(), diag::expr_selector_var,
isa<ParamDecl>(VD)
? 1
: VD->getDeclContext()->isTypeContext()
? 0
: 2));
} else {
diag.emplace(tc.diagnose(E->getLoc(),
diag::expr_selector_not_method_or_init));
}
diag->highlight(subExpr->getSourceRange());
diag.reset();
tc.diagnose(foundDecl, diag::decl_declared_here,
foundDecl->getFullName());
return E;
Expand Down
16 changes: 16 additions & 0 deletions test/expr/unary/selector/selector.swift
Expand Up @@ -18,6 +18,22 @@ class C1 {
@objc var a: A = A() // expected-note{{'a' declared here}}

@objc func getC1() -> AnyObject { return self }

@objc func testUnqualifiedSelector(a: A, b: B) {
_ = #selector(testUnqualifiedSelector(_:b:))
let testUnqualifiedSelector = 1
_ = #selector(testUnqualifiedSelector(_:b:))
_ = testUnqualifiedSelector // suppress unused warning
}

@objc func testParam(testParam: A) { // expected-note{{'testParam' declared here}}
_ = #selector(testParam) // expected-error{{argument of '#selector' cannot refer to a parameter}}
}

@objc func testVariable() {
let testVariable = 1 // expected-note{{'testVariable' declared here}}
_ = #selector(testVariable) // expected-error{{argument of '#selector' cannot refer to a variable}}
}
}

@objc protocol P1 {
Expand Down

0 comments on commit d525309

Please sign in to comment.