Skip to content

Commit bc460a2

Browse files
committed
[ClangImporter] Add fast-path lookup for error code enums as well.
These are also imported as local types, so they can have the same issues as the previous commit.
1 parent 925f291 commit bc460a2

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,6 +2435,23 @@ static bool isVisibleClangEntry(clang::ASTContext &ctx,
24352435
TypeDecl *
24362436
ClangModuleUnit::lookupNestedType(Identifier name,
24372437
const NominalTypeDecl *baseType) const {
2438+
// Special case for error code enums: try looking directly into the struct
2439+
// first. But only if it looks like a synthesized error wrapped struct.
2440+
if (name == getASTContext().Id_Code && !baseType->hasClangNode() &&
2441+
isa<StructDecl>(baseType) && !baseType->hasLazyMembers() &&
2442+
baseType->isChildContextOf(this)) {
2443+
auto *mutableBase = const_cast<NominalTypeDecl *>(baseType);
2444+
auto codeEnum = mutableBase->lookupDirect(name,/*ignoreNewExtensions*/true);
2445+
// Double-check that we actually have a good result. It's possible what we
2446+
// found is /not/ a synthesized error struct, but just something that looks
2447+
// like it. But if we still found a good result we should return that.
2448+
if (codeEnum.size() == 1 && isa<TypeDecl>(codeEnum.front()))
2449+
return cast<TypeDecl>(codeEnum.front());
2450+
if (codeEnum.size() > 1)
2451+
return nullptr;
2452+
// Otherwise, fall back and try via lookup table.
2453+
}
2454+
24382455
auto lookupTable = owner.findLookupTable(clangModule);
24392456
if (!lookupTable)
24402457
return nullptr;
@@ -2491,9 +2508,13 @@ ClangModuleUnit::lookupNestedType(Identifier name,
24912508
});
24922509
}
24932510

2494-
if (results.size() == 1)
2495-
return results.front();
2496-
return nullptr;
2511+
if (results.size() != 1) {
2512+
// It's possible that two types were import-as-member'd onto the same base
2513+
// type with the same name. In this case, fall back to regular lookup.
2514+
return nullptr;
2515+
}
2516+
2517+
return results.front();
24972518
}
24982519

24992520
void ClangImporter::loadExtensions(NominalTypeDecl *nominal,

test/Serialization/Inputs/xref-nested-clang-type/NestedClangTypes.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,14 @@ struct Outer {
55
struct __attribute__((swift_name("Outer.InterestingValue"))) Inner {
66
int value;
77
};
8+
9+
#if __OBJC__
10+
11+
@import Foundation;
12+
13+
extern NSString * const ErrorCodeDomain;
14+
enum __attribute__((ns_error_domain(ErrorCodeDomain))) ErrorCodeEnum {
15+
ErrorCodeEnumA
16+
};
17+
18+
#endif // __OBJC__
Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend -emit-module -o %t -I %S/Inputs/xref-nested-clang-type/ %s -module-name Lib
3+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t -I %S/Inputs/xref-nested-clang-type/ %s -module-name Lib
44

5-
// RUN: %target-swift-frontend -typecheck -I %t -I %S/Inputs/xref-nested-clang-type/ %s -DCLIENT -verify
5+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %t -I %S/Inputs/xref-nested-clang-type/ %s -DCLIENT -verify
66

77
#if CLIENT
88

99
import Lib
1010

1111
func test(x: MyInner) {}
1212

13-
#else
13+
#if _runtime(_ObjC)
14+
import Foundation
15+
func test(x: MyCode) {}
16+
#endif // ObjC
17+
18+
#else // CLIENT
1419

1520
import NestedClangTypes
1621

@@ -21,4 +26,13 @@ extension MyOuter {
2126
public func use(inner: MyInner) {}
2227
}
2328

24-
#endif
29+
#if _runtime(_ObjC)
30+
import Foundation
31+
32+
public typealias MyCode = ErrorCodeEnum.Code
33+
extension ErrorCodeEnum {
34+
public func whatever(code: MyCode) {}
35+
}
36+
#endif // ObjC
37+
38+
#endif // CLIENT

0 commit comments

Comments
 (0)