Skip to content

Commit cf97c88

Browse files
committed
[ClangImporter] Swift Implemented ObjC Forward Declarations
Objective-C libraries that wrap Swift types will often forward declare these types in public headers. Prior to this patch, if a Swift client consumed this Obejctive-C header, the forward declarations and dependent declarations will not be imported, despite the client importing the defining Swift module. The same is not true for Clang modules, which was confusing behavior. This patch allows the ClangImporter to check if a matching @objc Swift declarations is available from the importing Swift context when encountering an incomplete ObjC interface or protocol. If such a Swift declaration is found, it is simply returned.
1 parent 3d36113 commit cf97c88

24 files changed

+307
-10
lines changed

include/swift/AST/FileUnit.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
6767
virtual void lookupValue(DeclName name, NLKind lookupKind,
6868
SmallVectorImpl<ValueDecl*> &result) const = 0;
6969

70+
virtual void
71+
lookupSwiftValueByObjCName(DeclName name,
72+
SmallVectorImpl<ValueDecl *> &result) const = 0;
73+
7074
/// Look up a local type declaration by its mangled name.
7175
///
7276
/// This does a simple local lookup, not recursively looking through imports.
@@ -369,6 +373,9 @@ class BuiltinUnit final : public FileUnit {
369373
virtual void lookupValue(DeclName name, NLKind lookupKind,
370374
SmallVectorImpl<ValueDecl*> &result) const override;
371375

376+
virtual void lookupSwiftValueByObjCName(
377+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const override;
378+
372379
/// Find all Objective-C methods with the given selector.
373380
void lookupObjCMethods(
374381
ObjCSelector selector,

include/swift/AST/Identifier.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,8 @@ class ObjCSelector {
883883
return Storage.getBaseIdentifier();
884884
}
885885

886+
DeclName &getName() { return Storage; }
887+
886888
/// Get a string representation of the selector.
887889
///
888890
/// \param scratch Scratch space to use.

include/swift/AST/Module.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,17 @@ class ModuleDecl
640640
void lookupValue(DeclName Name, NLKind LookupKind,
641641
SmallVectorImpl<ValueDecl*> &Result) const;
642642

643+
/// Look up a value just as "ModuleDecl::lookupValue` does, but provide the
644+
/// Swift context from which the lookup is made.
645+
void lookupValueWithContext(DeclName Name, NLKind LookupKind,
646+
SmallVectorImpl<ValueDecl *> &Result,
647+
const DeclContext *Context) const;
648+
649+
/// Look up a top-level value by @objc provided name within the current
650+
/// module. Top levels values without an @objc attribute are ignored.
651+
void lookupSwiftValueByObjCName(DeclName Name,
652+
SmallVectorImpl<ValueDecl *> &Result) const;
653+
643654
/// Look up a local type declaration by its mangled name.
644655
///
645656
/// This does a simple local lookup, not recursively looking through imports.

include/swift/AST/SourceFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,9 @@ class SourceFile final : public FileUnit {
418418
virtual void lookupValue(DeclName name, NLKind lookupKind,
419419
SmallVectorImpl<ValueDecl*> &result) const override;
420420

421+
virtual void lookupSwiftValueByObjCName(
422+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const override;
423+
421424
virtual void lookupVisibleDecls(ImportPath::Access accessPath,
422425
VisibleDeclConsumer &consumer,
423426
NLKind lookupKind) const override;

include/swift/AST/SynthesizedFileUnit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class SynthesizedFileUnit final : public FileUnit {
4646
virtual void lookupValue(DeclName name, NLKind lookupKind,
4747
SmallVectorImpl<ValueDecl *> &result) const override;
4848

49+
virtual void lookupSwiftValueByObjCName(
50+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const override;
51+
4952
void lookupObjCMethods(
5053
ObjCSelector selector,
5154
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;

include/swift/ClangImporter/ClangModule.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ class ClangModuleUnit final : public LoadedFile {
6868
virtual void lookupValue(DeclName name, NLKind lookupKind,
6969
SmallVectorImpl<ValueDecl*> &results) const override;
7070

71+
void lookupValueWithContext(DeclName name, NLKind lookupKind,
72+
SmallVectorImpl<ValueDecl *> &results,
73+
const DeclContext *context) const;
74+
75+
virtual void lookupSwiftValueByObjCName(
76+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const override;
77+
7178
virtual TypeDecl *
7279
lookupNestedType(Identifier name,
7380
const NominalTypeDecl *baseType) const override;

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ class SerializedASTFile final : public LoadedFile {
355355
virtual void lookupValue(DeclName name, NLKind lookupKind,
356356
SmallVectorImpl<ValueDecl*> &results) const override;
357357

358+
virtual void lookupSwiftValueByObjCName(
359+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const override;
360+
358361
virtual StringRef
359362
getFilenameForPrivateDecl(const ValueDecl *decl) const override;
360363

lib/AST/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
set(SWIFTAST_LLVM_LINK_COMPONENTS
32
bitreader bitwriter coroutines coverage irreader debuginfoDWARF
43
profiledata instrumentation object objcarcopts mc mcparser

lib/AST/Module.cpp

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "swift/Basic/Compiler.h"
4444
#include "swift/Basic/SourceManager.h"
4545
#include "swift/Basic/Statistic.h"
46+
#include "swift/ClangImporter/ClangModule.h"
4647
#include "swift/Demangling/ManglingMacros.h"
4748
#include "swift/Parse/Token.h"
4849
#include "swift/Strings.h"
@@ -57,8 +58,8 @@
5758
#include "llvm/Support/MemoryBuffer.h"
5859
#include "llvm/Support/Path.h"
5960
#include "llvm/Support/SaveAndRestore.h"
60-
#include "llvm/Support/raw_ostream.h"
6161
#include "llvm/Support/YAMLTraits.h"
62+
#include "llvm/Support/raw_ostream.h"
6263

6364
using namespace swift;
6465

@@ -158,6 +159,7 @@ class swift::SourceLookupCache {
158159
};
159160

160161
ValueDeclMap TopLevelValues;
162+
ValueDeclMap TopLevelValuesByObjCName;
161163
ValueDeclMap ClassMembers;
162164
bool MemberCachePopulated = false;
163165

@@ -180,6 +182,9 @@ class swift::SourceLookupCache {
180182
void lookupValue(DeclName Name, NLKind LookupKind,
181183
SmallVectorImpl<ValueDecl*> &Result);
182184

185+
void lookupValueByObjCName(DeclName Name,
186+
SmallVectorImpl<ValueDecl *> &Result);
187+
183188
/// Retrieves all the operator decls. The order of the results is not
184189
/// guaranteed to be meaningful.
185190
void getOperatorDecls(SmallVectorImpl<OperatorDecl *> &results);
@@ -341,6 +346,17 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
341346
Result.push_back(Elt);
342347
}
343348

349+
void SourceLookupCache::lookupValueByObjCName(
350+
DeclName Name, SmallVectorImpl<ValueDecl *> &Result) {
351+
auto I = TopLevelValuesByObjCName.find(Name);
352+
if (I == TopLevelValuesByObjCName.end())
353+
return;
354+
355+
Result.reserve(I->second.size());
356+
for (ValueDecl *Elt : I->second)
357+
Result.push_back(Elt);
358+
}
359+
344360
void SourceLookupCache::getPrecedenceGroups(
345361
SmallVectorImpl<PrecedenceGroupDecl *> &results) {
346362
for (auto &groups : PrecedenceGroups)
@@ -736,6 +752,41 @@ void ModuleDecl::lookupValue(DeclName Name, NLKind LookupKind,
736752
FORWARD(lookupValue, (Name, LookupKind, Result));
737753
}
738754

755+
void ModuleDecl::lookupValueWithContext(DeclName Name, NLKind LookupKind,
756+
SmallVectorImpl<ValueDecl *> &Result,
757+
const DeclContext *Context) const {
758+
if (isParsedModule(this)) {
759+
getSourceLookupCache().lookupValue(Name, LookupKind, Result);
760+
return;
761+
}
762+
763+
for (const FileUnit *file : getFiles()) {
764+
// At the time of writing, Clang module units are the only FileUnits
765+
// that make use of the Context. If this changes, add appropriate calls
766+
// below.
767+
if (auto clangModuleUnit = dyn_cast<ClangModuleUnit>(file)) {
768+
clangModuleUnit->lookupValueWithContext(Name, LookupKind, Result,
769+
Context);
770+
} else {
771+
file->lookupValue(Name, LookupKind, Result);
772+
}
773+
if (auto *synth = file->getSynthesizedFile()) {
774+
synth->lookupValue(Name, LookupKind, Result);
775+
}
776+
}
777+
}
778+
779+
void ModuleDecl::lookupSwiftValueByObjCName(
780+
DeclName Name, SmallVectorImpl<ValueDecl *> &Result) const {
781+
782+
if (isParsedModule(this)) {
783+
getSourceLookupCache().lookupValueByObjCName(Name, Result);
784+
return;
785+
}
786+
787+
FORWARD(lookupSwiftValueByObjCName, (Name, Result));
788+
}
789+
739790
TypeDecl * ModuleDecl::lookupLocalType(StringRef MangledName) const {
740791
for (auto file : getFiles()) {
741792
auto TD = file->lookupLocalType(MangledName);
@@ -831,6 +882,11 @@ void BuiltinUnit::lookupValue(DeclName name, NLKind lookupKind,
831882
getCache().lookupValue(name.getBaseIdentifier(), lookupKind, *this, result);
832883
}
833884

885+
void BuiltinUnit::lookupSwiftValueByObjCName(
886+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const {
887+
// Shouldn't be any @objc values in the Builtin module.
888+
}
889+
834890
void BuiltinUnit::lookupObjCMethods(
835891
ObjCSelector selector,
836892
SmallVectorImpl<AbstractFunctionDecl *> &results) const {
@@ -842,6 +898,11 @@ void SourceFile::lookupValue(DeclName name, NLKind lookupKind,
842898
getCache().lookupValue(name, lookupKind, result);
843899
}
844900

901+
void SourceFile::lookupSwiftValueByObjCName(
902+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const {
903+
getCache().lookupValueByObjCName(name, result);
904+
}
905+
845906
void ModuleDecl::lookupVisibleDecls(ImportPath::Access AccessPath,
846907
VisibleDeclConsumer &Consumer,
847908
NLKind LookupKind) const {
@@ -3635,6 +3696,23 @@ void SynthesizedFileUnit::lookupValue(
36353696
}
36363697
}
36373698

3699+
void SynthesizedFileUnit::lookupSwiftValueByObjCName(
3700+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const {
3701+
for (auto *decl : TopLevelDecls) {
3702+
if (auto VD = dyn_cast<ValueDecl>(decl)) {
3703+
if (VD->getAttrs().hasAttribute<ObjCAttr>()) {
3704+
const ObjCAttr *objCAttribute = VD->getAttrs().getAttribute<ObjCAttr>();
3705+
const DeclName &objCName = objCAttribute->hasName()
3706+
? objCAttribute->getName()->getName()
3707+
: VD->getName();
3708+
if (objCName.matchesRef(name)) {
3709+
result.push_back(VD);
3710+
}
3711+
}
3712+
}
3713+
}
3714+
}
3715+
36383716
void SynthesizedFileUnit::lookupObjCMethods(
36393717
ObjCSelector selector,
36403718
SmallVectorImpl<AbstractFunctionDecl *> &results) const {

lib/AST/ModuleNameLookup.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ class LookupByName : public ModuleNameLookup<LookupByName> {
8181
}
8282

8383
void doLocalLookup(ModuleDecl *module, ImportPath::Access path,
84-
SmallVectorImpl<ValueDecl *> &localDecls) {
84+
SmallVectorImpl<ValueDecl *> &localDecls,
85+
const DeclContext *callingContext) {
8586
// If this import is specific to some named decl ("import Swift.Int")
8687
// then filter out any lookups that don't match.
8788
if (!path.matches(name))
8889
return;
89-
module->lookupValue(name, lookupKind, localDecls);
90+
module->lookupValueWithContext(name, lookupKind, localDecls,
91+
callingContext);
9092
}
9193
};
9294

@@ -112,7 +114,8 @@ class LookupVisibleDecls : public ModuleNameLookup<LookupVisibleDecls> {
112114
}
113115

114116
void doLocalLookup(ModuleDecl *module, ImportPath::Access path,
115-
SmallVectorImpl<ValueDecl *> &localDecls) {
117+
SmallVectorImpl<ValueDecl *> &localDecls,
118+
const DeclContext *callingContext) {
116119
VectorDeclConsumer consumer(localDecls);
117120
module->lookupVisibleDecls(path, consumer, lookupKind);
118121
}
@@ -169,7 +172,7 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
169172

170173
// Do the lookup into the current module.
171174
auto *module = moduleOrFile->getParentModule();
172-
getDerived()->doLocalLookup(module, accessPath, decls);
175+
getDerived()->doLocalLookup(module, accessPath, decls, moduleOrFile);
173176
updateNewDecls(moduleScopeContext);
174177

175178
bool canReturnEarly = (initialCount != decls.size() &&
@@ -196,7 +199,7 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
196199
return;
197200

198201
getDerived()->doLocalLookup(import.importedModule, import.accessPath,
199-
decls);
202+
decls, moduleOrFile);
200203
updateNewDecls(moduleScopeContext);
201204
};
202205

lib/ClangImporter/ClangImporter.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3286,6 +3286,12 @@ void ClangModuleUnit::getDisplayDecls(SmallVectorImpl<Decl*> &results, bool recu
32863286

32873287
void ClangModuleUnit::lookupValue(DeclName name, NLKind lookupKind,
32883288
SmallVectorImpl<ValueDecl*> &results) const {
3289+
lookupValueWithContext(name, lookupKind, results, nullptr);
3290+
}
3291+
3292+
void ClangModuleUnit::lookupValueWithContext(
3293+
DeclName name, NLKind lookupKind, SmallVectorImpl<ValueDecl *> &results,
3294+
const DeclContext *context) const {
32893295
// FIXME: Ignore submodules, which are empty for now.
32903296
if (clangModule && clangModule->isSubModule())
32913297
return;
@@ -3305,10 +3311,21 @@ void ClangModuleUnit::lookupValue(DeclName name, NLKind lookupKind,
33053311
// Find the corresponding lookup table.
33063312
if (auto lookupTable = owner.findLookupTable(clangModule)) {
33073313
// Search it.
3308-
owner.lookupValue(*lookupTable, name, *consumer);
3314+
if (context) {
3315+
owner.setImportingContext(*context);
3316+
owner.lookupValue(*lookupTable, name, *consumer);
3317+
owner.resetImportingContext();
3318+
} else {
3319+
owner.lookupValue(*lookupTable, name, *consumer);
3320+
}
33093321
}
33103322
}
33113323

3324+
void ClangModuleUnit::lookupSwiftValueByObjCName(
3325+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const {
3326+
// Clang modules don't store Swift declarations, much less @objc annotated ones.
3327+
}
3328+
33123329
bool ClangImporter::Implementation::isVisibleClangEntry(
33133330
const clang::NamedDecl *clangDecl) {
33143331
// For a declaration, check whether the declaration is hidden.

lib/ClangImporter/DWARFImporter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class DWARFModuleUnit final : public LoadedFile {
3838
getParentModule()->getName(), results);
3939
}
4040

41+
virtual void lookupSwiftValueByObjCName(
42+
DeclName name, SmallVectorImpl<ValueDecl *> &result) const override {}
43+
4144
virtual TypeDecl *
4245
lookupNestedType(Identifier name,
4346
const NominalTypeDecl *baseType) const override {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4514,6 +4514,47 @@ namespace {
45144514
}
45154515
}
45164516

4517+
if (auto importingContext = Impl.getImportingContext()) {
4518+
llvm::SmallVector<ValueDecl *> results;
4519+
llvm::SmallVector<ImportedModule> importedModules;
4520+
4521+
const SourceFile *importingSwiftSourceFile =
4522+
importingContext.getValue()->getParentSourceFile();
4523+
if (importingSwiftSourceFile) {
4524+
importingSwiftSourceFile->getImportedModules(
4525+
importedModules, ModuleDecl::ImportFilterKind::Default);
4526+
} else {
4527+
// If the DeclContext chain does not contain a SourceFile,
4528+
// we fall back to the top level Module. This occurs in cases
4529+
// were the main module is serialized (ex: swift-ide-test)
4530+
// instead of currently being compiled.
4531+
const ModuleDecl *importingSwiftModule =
4532+
importingContext.getValue()->getParentModule();
4533+
ModuleDecl::ImportFilter filter;
4534+
filter |= ModuleDecl::ImportFilterKind::Default;
4535+
filter |= ModuleDecl::ImportFilterKind::Exported;
4536+
filter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
4537+
// TODO: Do we need these last 3?
4538+
filter |= ModuleDecl::ImportFilterKind::SPIAccessControl;
4539+
filter |= ModuleDecl::ImportFilterKind::SPIOnly;
4540+
filter |=
4541+
ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay;
4542+
importingSwiftModule->getImportedModules(importedModules, filter);
4543+
}
4544+
4545+
for (auto &import : importedModules) {
4546+
if (import.importedModule->isNonSwiftModule())
4547+
continue;
4548+
4549+
import.importedModule->lookupSwiftValueByObjCName(name, results);
4550+
for (auto result : results) {
4551+
if (ClassDecl *swiftDefinition = dyn_cast<ClassDecl>(result)) {
4552+
return swiftDefinition;
4553+
}
4554+
}
4555+
}
4556+
}
4557+
45174558
if (Impl.ImportForwardDeclarations) {
45184559
// Fake it by making an unavailable opaque @objc root class.
45194560
auto result = createFakeRootClass(name);

0 commit comments

Comments
 (0)