Skip to content

Commit

Permalink
Clang importer: teach importFullName about dropping certain variadics.
Browse files Browse the repository at this point in the history
This moves the hack used for UIActionSheet and UIAlertView's variadic
designated initializers over into importFullName().
  • Loading branch information
DougGregor committed Dec 3, 2015
1 parent 91d1c3b commit 13c1805
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 3 deletions.
52 changes: 50 additions & 2 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,46 @@ StringRef ClangImporter::Implementation::getEnumConstantNamePrefix(
return commonPrefix;
}

/// Determine whether the given Clang selector matches the given
/// selector pieces.
static bool isNonNullarySelector(clang::Selector selector,
ArrayRef<StringRef> pieces) {
unsigned n = selector.getNumArgs();
if (n == 0) return false;
if (n != pieces.size()) return false;

for (unsigned i = 0; i != n; ++i) {
if (selector.getNameForSlot(i) != pieces[i]) return false;
}

return true;
}

/// Whether we should make a variadic method with the given selector
/// non-variadic.
static bool shouldMakeSelectorNonVariadic(clang::Selector selector) {
// This is UIActionSheet's designated initializer.
if (isNonNullarySelector(selector,
{ "initWithTitle",
"delegate",
"cancelButtonTitle",
"destructiveButtonTitle",
"otherButtonTitles" }))
return true;

// This is UIAlertView's designated initializer.
if (isNonNullarySelector(selector,
{ "initWithTitle",
"message",
"delegate",
"cancelButtonTitle",
"otherButtonTitles" }))
return true;

// Nothing else for now.
return false;
}

auto ClangImporter::Implementation::importFullName(
const clang::NamedDecl *D,
clang::DeclContext **effectiveContext) -> ImportedName {
Expand Down Expand Up @@ -1694,8 +1734,16 @@ auto ClangImporter::Implementation::importFullName(
baseName = "init";
else
baseName = selector.getNameForSlot(0);
for (unsigned index = 0, numArgs = selector.getNumArgs(); index != numArgs;
++index) {

// If we have a variadic method for which we need to drop the last
// selector piece, do so now.
unsigned numArgs = selector.getNumArgs();
if (objcMethod->isVariadic() && shouldMakeSelectorNonVariadic(selector)) {
--numArgs;
result.DroppedVariadic = true;
}

for (unsigned index = 0; index != numArgs; ++index) {
if (index == 0) {
argumentNames.push_back(StringRef());
} else {
Expand Down
5 changes: 5 additions & 0 deletions lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,11 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
/// swift_name attribute.
bool HasCustomName = false;

/// Whether this was one of a special class of Objective-C
/// initializers for which we drop the variadic argument rather
/// than refuse to import the initializer.
bool DroppedVariadic = false;

/// For an initializer, the kind of initializer to import.
CtorInitializerKind InitKind;

Expand Down
4 changes: 4 additions & 0 deletions test/IDE/Inputs/swift_name_objc.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ SWIFT_NAME(SomeProtocol)
@protocol NSAccessibility
@property (nonatomic) float accessibilityFloat;
@end

@interface UIActionSheet : NSObject
-(instancetype)initWithTitle:(const char *)title delegate:(id)delegate cancelButtonTitle:(const char *)cancelButtonTitle destructiveButtonTitle:(const char *)destructiveButtonTitle otherButtonTitles:(const char *)otherButtonTitles, ...;
@end
7 changes: 6 additions & 1 deletion test/IDE/dump_swift_lookup_tables_objc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
// CHECK-NEXT: SNCollisionProtocol --> SNCollisionProtocol
// CHECK-NEXT: SomeClass --> SomeClass
// CHECK-NEXT: SomeProtocol --> SomeProtocol
// CHECK-NEXT: UIActionSheet --> UIActionSheet
// CHECK-NEXT: accessibilityFloat --> accessibilityFloat()
// CHECK-NEXT: categoryMethodWithX --> categoryMethodWithX(_:y:), categoryMethodWithX(_:y:z:)
// CHECK-NEXT: doubleProperty --> doubleProperty{{$}}
// CHECK-NEXT: extensionMethodWithX --> extensionMethodWithX(_:y:)
// CHECK-NEXT: floatProperty --> floatProperty{{$}}
// CHECK-NEXT: init --> init(float:), init(withDefault:), init(double:), init(withTry:), init(uint8:){{$}}
// CHECK-NEXT: init --> init(float:), init(withDefault:), init(double:), init(withTry:), init(uint8:), init(title:delegate:cancelButtonTitle:destructiveButtonTitle:)
// CHECK-NEXT: instanceMethodWithX --> instanceMethodWithX(_:y:z:)
// CHECK-NEXT: protoInstanceMethodWithX --> protoInstanceMethodWithX(_:y:)
// CHECK-NEXT: setAccessibilityFloat --> setAccessibilityFloat(_:)
Expand All @@ -30,6 +31,8 @@
// CHECK-NEXT: TU: SNSomeClass
// CHECK-NEXT: SomeProtocol:
// CHECK-NEXT: TU: SNSomeProtocol
// CHECK-NEXT: UIActionSheet:
// CHECK-NEXT: TU: UIActionSheet
// CHECK-NEXT: accessibilityFloat():
// CHECK-NEXT: NSAccessibility: -[NSAccessibility accessibilityFloat]
// CHECK-NEXT: categoryMethodWithX(_:y:):
Expand All @@ -46,6 +49,8 @@
// CHECK-NEXT: SNSomeClass: +[SNSomeClass someClassWithDouble:]
// CHECK-NEXT: init(float:):
// CHECK-NEXT: SNSomeClass: -[SNSomeClass initWithFloat:]
// CHECK-NEXT: init(title:delegate:cancelButtonTitle:destructiveButtonTitle:):
// CHECK-NEXT: UIActionSheet: -[UIActionSheet initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:]
// CHECK-NEXT: init(uint8:):
// CHECK-NEXT: SNSomeClass: +[SNSomeClass buildWithUnsignedChar:]
// CHECK-NEXT: init(withDefault:):
Expand Down

0 comments on commit 13c1805

Please sign in to comment.