Skip to content

Commit 2244cb4

Browse files
committed
Swift lookup tables: start testing and cleaning up handling for Objective-C.
Start testing the construction of the Swift lookup tables in the Clang importer for Objective-C entities. Fix some obvious issues, e.g., category and extension entries should be associated with the corresponding class, and the categories/extensions shouldn't have entries in the lookup table.
1 parent fa865c7 commit 2244cb4

File tree

4 files changed

+144
-1
lines changed

4 files changed

+144
-1
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,10 @@ DeclName ClangImporter::Implementation::importFullName(
15791579
const clang::NamedDecl *D,
15801580
bool *hasCustomName,
15811581
clang::DeclContext **effectiveContext) {
1582+
// Objective-C categories and extensions don't have names.
1583+
if (isa<clang::ObjCCategoryDecl>(D))
1584+
return { };
1585+
15821586
// Compute the effective context, if requested.
15831587
if (effectiveContext) {
15841588
auto dc = const_cast<clang::DeclContext *>(D->getDeclContext());
@@ -1605,6 +1609,12 @@ DeclName ClangImporter::Implementation::importFullName(
16051609
// Everything else goes into its redeclaration context.
16061610
*effectiveContext = dc->getRedeclContext();
16071611
}
1612+
1613+
// Anything in an Objective-C category or extension is adjusted to the
1614+
// class context.
1615+
if (auto category = dyn_cast<clang::ObjCCategoryDecl>(*effectiveContext)) {
1616+
*effectiveContext = category->getClassInterface();
1617+
}
16081618
}
16091619

16101620
// If we have a swift_name attribute, use that.

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,41 @@ void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl,
9494
static void printName(clang::NamedDecl *named, llvm::raw_ostream &out) {
9595
// If there is a name, print it.
9696
if (!named->getDeclName().isEmpty()) {
97+
// If we have an Objective-C method, print the class name along
98+
// with '+'/'-'.
99+
if (auto objcMethod = dyn_cast<clang::ObjCMethodDecl>(named)) {
100+
out << (objcMethod->isInstanceMethod() ? '-' : '+') << '[';
101+
if (auto classDecl = objcMethod->getClassInterface()) {
102+
classDecl->printName(out);
103+
out << ' ';
104+
} else if (auto proto = dyn_cast<clang::ObjCProtocolDecl>(
105+
objcMethod->getDeclContext())) {
106+
proto->printName(out);
107+
out << ' ';
108+
}
109+
named->printName(out);
110+
out << ']';
111+
return;
112+
}
113+
114+
// If we have an Objective-C property, print the class name along
115+
// with the property name.
116+
if (auto objcProperty = dyn_cast<clang::ObjCPropertyDecl>(named)) {
117+
auto dc = objcProperty->getDeclContext();
118+
if (auto classDecl = dyn_cast<clang::ObjCInterfaceDecl>(dc)) {
119+
classDecl->printName(out);
120+
out << '.';
121+
} else if (auto categoryDecl = dyn_cast<clang::ObjCCategoryDecl>(dc)) {
122+
categoryDecl->getClassInterface()->printName(out);
123+
out << '.';
124+
} else if (auto proto = dyn_cast<clang::ObjCProtocolDecl>(dc)) {
125+
proto->printName(out);
126+
out << '.';
127+
}
128+
named->printName(out);
129+
return;
130+
}
131+
97132
named->printName(out);
98133
return;
99134
}
@@ -158,7 +193,10 @@ void SwiftLookupTable::dump() const {
158193

159194
interleave(fullEntry.Decls.begin(), fullEntry.Decls.end(),
160195
[](clang::NamedDecl *decl) {
161-
decl->printName(llvm::errs());
196+
if (auto named = dyn_cast<clang::NamedDecl>(decl))
197+
printName(named, llvm::errs());
198+
else
199+
decl->printName(llvm::errs());
162200
},
163201
[] {
164202
llvm::errs() << ", ";

test/IDE/Inputs/swift_name_objc.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
@import ObjectiveC;
2+
3+
#define SWIFT_NAME(X) __attribute__((swift_name(#X)))
4+
5+
#ifndef SWIFT_ENUM_EXTRA
6+
# define SWIFT_ENUM_EXTRA
7+
#endif
8+
9+
#ifndef SWIFT_ENUM
10+
# define SWIFT_ENUM(_type, _name) \
11+
enum _name : _type _name; \
12+
enum SWIFT_ENUM_EXTRA _name : _type
13+
#endif
14+
15+
// Renaming classes
16+
SWIFT_NAME(SomeClass)
17+
@interface SNSomeClass : NSObject
18+
- (instancetype)initWithFloat:(float)f;
19+
- (void)instanceMethodWithX:(float)x y:(float)y z:(float)z;
20+
+ (instancetype)someClassWithDouble:(double)d;
21+
22+
@property (readonly,nonatomic) float floatProperty;
23+
@property (readwrite,nonatomic) double doubleProperty;
24+
@end
25+
26+
SWIFT_NAME(SomeProtocol)
27+
@protocol SNSomeProtocol
28+
- (void)protoInstanceMethodWithX:(float)x y:(float)y;
29+
@end
30+
31+
@interface SNSomeClass ()
32+
- (void)extensionMethodWithX:(float)x y:(float)y;
33+
@end
34+
35+
@interface SNSomeClass (Category1) <SNSomeProtocol>
36+
- (void)categoryMethodWithX:(float)x y:(float)y;
37+
- (void)categoryMethodWithX:(float)x y:(float)y z:(float)z;
38+
@end
39+
40+
@interface SNCollision
41+
@end
42+
43+
@protocol SNCollision
44+
@end
45+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %target-swift-ide-test -dump-importer-lookup-table -source-filename %s -import-objc-header %S/Inputs/swift_name_objc.h > %t.log 2>&1
2+
// RUN: FileCheck %s < %t.log
3+
4+
// REQUIRES: objc_interop
5+
6+
// CHECK: Base -> full name mappings:
7+
// CHECK-NEXT: SNCollision --> SNCollision
8+
// CHECK-NEXT: SomeClass --> SomeClass
9+
// CHECK-NEXT: SomeProtocol --> SomeProtocol
10+
// CHECK-NEXT: categoryMethodWithX --> categoryMethodWithX(_:y:), categoryMethodWithX(_:y:z:)
11+
// CHECK-NEXT: doubleProperty --> doubleProperty, doubleProperty()
12+
// CHECK-NEXT: extensionMethodWithX --> extensionMethodWithX(_:y:)
13+
// CHECK-NEXT: floatProperty --> floatProperty, floatProperty()
14+
// CHECK-NEXT: initWithFloat --> initWithFloat(_:)
15+
// CHECK-NEXT: instanceMethodWithX --> instanceMethodWithX(_:y:z:)
16+
// CHECK-NEXT: protoInstanceMethodWithX --> protoInstanceMethodWithX(_:y:)
17+
// CHECK-NEXT: setDoubleProperty --> setDoubleProperty(_:)
18+
// CHECK-NEXT: someClassWithDouble --> someClassWithDouble(_:)
19+
20+
// CHECK: Full name -> entry mappings:
21+
// CHECK-NEXT: SNCollision:
22+
// CHECK-NEXT: TU: SNCollision, SNCollision
23+
// CHECK-NEXT: SomeClass:
24+
// CHECK-NEXT: TU: SNSomeClass
25+
// CHECK-NEXT: SomeProtocol:
26+
// CHECK-NEXT: TU: SNSomeProtocol
27+
// CHECK-NEXT: categoryMethodWithX(_:y:):
28+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass categoryMethodWithX:y:]
29+
// CHECK-NEXT: categoryMethodWithX(_:y:z:):
30+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass categoryMethodWithX:y:z:]
31+
// CHECK-NEXT: doubleProperty:
32+
// CHECK-NEXT: SNSomeClass: SNSomeClass.doubleProperty
33+
// CHECK-NEXT: doubleProperty():
34+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass doubleProperty]
35+
// CHECK-NEXT: extensionMethodWithX(_:y:):
36+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass extensionMethodWithX:y:]
37+
// CHECK-NEXT: floatProperty:
38+
// CHECK-NEXT: SNSomeClass: SNSomeClass.floatProperty
39+
// CHECK-NEXT: floatProperty():
40+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass floatProperty]
41+
// CHECK-NEXT: initWithFloat(_:):
42+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass initWithFloat:]
43+
// CHECK-NEXT: instanceMethodWithX(_:y:z:):
44+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass instanceMethodWithX:y:z:]
45+
// CHECK-NEXT: protoInstanceMethodWithX(_:y:):
46+
// CHECK-NEXT: SNSomeProtocol: -[SNSomeProtocol protoInstanceMethodWithX:y:]
47+
// CHECK-NEXT: setDoubleProperty(_:):
48+
// CHECK-NEXT: SNSomeClass: -[SNSomeClass setDoubleProperty:]
49+
// CHECK-NEXT: someClassWithDouble(_:):
50+
// CHECK-NEXT: SNSomeClass: +[SNSomeClass someClassWithDouble:]

0 commit comments

Comments
 (0)