Skip to content

Commit 0ef9b79

Browse files
committed
[PrintAsObjC] Use NSUInteger if protocol requires
When printing an ObjC member into a header with an `Int` parameter or result, PrintAsClang would look up any imported Objective-C member it overrode to see if ClangImporter imported `NSUInteger` as `Int`, and if so, would print `NSUInteger` instead of `NSInteger`. However, it did not do the same for protocol requirements the member witnessed. Correct this oversight. Fixes rdar://124300674.
1 parent 59153a0 commit 0ef9b79

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -963,11 +963,26 @@ class DeclAndTypePrinter::Implementation
963963

964964
template <typename T>
965965
static const T *findClangBase(const T *member) {
966-
while (member) {
967-
if (member->getClangDecl())
968-
return member;
969-
member = member->getOverriddenDecl();
970-
}
966+
// Search overridden members.
967+
const T *ancestorMember = member;
968+
while (ancestorMember) {
969+
if (ancestorMember->getClangDecl())
970+
return ancestorMember;
971+
ancestorMember = ancestorMember->getOverriddenDecl();
972+
}
973+
974+
// Search witnessed requirements.
975+
// FIXME: Semi-arbitrary behavior if `member` witnesses several requirements
976+
// (The conformance which sorts first will be used; the others will be
977+
// ignored.)
978+
for (const ValueDecl *requirementVD :
979+
member->getSatisfiedProtocolRequirements(/*Sorted=*/true)) {
980+
const T *requirement = dyn_cast<T>(requirementVD);
981+
if (requirement && requirement->getClangDecl())
982+
return requirement;
983+
}
984+
985+
// No related clang members found.
971986
return nullptr;
972987
}
973988

test/PrintAsObjC/Inputs/custom-modules/override.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@
1616
- (BOOL)doAnotherThingWithError:(NSError **)error;
1717

1818
@end
19+
20+
@protocol Proto <NSObject>
21+
22+
- (NSUInteger)proto;
23+
- (NSUInteger)proto:(NSUInteger)ignored;
24+
- (NSUInteger)proto:(NSUInteger)x y:(NSUInteger)y;
25+
26+
@end

test/PrintAsObjC/override.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ class A_Child : Base {
4545
// CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
4646
} // CHECK-NEXT: @end
4747

48+
// CHECK-LABEL: @interface A_Child ({{.*}}) <Proto>
49+
extension A_Child : Proto {
50+
// CHECK-NEXT: - (NSUInteger)proto SWIFT_WARN_UNUSED_RESULT;
51+
func proto() -> Int { return 0 }
52+
53+
// CHECK-NEXT: - (NSUInteger)proto:(NSUInteger)_ SWIFT_WARN_UNUSED_RESULT;
54+
func proto(_: Int) -> Int { return 0 }
55+
56+
// CHECK-NEXT: - (NSUInteger)proto:(NSUInteger)_ y:(NSUInteger)y SWIFT_WARN_UNUSED_RESULT;
57+
func proto(_: Int, y: Int) -> Int { return 0 }
58+
} // CHECK-NEXT: @end
59+
4860
// CHECK-LABEL: @interface A_Grandchild : A_Child
4961
class A_Grandchild : A_Child {
5062
// CHECK-NEXT: @property (nonatomic, readonly, getter=getProp) NSUInteger prop;

0 commit comments

Comments
 (0)