Skip to content

Commit 09cdd36

Browse files
authored
[c++-interop] For failed imports in ClangImporter, cache them regardless. (#41173)
As per SR-14137 this caches entries in ImportedDecls even when the import failed. Also have to mention I did this based on Thomas's PR #36747. This should help us better handle complex templates and dependant types.
1 parent 9e919fd commit 09cdd36

File tree

6 files changed

+42
-33
lines changed

6 files changed

+42
-33
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,12 @@ class ClangImporter final : public ClangModuleLoader {
441441

442442
std::string getClangModuleHash() const;
443443

444-
/// If we already imported a given decl, return the corresponding Swift decl.
445-
/// Otherwise, return nullptr.
446-
Decl *importDeclCached(const clang::NamedDecl *ClangDecl);
444+
/// If we already imported a given decl successfully, return the corresponding
445+
/// Swift decl as an Optional<Decl *>, but if we previously tried and failed
446+
/// to import said decl then return nullptr.
447+
/// Otherwise, if we have never encountered this decl previously then return
448+
/// None.
449+
Optional<Decl *> importDeclCached(const clang::NamedDecl *ClangDecl);
447450

448451
// Returns true if it is expected that the macro is ignored.
449452
bool shouldIgnoreMacro(StringRef Name, const clang::MacroInfo *Macro);

lib/ClangImporter/ClangImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3631,7 +3631,8 @@ std::string ClangImporter::getClangModuleHash() const {
36313631
return Impl.Invocation->getModuleHash(Impl.Instance->getDiagnostics());
36323632
}
36333633

3634-
Decl *ClangImporter::importDeclCached(const clang::NamedDecl *ClangDecl) {
3634+
Optional<Decl *>
3635+
ClangImporter::importDeclCached(const clang::NamedDecl *ClangDecl) {
36353636
return Impl.importDeclCached(ClangDecl, Impl.CurrentVersion);
36363637
}
36373638

lib/ClangImporter/ImportDecl.cpp

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4841,8 +4841,9 @@ namespace {
48414841

48424842
// While importing the DeclContext, we might have imported the decl
48434843
// itself.
4844-
if (auto Known = Impl.importDeclCached(decl, getVersion()))
4845-
return Known;
4844+
auto Known = Impl.importDeclCached(decl, getVersion());
4845+
if (Known.hasValue())
4846+
return Known.getValue();
48464847

48474848
ImportedName importedName;
48484849
std::tie(importedName, std::ignore) = importFullName(decl);
@@ -4926,8 +4927,11 @@ namespace {
49264927
}
49274928

49284929
private:
4929-
static bool isAcceptableResult(Decl *fn,
4930-
Optional<AccessorInfo> accessorInfo) {
4930+
static bool isAcceptableResultOrNull(Decl *fn,
4931+
Optional<AccessorInfo> accessorInfo) {
4932+
if (nullptr == fn)
4933+
return true;
4934+
49314935
// We can't safely re-use the same declaration if it disagrees
49324936
// in accessor-ness.
49334937
auto accessor = dyn_cast<AccessorDecl>(fn);
@@ -5038,7 +5042,7 @@ namespace {
50385042
getVersion()});
50395043
if (known != Impl.ImportedDecls.end()) {
50405044
auto decl = known->second;
5041-
if (isAcceptableResult(decl, accessorInfo))
5045+
if (isAcceptableResultOrNull(decl, accessorInfo))
50425046
return decl;
50435047
}
50445048
}
@@ -5056,7 +5060,7 @@ namespace {
50565060
if (isActiveSwiftVersion()) {
50575061
if (isMethodAlreadyImported(selector, importedName, isInstance, dc,
50585062
[&](AbstractFunctionDecl *fn) {
5059-
return isAcceptableResult(fn, accessorInfo);
5063+
return isAcceptableResultOrNull(fn, accessorInfo);
50605064
})) {
50615065
return nullptr;
50625066
}
@@ -5190,7 +5194,7 @@ namespace {
51905194
getVersion()});
51915195
if (known != Impl.ImportedDecls.end()) {
51925196
auto decl = known->second;
5193-
if (isAcceptableResult(decl, accessorInfo))
5197+
if (isAcceptableResultOrNull(decl, accessorInfo))
51945198
return decl;
51955199
}
51965200
}
@@ -5885,8 +5889,9 @@ namespace {
58855889

58865890
// While importing the DeclContext, we might have imported the decl
58875891
// itself.
5888-
if (auto Known = Impl.importDeclCached(decl, getVersion()))
5889-
return Known;
5892+
auto Known = Impl.importDeclCached(decl, getVersion());
5893+
if (Known.hasValue())
5894+
return Known.getValue();
58905895

58915896
return importObjCPropertyDecl(decl, dc);
58925897
}
@@ -8589,16 +8594,16 @@ void SwiftDeclConverter::importInheritedConstructors(
85898594
}
85908595
}
85918596

8592-
Decl *ClangImporter::Implementation::importDeclCached(
8597+
Optional<Decl *> ClangImporter::Implementation::importDeclCached(
85938598
const clang::NamedDecl *ClangDecl,
85948599
ImportNameVersion version,
85958600
bool UseCanonical) {
85968601
auto Known = ImportedDecls.find(
85978602
{ UseCanonical? ClangDecl->getCanonicalDecl(): ClangDecl, version });
8598-
if (Known != ImportedDecls.end())
8599-
return Known->second;
8603+
if (Known == ImportedDecls.end())
8604+
return None;
86008605

8601-
return nullptr;
8606+
return Known->second;
86028607
}
86038608

86048609
/// Checks if we don't need to import the typedef itself. If the typedef
@@ -9451,11 +9456,12 @@ Decl *ClangImporter::Implementation::importDeclAndCacheImpl(
94519456

94529457
auto Canon = cast<clang::NamedDecl>(UseCanonicalDecl? ClangDecl->getCanonicalDecl(): ClangDecl);
94539458

9454-
if (auto Known = importDeclCached(Canon, version, UseCanonicalDecl)) {
9459+
auto Known = importDeclCached(Canon, version, UseCanonicalDecl);
9460+
if (Known.hasValue()) {
94559461
if (!SuperfluousTypedefsAreTransparent &&
94569462
SuperfluousTypedefs.count(Canon))
94579463
return nullptr;
9458-
return Known;
9464+
return Known.getValue();
94599465
}
94609466

94619467
bool TypedefIsSuperfluous = false;
@@ -9464,8 +9470,10 @@ Decl *ClangImporter::Implementation::importDeclAndCacheImpl(
94649470
startedImportingEntity();
94659471
Decl *Result = importDeclImpl(ClangDecl, version, TypedefIsSuperfluous,
94669472
HadForwardDeclaration);
9467-
if (!Result)
9473+
if (!Result) {
9474+
ImportedDecls[{Canon, version}] = nullptr;
94689475
return nullptr;
9476+
}
94699477

94709478
if (TypedefIsSuperfluous) {
94719479
SuperfluousTypedefs.insert(Canon);
@@ -9633,8 +9641,9 @@ ClangImporter::Implementation::importDeclForDeclContext(
96339641

96349642
// There's a cycle. Is the declaration imported enough to break the cycle
96359643
// gracefully? If so, we'll have it in the decl cache.
9636-
if (auto cached = importDeclCached(contextDecl, version, useCanonicalDecl))
9637-
return cached;
9644+
auto cached = importDeclCached(contextDecl, version, useCanonicalDecl);
9645+
if (cached.hasValue())
9646+
return cached.getValue();
96389647

96399648
// Can't break it? Warn and return nullptr, which is at least better than
96409649
// stack overflow by recursion.

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -958,8 +958,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
958958

959959
/// If we already imported a given decl, return the corresponding Swift decl.
960960
/// Otherwise, return nullptr.
961-
Decl *importDeclCached(const clang::NamedDecl *ClangDecl, Version version,
962-
bool UseCanonicalDecl = true);
961+
Optional<Decl *> importDeclCached(const clang::NamedDecl *ClangDecl,
962+
Version version,
963+
bool UseCanonicalDecl = true);
963964

964965
Decl *importDeclImpl(const clang::NamedDecl *ClangDecl, Version version,
965966
bool &TypedefIsSuperfluous, bool &HadForwardDeclaration);

lib/ClangImporter/Serializability.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ class SerializationPathFinder {
6666

6767
StableSerializationPath findImportedPath(const clang::NamedDecl *decl) {
6868
// We've almost certainly imported this declaration, look for it.
69-
if (auto swiftDecl = Impl.importDeclCached(decl, Impl.CurrentVersion)) {
69+
Optional<Decl *> swiftDeclOpt =
70+
Impl.importDeclCached(decl, Impl.CurrentVersion);
71+
if (swiftDeclOpt.hasValue() && swiftDeclOpt.getValue()) {
72+
auto swiftDecl = swiftDeclOpt.getValue();
7073
// The serialization code doesn't allow us to cross-reference
7174
// typealias declarations directly. We could fix that, but it's
7275
// easier to just avoid doing so and fall into the external-path code.

test/ClangImporter/attr-swift_name.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ func test(_ i: Int) {
4545
// CHECK: SWIFT_NAME(MutuallyCircularNameA.Inner) @interface MutuallyCircularNameB : NSObject @end
4646
// CHECK-NOT: {{warning|note}}:
4747
// CHECK: note: please report this issue to the owners of 'ObjCIRExtras'
48-
// CHECK-NOT: warning:
49-
50-
// CHECK: warning: cycle detected while resolving 'MutuallyCircularNameA' in swift_name attribute for 'MutuallyCircularNameB'
51-
// CHECK: SWIFT_NAME(MutuallyCircularNameA.Inner) @interface MutuallyCircularNameB : NSObject @end
5248
// CHECK-NOT: {{warning|note}}:
53-
// CHECK: note: while resolving 'MutuallyCircularNameB' in swift_name attribute for 'MutuallyCircularNameA'
5449
// CHECK: SWIFT_NAME(MutuallyCircularNameB.Inner) @interface MutuallyCircularNameA : NSObject @end
55-
// CHECK-NOT: {{warning|note}}:
56-
// CHECK: note: please report this issue to the owners of 'ObjCIRExtras'
57-
// CHECK-NOT: warning:
5850
}

0 commit comments

Comments
 (0)