Skip to content

Commit 7786ac8

Browse files
committed
Sema: Move forcing of certain requests from finalizeDecl() to typeCheckDecl()
finalizeDecl() would kick off certain requests. This was necessary before we had the long-lived type checker to ensure that requests that required a type checker could be completed in time for SILGen. It was also necessary to always emit diagnostics for declarations in primary files. Since we now have a long lived type checker, the first reason is no longer valid, so we can move this work from finalizeDecl() to typeCheckDecl(), where it will run for declarations in primary files only. To ensure that @objc selector conflict diagnostics still get emitted, we also walk the superclass chain and force isObjC() to be computed for each declaration in each superclass.
1 parent 88aa93b commit 7786ac8

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

lib/AST/Decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,8 @@ bool ValueDecl::canInferObjCFromRequirement(ValueDecl *requirement) {
27012701
// If there is already an @objc attribute with an explicit name, we
27022702
// can't infer a name (it's already there).
27032703
if (auto objcAttr = getAttrs().getAttribute<ObjCAttr>()) {
2704-
if (!objcAttr->isNameImplicit()) return false;
2704+
if (objcAttr->hasName() && !objcAttr->isNameImplicit())
2705+
return false;
27052706
}
27062707

27072708
// If the nominal type doesn't conform to the protocol at all, we

lib/Sema/TypeCheckDecl.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,18 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
22552255
if (auto VD = dyn_cast<ValueDecl>(decl)) {
22562256
checkRedeclaration(TC, VD);
22572257

2258+
// Force some requests, which can produce diagnostics.
2259+
2260+
// Compute access level.
2261+
(void) VD->getFormalAccess();
2262+
2263+
// Compute overrides.
2264+
(void) VD->getOverriddenDecls();
2265+
2266+
// Check whether the member is @objc or dynamic.
2267+
(void) VD->isObjC();
2268+
(void) VD->isDynamic();
2269+
22582270
// Make sure we finalize this declaration.
22592271
TC.DeclsToFinalize.insert(VD);
22602272

@@ -2974,6 +2986,24 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
29742986
TC.addImplicitConstructors(CD);
29752987
CD->addImplicitDestructor();
29762988

2989+
// Compute @objc for each superclass member, to catch selector
2990+
// conflicts resulting from unintended overrides.
2991+
//
2992+
// FIXME: This should be a request so we can measure how much work
2993+
// we're doing here.
2994+
CD->walkSuperclasses(
2995+
[&](ClassDecl *superclass) {
2996+
for (auto *member : superclass->getMembers()) {
2997+
if (auto *vd = dyn_cast<ValueDecl>(member)) {
2998+
if (vd->isPotentiallyOverridable()) {
2999+
(void) vd->isObjC();
3000+
}
3001+
}
3002+
}
3003+
3004+
return TypeWalker::Action::Continue;
3005+
});
3006+
29773007
if (auto superclassTy = CD->getSuperclass()) {
29783008
ClassDecl *Super = superclassTy->getClassOrBoundGenericClass();
29793009

@@ -4550,16 +4580,6 @@ void TypeChecker::finalizeDecl(ValueDecl *decl) {
45504580
} else if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
45514581
finalizeAbstractStorageDecl(*this, storage);
45524582
}
4553-
4554-
// Compute access level.
4555-
(void)decl->getFormalAccess();
4556-
4557-
// Compute overrides.
4558-
(void)decl->getOverriddenDecls();
4559-
4560-
// Check whether the member is @objc or dynamic.
4561-
(void)decl->isObjC();
4562-
(void)decl->isDynamic();
45634583
}
45644584

45654585
/// Determine whether this is a "pass-through" typealias, which has the

test/decl/protocol/conforms/near_miss_objc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class C1a : P1 {
1111
@objc func doSomething(a: Int, c: Double) { }
1212
// expected-warning@-1{{instance method 'doSomething(a:c:)' nearly matches optional requirement 'doSomething(a:b:)' of protocol 'P1'}}
13-
// expected-note@-2{{rename to 'doSomething(a:b:)' to satisfy this requirement}}{{34-34=b }}{{8-8=(doSomethingWithA:b:)}} {{34-34=b }}
13+
// expected-note@-2{{rename to 'doSomething(a:b:)' to satisfy this requirement}}{{34-34=b }}
1414
// expected-note@-3{{move 'doSomething(a:c:)' to an extension to silence this warning}}
1515
// expected-note@-4{{make 'doSomething(a:c:)' private to silence this warning}}{{9-9=private }}
1616
}

0 commit comments

Comments
 (0)