Skip to content

Commit 7a29897

Browse files
committed
[NFC] Serialize ObjC selectors for protocols
The ObjCMethodLookupTable for protocols was not being serialized and rebuilt on load, so NominalTypeDecl::lookupDirect() on selectors was not working correctly for deserialized types. Correct this oversight.
1 parent 5af0a36 commit 7a29897

File tree

12 files changed

+40
-30
lines changed

12 files changed

+40
-30
lines changed

include/swift/AST/ModuleLoader.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,11 @@ class ModuleLoader {
226226
virtual void loadExtensions(NominalTypeDecl *nominal,
227227
unsigned previousGeneration) { }
228228

229-
/// Load the methods within the given class that produce
229+
/// Load the methods within the given type that produce
230230
/// Objective-C class or instance methods with the given selector.
231231
///
232-
/// \param classDecl The class in which we are searching for @objc methods.
233-
/// The search only considers this class and its extensions; not any
232+
/// \param typeDecl The type in which we are searching for @objc methods.
233+
/// The search only considers this type and its extensions; not any
234234
/// superclasses.
235235
///
236236
/// \param selector The selector to search for.
@@ -246,7 +246,7 @@ class ModuleLoader {
246246
/// selector and are instance/class methods as requested. This list will be
247247
/// extended with any methods found in subsequent generations.
248248
virtual void loadObjCMethods(
249-
ClassDecl *classDecl,
249+
NominalTypeDecl *typeDecl,
250250
ObjCSelector selector,
251251
bool isInstanceMethod,
252252
unsigned previousGeneration,

include/swift/ClangImporter/ClangImporter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class ClangImporter final : public ClangModuleLoader {
309309
unsigned previousGeneration) override;
310310

311311
virtual void loadObjCMethods(
312-
ClassDecl *classDecl,
312+
NominalTypeDecl *typeDecl,
313313
ObjCSelector selector,
314314
bool isInstanceMethod,
315315
unsigned previousGeneration,

include/swift/Sema/SourceLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class SourceLoader : public ModuleLoader {
8585
unsigned previousGeneration) override;
8686

8787
virtual void loadObjCMethods(
88-
ClassDecl *classDecl,
88+
NominalTypeDecl *typeDecl,
8989
ObjCSelector selector,
9090
bool isInstanceMethod,
9191
unsigned previousGeneration,

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
190190
unsigned previousGeneration) override;
191191

192192
virtual void loadObjCMethods(
193-
ClassDecl *classDecl,
193+
NominalTypeDecl *typeDecl,
194194
ObjCSelector selector,
195195
bool isInstanceMethod,
196196
unsigned previousGeneration,

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,24 +1913,12 @@ void ASTContext::loadObjCMethods(
19131913
PrettyStackTraceSelector stackTraceSelector("looking for", selector);
19141914
PrettyStackTraceDecl stackTraceDecl("...in", tyDecl);
19151915

1916-
// @objc protocols cannot have @objc extension members, so if we've recorded
1917-
// everything in the protocol definition, we've recorded everything. And we
1918-
// only ever use the ObjCSelector version of `NominalTypeDecl::lookupDirect()`
1919-
// on protocols in primary file typechecking, so we don't care about protocols
1920-
// that need to be loaded from files.
1921-
// TODO: Rework `ModuleLoader::loadObjCMethods()` to support protocols too if
1922-
// selector-based `NominalTypeDecl::lookupDirect()` ever needs to work
1923-
// in more situations.
1924-
ClassDecl *classDecl = dyn_cast<ClassDecl>(tyDecl);
1925-
if (!classDecl)
1926-
return;
1927-
19281916
for (auto &loader : getImpl().ModuleLoaders) {
19291917
// Ignore the Clang importer if we've been asked for Swift-only results.
19301918
if (swiftOnly && loader.get() == getClangModuleLoader())
19311919
continue;
19321920

1933-
loader->loadObjCMethods(classDecl, selector, isInstanceMethod,
1921+
loader->loadObjCMethods(tyDecl, selector, isInstanceMethod,
19341922
previousGeneration, methods);
19351923
}
19361924
}

lib/AST/NameLookup.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,24 @@ class swift::ObjCMethodLookupTable
13101310
: public llvm::DenseMap<std::pair<ObjCSelector, char>,
13111311
StoredObjCMethods>,
13121312
public ASTAllocated<ObjCMethodLookupTable>
1313-
{};
1313+
{
1314+
SWIFT_DEBUG_DUMP {
1315+
llvm::errs() << "ObjCMethodLookupTable:\n";
1316+
for (auto pair : *this) {
1317+
auto selector = pair.getFirst().first;
1318+
auto isInstanceMethod = pair.getFirst().second;
1319+
auto &methods = pair.getSecond();
1320+
1321+
llvm::errs() << " \"" << (isInstanceMethod ? "-" : "+") << selector
1322+
<< "\":\n";
1323+
for (auto method : methods.Methods) {
1324+
llvm::errs() << " - \"";
1325+
method->dumpRef(llvm::errs());
1326+
llvm::errs() << "\"\n";
1327+
}
1328+
}
1329+
}
1330+
};
13141331

13151332
MemberLookupTable::MemberLookupTable(ASTContext &ctx) {
13161333
// Register a cleanup with the ASTContext to call the lookup table

lib/ClangImporter/ClangImporter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3562,11 +3562,16 @@ void ClangImporter::loadExtensions(NominalTypeDecl *nominal,
35623562
}
35633563

35643564
void ClangImporter::loadObjCMethods(
3565-
ClassDecl *classDecl,
3565+
NominalTypeDecl *typeDecl,
35663566
ObjCSelector selector,
35673567
bool isInstanceMethod,
35683568
unsigned previousGeneration,
35693569
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods) {
3570+
// TODO: We don't currently need to load methods from imported ObjC protocols.
3571+
auto classDecl = dyn_cast<ClassDecl>(typeDecl);
3572+
if (!classDecl)
3573+
return;
3574+
35703575
const auto *objcClass =
35713576
dyn_cast_or_null<clang::ObjCInterfaceDecl>(classDecl->getClangDecl());
35723577
if (!objcClass)

lib/Serialization/ModuleFile.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ void ModuleFile::loadExtensions(NominalTypeDecl *nominal) {
613613
}
614614

615615
void ModuleFile::loadObjCMethods(
616-
ClassDecl *classDecl,
616+
NominalTypeDecl *typeDecl,
617617
ObjCSelector selector,
618618
bool isInstanceMethod,
619619
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods) {
@@ -627,7 +627,7 @@ void ModuleFile::loadObjCMethods(
627627
return;
628628
}
629629

630-
std::string ownerName = Mangle::ASTMangler().mangleNominalType(classDecl);
630+
std::string ownerName = Mangle::ASTMangler().mangleNominalType(typeDecl);
631631
auto results = *known;
632632
for (const auto &result : results) {
633633
// If the method is the wrong kind (instance vs. class), skip it.

lib/Serialization/ModuleFile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ class ModuleFile
634634
///
635635
/// \param methods The list of @objc methods in this class that have this
636636
/// selector and are instance/class methods as requested.
637-
void loadObjCMethods(ClassDecl *classDecl,
637+
void loadObjCMethods(NominalTypeDecl *typeDecl,
638638
ObjCSelector selector,
639639
bool isInstanceMethod,
640640
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods);

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 691; // bump to avoid conflict
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 692; // add @objc protocol methods to objc method tables
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5533,10 +5533,10 @@ static void collectInterestingNestedDeclarations(
55335533
if (isLocal)
55345534
return;
55355535

5536-
if (auto owningClass = func->getDeclContext()->getSelfClassDecl()) {
5536+
if (auto owningType = func->getDeclContext()->getSelfNominalTypeDecl()) {
55375537
if (func->isObjC()) {
55385538
Mangle::ASTMangler mangler;
5539-
std::string ownerName = mangler.mangleNominalType(owningClass);
5539+
std::string ownerName = mangler.mangleNominalType(owningType);
55405540
assert(!ownerName.empty() && "Mangled type came back empty!");
55415541

55425542
objcMethods[func->getObjCSelector()].push_back(

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,15 +1320,15 @@ void SerializedModuleLoaderBase::loadExtensions(NominalTypeDecl *nominal,
13201320
}
13211321

13221322
void SerializedModuleLoaderBase::loadObjCMethods(
1323-
ClassDecl *classDecl,
1323+
NominalTypeDecl *typeDecl,
13241324
ObjCSelector selector,
13251325
bool isInstanceMethod,
13261326
unsigned previousGeneration,
13271327
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods) {
13281328
for (auto &modulePair : LoadedModuleFiles) {
13291329
if (modulePair.second <= previousGeneration)
13301330
continue;
1331-
modulePair.first->loadObjCMethods(classDecl, selector, isInstanceMethod,
1331+
modulePair.first->loadObjCMethods(typeDecl, selector, isInstanceMethod,
13321332
methods);
13331333
}
13341334
}

0 commit comments

Comments
 (0)