Skip to content

Commit 8a546a9

Browse files
authored
Merge pull request #59421 from plotfi/typedef-ns-options-name-fixup
[c++-interop] Providing information about enum types from inferDefaultArgument
2 parents 59a9e28 + 28375ae commit 8a546a9

File tree

7 files changed

+152
-10
lines changed

7 files changed

+152
-10
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5744,6 +5744,10 @@ class ParamDecl : public VarDecl {
57445744
Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
57455745
}
57465746

5747+
void setDefaultArgumentKind(ArgumentAttrs K) {
5748+
setDefaultArgumentKind(K.argumentKind);
5749+
}
5750+
57475751
bool isNoImplicitCopy() const {
57485752
return getAttrs().hasAttribute<NoImplicitCopyAttr>();
57495753
}

include/swift/AST/DefaultArgumentKind.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#ifndef SWIFT_DEFAULTARGUMENTKIND_H
1818
#define SWIFT_DEFAULTARGUMENTKIND_H
1919

20+
#include "llvm/ADT/StringRef.h"
2021
#include <cstdint>
22+
#include <string>
2123

2224
namespace llvm {
2325
class StringRef;
@@ -52,6 +54,40 @@ enum class DefaultArgumentKind : uint8_t {
5254
};
5355
enum { NumDefaultArgumentKindBits = 4 };
5456

57+
struct ArgumentAttrs {
58+
DefaultArgumentKind argumentKind;
59+
bool isUnavailableInSwift = false;
60+
llvm::StringRef CXXOptionsEnumName = "";
61+
62+
ArgumentAttrs(DefaultArgumentKind argumentKind,
63+
bool isUnavailableInSwift = false,
64+
llvm::StringRef CXXOptionsEnumName = "")
65+
: argumentKind(argumentKind), isUnavailableInSwift(isUnavailableInSwift),
66+
CXXOptionsEnumName(CXXOptionsEnumName) {}
67+
68+
bool operator !=(const DefaultArgumentKind &rhs) const {
69+
return argumentKind != rhs;
70+
}
71+
72+
bool operator==(const DefaultArgumentKind &rhs) const {
73+
return argumentKind == rhs;
74+
}
75+
76+
bool hasDefaultArg() const {
77+
return argumentKind != DefaultArgumentKind::None;
78+
}
79+
80+
bool hasAlternateCXXOptionsEnumName() const {
81+
return !CXXOptionsEnumName.empty() && isUnavailableInSwift;
82+
}
83+
84+
llvm::StringRef getAlternateCXXOptionsEnumName() const {
85+
assert(hasAlternateCXXOptionsEnumName() &&
86+
"Expected a C++ Options type for C++-Interop but found none.");
87+
return CXXOptionsEnumName;
88+
}
89+
};
90+
5591
} // end namespace swift
5692

5793
#endif // LLVM_SWIFT_DEFAULTARGUMENTKIND_H

lib/ClangImporter/ImportName.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -869,16 +869,18 @@ static bool omitNeedlessWordsInFunctionName(
869869
StringRef argumentName;
870870
if (i < argumentNames.size())
871871
argumentName = argumentNames[i];
872-
bool hasDefaultArg =
872+
auto argumentAttrs =
873873
ClangImporter::Implementation::inferDefaultArgument(
874874
param->getType(),
875875
getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[i]),
876876
nameImporter.getIdentifier(baseName), argumentName, i == 0,
877-
isLastParameter, nameImporter) != DefaultArgumentKind::None;
877+
isLastParameter, nameImporter);
878878

879-
paramTypes.push_back(getClangTypeNameForOmission(clangCtx,
880-
param->getOriginalType())
881-
.withDefaultArgument(hasDefaultArg));
879+
paramTypes.push_back(
880+
(argumentAttrs.hasAlternateCXXOptionsEnumName()
881+
? OmissionTypeName(argumentAttrs.getAlternateCXXOptionsEnumName())
882+
: getClangTypeNameForOmission(clangCtx, param->getOriginalType()))
883+
.withDefaultArgument(argumentAttrs.hasDefaultArg()));
882884
}
883885

884886
// Find the property names.

lib/ClangImporter/ImportType.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/ABI/MetadataValues.h"
2121
#include "swift/AST/ASTContext.h"
2222
#include "swift/AST/Decl.h"
23+
#include "swift/AST/DefaultArgumentKind.h"
2324
#include "swift/AST/DiagnosticEngine.h"
2425
#include "swift/AST/DiagnosticsClangImporter.h"
2526
#include "swift/AST/ExistentialLayout.h"
@@ -2410,7 +2411,7 @@ static bool isObjCMethodResultAudited(const clang::Decl *decl) {
24102411
decl->hasAttr<clang::ObjCReturnsInnerPointerAttr>());
24112412
}
24122413

2413-
DefaultArgumentKind ClangImporter::Implementation::inferDefaultArgument(
2414+
ArgumentAttrs ClangImporter::Implementation::inferDefaultArgument(
24142415
clang::QualType type, OptionalTypeKind clangOptionality,
24152416
DeclBaseName baseName, StringRef argumentLabel, bool isFirstParameter,
24162417
bool isLastParameter, NameImporter &nameImporter) {
@@ -2455,10 +2456,29 @@ DefaultArgumentKind ClangImporter::Implementation::inferDefaultArgument(
24552456
// If we've taken this branch it means we have an enum type, and it is
24562457
// likely an integer or NSInteger that is being used by NS/CF_OPTIONS to
24572458
// behave like a C enum in the presence of C++.
2458-
auto enumName = typedefType->getDecl()->getDeclName().getAsString();
2459+
auto enumName = typedefType->getDecl()->getName();
2460+
ArgumentAttrs argumentAttrs(DefaultArgumentKind::None, true, enumName);
24592461
for (auto word : llvm::reverse(camel_case::getWords(enumName))) {
2460-
if (camel_case::sameWordIgnoreFirstCase(word, "options"))
2461-
return DefaultArgumentKind::EmptyArray;
2462+
if (camel_case::sameWordIgnoreFirstCase(word, "options")) {
2463+
argumentAttrs.argumentKind = DefaultArgumentKind::EmptyArray;
2464+
return argumentAttrs;
2465+
}
2466+
if (camel_case::sameWordIgnoreFirstCase(word, "units"))
2467+
return argumentAttrs;
2468+
if (camel_case::sameWordIgnoreFirstCase(word, "domain"))
2469+
return argumentAttrs;
2470+
if (camel_case::sameWordIgnoreFirstCase(word, "action"))
2471+
return argumentAttrs;
2472+
if (camel_case::sameWordIgnoreFirstCase(word, "controlevents"))
2473+
return argumentAttrs;
2474+
if (camel_case::sameWordIgnoreFirstCase(word, "state"))
2475+
return argumentAttrs;
2476+
if (camel_case::sameWordIgnoreFirstCase(word, "unit"))
2477+
return argumentAttrs;
2478+
if (camel_case::sameWordIgnoreFirstCase(word, "scrollposition"))
2479+
return argumentAttrs;
2480+
if (camel_case::sameWordIgnoreFirstCase(word, "edge"))
2481+
return argumentAttrs;
24622482
}
24632483
}
24642484
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1397,7 +1397,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
13971397

13981398
/// Attempt to infer a default argument for a parameter with the
13991399
/// given Clang \c type, \c baseName, and optionality.
1400-
static DefaultArgumentKind
1400+
static ArgumentAttrs
14011401
inferDefaultArgument(clang::QualType type, OptionalTypeKind clangOptionality,
14021402
DeclBaseName baseName, StringRef argumentLabel,
14031403
bool isFirstParameter, bool isLastParameter,

test/Interop/Cxx/enum/Inputs/c-enums-withOptions-omit.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,33 @@ enum : NSEnumerationOptions { NSEnumerationConcurrent, NSEnumerationReverse };
66
@interface NSSet
77
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts ;
88
@end
9+
10+
typedef int __attribute__((availability(swift, unavailable))) NSOrderedCollectionDifferenceCalculationOptions;
11+
enum : NSOrderedCollectionDifferenceCalculationOptions {
12+
NSOrderedCollectionDifferenceCalculationOptions1,
13+
NSOrderedCollectionDifferenceCalculationOptions2
14+
};
15+
16+
typedef int __attribute__((availability(swift, unavailable))) NSCalendarUnit;
17+
enum : NSCalendarUnit { NSCalendarUnit1, NSCalendarUnit2 };
18+
19+
typedef int __attribute__((availability(swift, unavailable))) NSSearchPathDomainMask;
20+
enum : NSSearchPathDomainMask { NSSearchPathDomainMask1, NSSearchPathDomainMask2 };
21+
22+
typedef int __attribute__((availability(swift, unavailable))) NSControlCharacterAction;
23+
enum : NSControlCharacterAction { NSControlCharacterAction1, NSControlCharacterAction2 };
24+
25+
typedef int __attribute__((availability(swift, unavailable))) UIControlState;
26+
enum : UIControlState { UIControlState1, UIControlState2 };
27+
28+
typedef int __attribute__((availability(swift, unavailable))) UITableViewCellStateMask;
29+
enum : UITableViewCellStateMask { UITableViewCellStateMask1, UITableViewCellStateMask2 };
30+
31+
@interface TestsForEnhancedOmitNeedlessWords
32+
- (void)differenceFromArray:(int)other withOptions:(NSOrderedCollectionDifferenceCalculationOptions)options ;
33+
- (unsigned)minimumRangeOfUnit:(NSCalendarUnit)unit;
34+
- (unsigned)URLForDirectory:(unsigned)directory inDomain:(NSSearchPathDomainMask)domain ;
35+
- (unsigned)layoutManager:(unsigned)layoutManager shouldUseAction:(NSControlCharacterAction)action ;
36+
- (void)setBackButtonBackgroundImage:(unsigned)backgroundImage forState:(UIControlState)state ;
37+
- (void)willTransitionToState:(UITableViewCellStateMask)state ;
38+
@end

test/Interop/Cxx/enum/c-enums-withOptions-omit.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,53 @@ import CenumsWithOptionsOmit
77
// CHECK-NEXT: class func enumerateObjects(options
88
// CHECK-NEXT: func enumerateObjects(options
99
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "enumerateObjects(options:)")
10+
11+
// CHECK: class TestsForEnhancedOmitNeedlessWords {
12+
13+
// Tests for withOptions -> 'with options'
14+
// CHECK-NEXT: class func difference(fromArray other: Int32, with options: NSOrderedCollectionDifferenceCalculationOptions = [])
15+
// CHECK-NEXT: func difference(fromArray other: Int32, with options: NSOrderedCollectionDifferenceCalculationOptions = [])
16+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "difference(fromArray:with:)")
17+
// CHECK-NEXT: class func differenceFromArray(_ other: Int32, withOptions options: NSOrderedCollectionDifferenceCalculationOptions = [])
18+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "difference(fromArray:with:)")
19+
// CHECK-NEXT: func differenceFromArray(_ other: Int32, withOptions options: NSOrderedCollectionDifferenceCalculationOptions = [])
20+
21+
// Tests for ofUnit -> 'of unit'
22+
// CHECK-NEXT: class func minimumRange(of unit: NSCalendarUnit) -> UInt32
23+
// CHECK-NEXT: func minimumRange(of unit: NSCalendarUnit) -> UInt32
24+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "minimumRange(of:)")
25+
// CHECK-NEXT: class func minimumRangeOfUnit(_ unit: NSCalendarUnit) -> UInt32
26+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "minimumRange(of:)")
27+
// CHECK-NEXT: func minimumRangeOfUnit(_ unit: NSCalendarUnit) -> UInt32
28+
29+
// Tests for inDomain -> 'in domain'
30+
// CHECK-NEXT: class func url(forDirectory directory: UInt32, in domain: NSSearchPathDomainMask) -> UInt32
31+
// CHECK-NEXT: func url(forDirectory directory: UInt32, in domain: NSSearchPathDomainMask) -> UInt32
32+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "url(forDirectory:in:)")
33+
// CHECK-NEXT: class func URLForDirectory(_ directory: UInt32, inDomain domain: NSSearchPathDomainMask) -> UInt32
34+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "url(forDirectory:in:)")
35+
// CHECK-NEXT: func URLForDirectory(_ directory: UInt32, inDomain domain: NSSearchPathDomainMask) -> UInt32
36+
37+
// Tests for shouldUseAction -> 'shouldUse action'
38+
// CHECK-NEXT: class func layoutManager(_ layoutManager: UInt32, shouldUse action: NSControlCharacterAction) -> UInt32
39+
// CHECK-NEXT: func layoutManager(_ layoutManager: UInt32, shouldUse action: NSControlCharacterAction) -> UInt32
40+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "layoutManager(_:shouldUse:)")
41+
// CHECK-NEXT: class func layoutManager(_ layoutManager: UInt32, shouldUseAction action: NSControlCharacterAction) -> UInt32
42+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "layoutManager(_:shouldUse:)")
43+
// CHECK-NEXT: func layoutManager(_ layoutManager: UInt32, shouldUseAction action: NSControlCharacterAction) -> UInt32
44+
45+
// Tests for forState -> 'for state'
46+
// CHECK-NEXT: class func setBackButtonBackgroundImage(_ backgroundImage: UInt32, for state: UIControlState)
47+
// CHECK-NEXT: func setBackButtonBackgroundImage(_ backgroundImage: UInt32, for state: UIControlState)
48+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "setBackButtonBackgroundImage(_:for:)")
49+
// CHECK-NEXT: class func setBackButtonBackgroundImage(_ backgroundImage: UInt32, forState state: UIControlState)
50+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "setBackButtonBackgroundImage(_:for:)")
51+
// CHECK-NEXT: func setBackButtonBackgroundImage(_ backgroundImage: UInt32, forState state: UIControlState)
52+
53+
// Tests for toState -> 'to state'
54+
// CHECK-NEXT: class func willTransition(to state: UITableViewCellStateMask)
55+
// CHECK-NEXT: func willTransition(to state: UITableViewCellStateMask)
56+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "willTransition(to:)")
57+
// CHECK-NEXT: class func willTransitionToState(_ state: UITableViewCellStateMask)
58+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "willTransition(to:)")
59+
// CHECK-NEXT: func willTransitionToState(_ state: UITableViewCellStateMask)

0 commit comments

Comments
 (0)