Skip to content

Commit 2da1c24

Browse files
committed
swift forwarding
1 parent 3d36113 commit 2da1c24

12 files changed

+183
-20
lines changed

include/swift/AST/Module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,12 @@ 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+
643649
/// Look up a local type declaration by its mangled name.
644650
///
645651
/// This does a simple local lookup, not recursively looking through imports.

include/swift/ClangImporter/ClangModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ 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+
7175
virtual TypeDecl *
7276
lookupNestedType(Identifier name,
7377
const NominalTypeDecl *baseType) const override;

lib/AST/Module.cpp

Lines changed: 26 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

@@ -736,6 +737,30 @@ void ModuleDecl::lookupValue(DeclName Name, NLKind LookupKind,
736737
FORWARD(lookupValue, (Name, LookupKind, Result));
737738
}
738739

740+
void ModuleDecl::lookupValueWithContext(DeclName Name, NLKind LookupKind,
741+
SmallVectorImpl<ValueDecl *> &Result,
742+
const DeclContext *Context) const {
743+
if (isParsedModule(this)) {
744+
getSourceLookupCache().lookupValue(Name, LookupKind, Result);
745+
return;
746+
}
747+
748+
for (const FileUnit *file : getFiles()) {
749+
// At the time of writing, Clang module units are the only FileUnits
750+
// that make use of the Context. If this changes, add appropriate calls
751+
// below.
752+
if (auto clangModuleUnit = dyn_cast<ClangModuleUnit>(file)) {
753+
clangModuleUnit->lookupValueWithContext(Name, LookupKind, Result,
754+
Context);
755+
} else {
756+
file->lookupValue(Name, LookupKind, Result);
757+
}
758+
if (auto *synth = file->getSynthesizedFile()) {
759+
synth->lookupValue(Name, LookupKind, Result);
760+
}
761+
}
762+
}
763+
739764
TypeDecl * ModuleDecl::lookupLocalType(StringRef MangledName) const {
740765
for (auto file : getFiles()) {
741766
auto TD = file->lookupLocalType(MangledName);

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: 13 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,7 +3311,13 @@ 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

lib/ClangImporter/ImportDecl.cpp

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4298,19 +4298,21 @@ namespace {
42984298
}
42994299
}
43004300

4301-
if (!found) {
4302-
// Go back to the first list and find classes with matching Swift names
4303-
// *even if the ObjC name doesn't match.*
4304-
// This shouldn't be allowed but we need it for source compatibility;
4305-
// people used `@class SwiftNameOfClass` as a workaround for not
4306-
// having the previous loop, and it "worked".
4307-
for (auto result : swiftDeclsByName) {
4308-
if (auto singleResult = dyn_cast<T>(result)) {
4309-
if (isMatch(singleResult, /*baseNameMatches=*/true,
4310-
/*allowObjCMismatch=*/true)) {
4311-
if (found)
4312-
return nullptr;
4313-
found = singleResult;
4301+
if (!languageVersion.isVersionAtLeast(6)) {
4302+
if (!found) {
4303+
// Go back to the first list and find classes with matching Swift
4304+
// names *even if the ObjC name doesn't match.* This shouldn't be
4305+
// allowed but we need it for source compatibility; people used
4306+
// `@class SwiftNameOfClass` as a workaround for not having the
4307+
// previous loop, and it "worked".
4308+
for (auto result : swiftDeclsByName) {
4309+
if (auto singleResult = dyn_cast<T>(result)) {
4310+
if (isMatch(singleResult, /*baseNameMatches=*/true,
4311+
/*allowObjCMismatch=*/true)) {
4312+
if (found)
4313+
return nullptr;
4314+
found = singleResult;
4315+
}
43144316
}
43154317
}
43164318
}
@@ -4338,6 +4340,35 @@ namespace {
43384340
return result;
43394341
}
43404342
}
4343+
if (auto importingContext = Impl.getImportingContext()) {
4344+
llvm::SmallVector<ValueDecl *> results;
4345+
llvm::SmallVector<ImportedModule> importedModules;
4346+
4347+
const ModuleDecl *importingSwiftModule =
4348+
importingContext.getValue()->getParentModule();
4349+
4350+
if (importingSwiftModule->isNonSwiftModule())
4351+
return nullptr;
4352+
4353+
const SourceFile *importingSwiftSourceFile =
4354+
importingContext.getValue()->getParentSourceFile();
4355+
4356+
// TODO: Make sure we aren't bailing early in legitimate cases
4357+
if (!importingSwiftSourceFile)
4358+
return nullptr;
4359+
4360+
importingSwiftSourceFile->getImportedModules(
4361+
importedModules, ModuleDecl::ImportFilterKind::Default);
4362+
4363+
for (auto &import : importedModules) {
4364+
if (import.importedModule->isNonSwiftModule())
4365+
continue;
4366+
4367+
if (T *result = resolveSwiftDeclImpl<T>(decl, name, hasKnownSwiftName,
4368+
import.importedModule))
4369+
return result;
4370+
}
4371+
}
43414372
return nullptr;
43424373
}
43434374

lib/ClangImporter/ImporterImpl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
528528
/// used when parsing the attribute text.
529529
llvm::SmallDenseMap<ModuleDecl *, SourceFile *> ClangSwiftAttrSourceFiles;
530530

531+
/// If set, the Swift DeclContext from which the current
532+
/// import request was triggered.
533+
llvm::Optional<const swift::DeclContext *> ImportingContext;
534+
531535
public:
532536
/// The Swift lookup table for the bridging header.
533537
std::unique_ptr<SwiftLookupTable> BridgingHeaderLookupTable;
@@ -587,6 +591,16 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
587591
return Instance.get();
588592
}
589593

594+
void setImportingContext(const DeclContext &importingContext) {
595+
ImportingContext = &importingContext;
596+
}
597+
598+
void resetImportingContext() { ImportingContext = None; }
599+
600+
llvm::Optional<const DeclContext *> getImportingContext() {
601+
return ImportingContext;
602+
}
603+
590604
private:
591605
/// Generation number that is used for crude versioning.
592606
///
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Foundation
2+
3+
@objc public class Foo : NSObject {
4+
@objc public func sayHello() {
5+
print("Hello from Foo.sayHello!")
6+
}
7+
}
8+
9+
@objc(Baz) public class Bar : NSObject {
10+
@objc public func sayHello() {
11+
print("Hello from Bar.sayHello!")
12+
}
13+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module ObjCLibraryForwardDeclaringCompleteSwiftTypes {
2+
header "objc-library-forward-declaring-complete-swift-types.h"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@class Foo;
2+
@class Baz;
3+
4+
void takeAFoo(Foo *foo);
5+
Foo *returnAFoo();
6+
7+
void takeABaz(Baz *baz);
8+
Baz *returnABaz();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#import "objc-library-forward-declaring-complete-swift-types.h"
2+
#import "CompleteSwiftTypes-Swift.h"
3+
4+
void takeAFoo(Foo *foo) { [foo sayHello]; }
5+
6+
Foo *returnAFoo() {
7+
Foo *result = [[Foo alloc] init];
8+
[result sayHello];
9+
return result;
10+
}
11+
12+
void takeABaz(Baz *baz) { [baz sayHello]; }
13+
14+
Baz *returnABaz() {
15+
Baz *result = [[Baz alloc] init];
16+
[result sayHello];
17+
return result;
18+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -parse-as-library %S/Inputs/custom-modules/IncompleteTypes/complete-swift-types.swift -emit-module -emit-module-path %t/CompleteSwiftTypes.swiftmodule -emit-objc-header -emit-objc-header-path %t/CompleteSwiftTypes-Swift.h -emit-library -o %t/libCompleteSwiftTypes.dylib
3+
// RUN: %target-clang -framework Foundation -dynamiclib %S/Inputs/custom-modules/IncompleteTypes/objc-library-forward-declaring-complete-swift-types.m -I %t -L %t -lCompleteSwiftTypes -o %t/libObjCLibraryForwardDeclaringCompleteSwiftTypes.dylib
4+
// RUN: %target-build-swift -Xfrontend -enable-objc-interop %s -I %S/Inputs/custom-modules/IncompleteTypes -I %t -L %t -lCompleteSwiftTypes -lObjCLibraryForwardDeclaringCompleteSwiftTypes -o %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s
6+
7+
// REQUIRES: objc_interop
8+
9+
import CompleteSwiftTypes
10+
import ObjCLibraryForwardDeclaringCompleteSwiftTypes
11+
12+
// Swift initializers
13+
let foo = Foo()
14+
let bar = Bar()
15+
16+
// Imported from Objective-C
17+
// CHECK: Hello from Foo.sayHello!
18+
takeAFoo(foo)
19+
// CHECK: Hello from Foo.sayHello!
20+
let foo2 = returnAFoo()
21+
22+
// CHECK: Hello from Bar.sayHello!
23+
takeABaz(bar)
24+
// CHECK: Hello from Bar.sayHello!
25+
let bar2 = returnABaz()
26+

0 commit comments

Comments
 (0)