Skip to content

Commit 6f93671

Browse files
committed
[c++-interop] Providing information about enum types from inferDefaultArgument
When ClangImporter::Implementation::inferDefaultArgument processes func/method arguments as part of omitNeedlessWordsInFunctionName it processes information about how the typenames for the parameters related to the parameter names to form a parameter names list. The parameter names list is used to determine if the argument label for a function should be clipped based on the typename. So for example a type like NSOrderedCollectionDifferenceCalculationOptions would cause a label ending with "Options" to get clipped so that for instance "withOptions" becomes simply "with". Unfortunately in the context of C++-Interop, the typename for the parameter often resolves to what the type backing the typedef or enum is and not the actual name of the typedef (so `typedef NSUInteger NSOrderedCollectionDifferenceCalculationOptions` resolves to a name of NSUInteger rather than NSOrderedCollectionDifferenceCalculationOptions). This patch seeks to collect a bit more information when processing NS_OPTIONS typedefs and providing that to the calling omitNeedlessWordsInFunctionName to handle more inteligently. In practice this fixes anywhere in Foundatio where `withOptions: NSOrderedCollectionDifferenceCalculationOptions` is used.
1 parent ec2c25d commit 6f93671

File tree

5 files changed

+70
-10
lines changed

5 files changed

+70
-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: 22 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,27 @@ 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;
24622480
}
24632481
}
24642482
}

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,

0 commit comments

Comments
 (0)