Skip to content

Commit 2ea58f9

Browse files
committed
Clang importer: handle CF type renaming in importFullName.
Ensures that the Swift lookup tables get transformed name for imported CF types, including original name (which is still available). Otherwise, this is an NFC refactoring that gets the last of the naming tricks into importFullName.
1 parent 50eea9c commit 2ea58f9

File tree

7 files changed

+145
-53
lines changed

7 files changed

+145
-53
lines changed

lib/Basic/StringExtras.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,18 @@ static bool isKeyword(StringRef identifier) {
309309
static Optional<StringRef> skipTypeSuffix(StringRef typeName) {
310310
if (typeName.empty()) return None;
311311

312+
auto lastWord = camel_case::getLastWord(typeName);
313+
312314
// "Type" suffix.
313-
if (camel_case::getLastWord(typeName) == "Type" &&
314-
typeName.size() > 4) {
315+
if (lastWord == "Type" && typeName.size() > 4) {
315316
return typeName.drop_back(4);
316317
}
317318

319+
// "Ref" suffix.
320+
if (lastWord == "Ref" && typeName.size() > 3) {
321+
return typeName.drop_back(3);
322+
}
323+
318324
// \d+D for dimensionality.
319325
if (typeName.back() == 'D' && typeName.size() > 1) {
320326
unsigned firstDigit = typeName.size() - 1;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,12 @@ void ClangImporter::Implementation::addEntryToLookupTable(
703703
if (!suppressDecl) {
704704
// If we have a name to import as, add this entry to the table.
705705
clang::DeclContext *effectiveContext;
706-
if (DeclName name = importFullName(named, None, &effectiveContext)) {
707-
table.addEntry(name, named, effectiveContext);
706+
if (auto importedName = importFullName(named, None, &effectiveContext)) {
707+
table.addEntry(importedName.Imported, named, effectiveContext);
708+
709+
// Also add the alias, if needed.
710+
if (importedName.Alias)
711+
table.addEntry(importedName.Alias, named, effectiveContext);
708712
}
709713
}
710714

@@ -2321,6 +2325,19 @@ auto ClangImporter::Implementation::importFullName(
23212325
}
23222326
}
23232327

2328+
// Typedef declarations might be CF types that will drop the "Ref"
2329+
// suffix.
2330+
bool aliasIsFunction = false;
2331+
bool aliasIsInitializer = false;
2332+
StringRef aliasBaseName;
2333+
SmallVector<StringRef, 4> aliasArgumentNames;
2334+
if (auto typedefNameDecl = dyn_cast<clang::TypedefNameDecl>(D)) {
2335+
auto swiftName = getCFTypeName(typedefNameDecl, &aliasBaseName);
2336+
if (!swiftName.empty()) {
2337+
baseName = swiftName;
2338+
}
2339+
}
2340+
23242341
// Local function to determine whether the given declaration is subject to
23252342
// a swift_private attribute.
23262343
auto hasSwiftPrivate = [this](const clang::NamedDecl *D) {
@@ -2398,32 +2415,58 @@ auto ClangImporter::Implementation::importFullName(
23982415
// If this declaration has the swift_private attribute, prepend "__" to the
23992416
// appropriate place.
24002417
SmallString<16> swiftPrivateScratch;
2418+
SmallString<16> swiftPrivateAliasScratch;
24012419
if (hasSwiftPrivate(D)) {
2402-
swiftPrivateScratch = "__";
2420+
// Make the given name private.
2421+
//
2422+
// Returns true if this is not possible.
2423+
auto makeNamePrivate = [](bool isInitializer,
2424+
StringRef &baseName,
2425+
SmallVectorImpl<StringRef> &argumentNames,
2426+
CtorInitializerKind initKind,
2427+
SmallString<16> &scratch) -> bool {
2428+
scratch = "__";
2429+
2430+
if (isInitializer) {
2431+
// For initializers, prepend "__" to the first argument name.
2432+
if (argumentNames.empty()) {
2433+
// FIXME: ... unless it was from a factory method, for historical
2434+
// reasons.
2435+
if (initKind == CtorInitializerKind::Factory ||
2436+
initKind == CtorInitializerKind::ConvenienceFactory)
2437+
return true;
24032438

2404-
if (isInitializer) {
2405-
// For initializers, prepend "__" to the first argument name.
2406-
if (argumentNames.empty()) {
2407-
// FIXME: ... unless it was from a factory method, for historical
2408-
// reasons.
2409-
if (result.InitKind == CtorInitializerKind::Factory ||
2410-
result.InitKind == CtorInitializerKind::ConvenienceFactory)
2411-
return result;
2412-
2413-
// FIXME: Record that we did this.
2414-
argumentNames.push_back("__");
2439+
// FIXME: Record that we did this.
2440+
argumentNames.push_back("__");
2441+
} else {
2442+
scratch += argumentNames[0];
2443+
argumentNames[0] = scratch;
2444+
}
24152445
} else {
2416-
swiftPrivateScratch += argumentNames[0];
2417-
argumentNames[0] = swiftPrivateScratch;
2446+
// For all other entities, prepend "__" to the base name.
2447+
scratch += baseName;
2448+
baseName = scratch;
24182449
}
2419-
} else {
2420-
// For all other entities, prepend "__" to the base name.
2421-
swiftPrivateScratch += baseName;
2422-
baseName = swiftPrivateScratch;
2450+
2451+
return false;
2452+
};
2453+
2454+
// Make the name private.
2455+
if (makeNamePrivate(isInitializer, baseName, argumentNames,
2456+
result.InitKind, swiftPrivateScratch))
2457+
return result;
2458+
2459+
// If we have an alias name, make it private as well.
2460+
if (!aliasBaseName.empty()) {
2461+
(void)makeNamePrivate(aliasIsInitializer, aliasBaseName,
2462+
aliasArgumentNames, CtorInitializerKind::Designated,
2463+
swiftPrivateAliasScratch);
24232464
}
24242465
}
24252466

24262467
result.Imported = formDeclName(baseName, argumentNames, isFunction);
2468+
result.Alias = formDeclName(aliasBaseName, aliasArgumentNames,
2469+
aliasIsFunction);
24272470
return result;
24282471
}
24292472

lib/ClangImporter/ImportDecl.cpp

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,15 +1181,34 @@ static StringRef getImportedCFTypeName(StringRef name) {
11811181

11821182
bool ClangImporter::Implementation::isCFTypeDecl(
11831183
const clang::TypedefNameDecl *Decl) {
1184-
if (auto pointee = CFPointeeInfo::classifyTypedef(Decl))
1185-
return pointee.isValid();
1184+
if (CFPointeeInfo::classifyTypedef(Decl))
1185+
return true;
11861186
return false;
11871187
}
11881188

11891189
StringRef ClangImporter::Implementation::getCFTypeName(
1190-
const clang::TypedefNameDecl *decl) {
1191-
if (isCFTypeDecl(decl))
1192-
return getImportedCFTypeName(decl->getName());
1190+
const clang::TypedefNameDecl *decl,
1191+
StringRef *secondaryName) {
1192+
if (secondaryName) *secondaryName = "";
1193+
1194+
if (auto pointee = CFPointeeInfo::classifyTypedef(decl)) {
1195+
auto name = decl->getName();
1196+
if (pointee.isRecord()) {
1197+
auto resultName = getImportedCFTypeName(name);
1198+
if (secondaryName && name != resultName)
1199+
*secondaryName = name;
1200+
1201+
return resultName;
1202+
}
1203+
1204+
if (pointee.isTypedef() && secondaryName) {
1205+
StringRef otherName = getImportedCFTypeName(name);
1206+
if (otherName != name)
1207+
*secondaryName = otherName;
1208+
}
1209+
1210+
return name;
1211+
}
11931212

11941213
return "";
11951214
}
@@ -1364,11 +1383,7 @@ namespace {
13641383
}
13651384

13661385
Type importCFClassType(const clang::TypedefNameDecl *decl,
1367-
StringRef name, CFPointeeInfo info) {
1368-
// If the name ends in 'Ref', drop that from the imported class name.
1369-
StringRef nameWithoutRef = getImportedCFTypeName(name);
1370-
Identifier className = Impl.SwiftContext.getIdentifier(nameWithoutRef);
1371-
1386+
Identifier className, CFPointeeInfo info) {
13721387
auto dc = Impl.importDeclContextOf(decl);
13731388
if (!dc) return Type();
13741389

@@ -1426,7 +1441,8 @@ namespace {
14261441
}
14271442

14281443
Decl *VisitTypedefNameDecl(const clang::TypedefNameDecl *Decl) {
1429-
auto Name = Impl.importFullName(Decl).Imported.getBaseName();
1444+
auto importedName = Impl.importFullName(Decl);
1445+
auto Name = importedName.Imported.getBaseName();
14301446
if (Name.empty())
14311447
return nullptr;
14321448

@@ -1448,10 +1464,15 @@ namespace {
14481464
if (auto pointee = CFPointeeInfo::classifyTypedef(Decl)) {
14491465
// If the pointee is a record, consider creating a class type.
14501466
if (pointee.isRecord()) {
1451-
SwiftType = importCFClassType(Decl, Name.str(), pointee);
1467+
SwiftType = importCFClassType(Decl, Name, pointee);
14521468
if (!SwiftType) return nullptr;
14531469
NameMapping = MappedTypeNameKind::DefineOnly;
14541470

1471+
// If there is an alias (i.e., that doesn't have "Ref"),
1472+
// use that as the name of the typedef later.
1473+
if (importedName.Alias)
1474+
Name = importedName.Alias.getBaseName();
1475+
14551476
// If the pointee is another CF typedef, create an extra typealias
14561477
// for the name without "Ref", but not a separate type.
14571478
} else if (pointee.isTypedef()) {
@@ -1460,7 +1481,6 @@ namespace {
14601481
if (!underlying)
14611482
return nullptr;
14621483

1463-
// Remove one level of "Ref" from the typealias.
14641484
if (auto typealias = dyn_cast<TypeAliasDecl>(underlying)) {
14651485
Type doublyUnderlyingTy = typealias->getUnderlyingType();
14661486
if (isa<NameAliasType>(doublyUnderlyingTy.getPointer()))
@@ -1473,20 +1493,24 @@ namespace {
14731493
if (!DC)
14741494
return nullptr;
14751495

1476-
StringRef nameWithoutRef = getImportedCFTypeName(Name.str());
1477-
Identifier idWithoutRef =
1478-
Impl.SwiftContext.getIdentifier(nameWithoutRef);
1479-
auto aliasWithoutRef =
1480-
Impl.createDeclWithClangNode<TypeAliasDecl>(Decl,
1481-
Impl.importSourceLoc(Decl->getLocStart()),
1482-
idWithoutRef,
1483-
Impl.importSourceLoc(Decl->getLocation()),
1484-
TypeLoc::withoutLoc(SwiftType),
1485-
DC);
1486-
1487-
aliasWithoutRef->computeType();
1488-
SwiftType = aliasWithoutRef->getDeclaredType();
1489-
NameMapping = MappedTypeNameKind::DefineOnly;
1496+
// If there is an alias (i.e., that doesn't have "Ref"),
1497+
// create that separate typedef.
1498+
if (importedName.Alias) {
1499+
auto aliasWithoutRef =
1500+
Impl.createDeclWithClangNode<TypeAliasDecl>(
1501+
Decl,
1502+
Impl.importSourceLoc(Decl->getLocStart()),
1503+
importedName.Alias.getBaseName(),
1504+
Impl.importSourceLoc(Decl->getLocation()),
1505+
TypeLoc::withoutLoc(SwiftType),
1506+
DC);
1507+
1508+
aliasWithoutRef->computeType();
1509+
SwiftType = aliasWithoutRef->getDeclaredType();
1510+
NameMapping = MappedTypeNameKind::DefineOnly;
1511+
} else {
1512+
NameMapping = MappedTypeNameKind::DefineAndUse;
1513+
}
14901514

14911515
// If the pointee is 'const void',
14921516
// 'CFTypeRef', bring it in specifically as AnyObject.

lib/ClangImporter/ImportType.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,9 +1967,8 @@ Type ClangImporter::Implementation::importMethodType(
19671967
allowNSUIntegerAsIntInResult,
19681968
/*isFullyBridgeable*/true,
19691969
OptionalityOfReturn);
1970-
19711970
// Adjust the result type for a throwing function.
1972-
if (errorInfo) {
1971+
if (swiftResultTy && errorInfo) {
19731972
origSwiftResultTy = swiftResultTy->getCanonicalType();
19741973
swiftResultTy = adjustResultTypeForThrowingFunction(*errorInfo,
19751974
swiftResultTy);

lib/ClangImporter/ImporterImpl.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
724724

725725
/// Determine the imported CF type for the given typedef-name, or the empty
726726
/// string if this is not an imported CF type name.
727-
StringRef getCFTypeName(const clang::TypedefNameDecl *decl);
727+
StringRef getCFTypeName(const clang::TypedefNameDecl *decl,
728+
StringRef *secondaryName = nullptr);
728729

729730
/// Retrieve the type name of a Clang type for the purposes of
730731
/// omitting unneeded words.
@@ -765,6 +766,10 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
765766
/// The imported name.
766767
DeclName Imported;
767768

769+
/// An additional alias to the imported name, which should be
770+
/// recorded in name lookup tables as well.
771+
DeclName Alias;
772+
768773
/// Whether this name was explicitly specified via a Clang
769774
/// swift_name attribute.
770775
bool HasCustomName = false;
@@ -775,7 +780,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
775780
bool DroppedVariadic = false;
776781

777782
/// For an initializer, the kind of initializer to import.
778-
CtorInitializerKind InitKind;
783+
CtorInitializerKind InitKind = CtorInitializerKind::Designated;
779784

780785
/// For names that map Objective-C error handling conventions into
781786
/// throwing Swift methods, describes how the mapping is performed.

test/IDE/Inputs/swift_name_objc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,6 @@ SWIFT_NAME(SomeProtocol)
6363
- (nullable instancetype)initAndReturnError:(NSError **)error;
6464
- (nullable instancetype)initWithFloat:(float)value error:(NSError **)error;
6565
@end
66+
67+
typedef const void *CFTypeRef __attribute__((objc_bridge(id)));
68+
typedef const struct __attribute__((objc_bridge(id))) __CCItem *CCItemRef;

test/IDE/dump_swift_lookup_tables_objc.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// REQUIRES: objc_interop
88

99
// CHECK: Base -> full name mappings:
10+
// CHECK-NEXT: CCItem --> CCItem
11+
// CHECK-NEXT: CCItemRef --> CCItemRef
12+
// CHECK-NEXT: CFTypeRef --> CFTypeRef
1013
// CHECK-NEXT: NSAccessibility --> NSAccessibility
1114
// CHECK-NEXT: NSError --> NSError
1215
// CHECK-NEXT: NSErrorImports --> NSErrorImports
@@ -15,6 +18,7 @@
1518
// CHECK-NEXT: SomeClass --> SomeClass
1619
// CHECK-NEXT: SomeProtocol --> SomeProtocol
1720
// CHECK-NEXT: UIActionSheet --> UIActionSheet
21+
// CHECK-NEXT: __CCItem --> __CCItem
1822
// CHECK-NEXT: accessibilityFloat --> accessibilityFloat()
1923
// CHECK-NEXT: categoryMethodWithX --> categoryMethodWithX(_:y:), categoryMethodWithX(_:y:z:)
2024
// CHECK-NEXT: doubleProperty --> doubleProperty{{$}}
@@ -28,6 +32,12 @@
2832
// CHECK-NEXT: setAccessibilityFloat --> setAccessibilityFloat(_:)
2933

3034
// CHECK: Full name -> entry mappings:
35+
// CHECK-NEXT: CCItem:
36+
// CHECK-NEXT: TU: CCItemRef
37+
// CHECK-NEXT: CCItemRef:
38+
// CHECK-NEXT: TU: CCItemRef
39+
// CHECK-NEXT: CFTypeRef:
40+
// CHECK-NEXT: TU: CFTypeRef
3141
// CHECK-NEXT: NSAccessibility:
3242
// CHECK-NEXT: TU: NSAccessibility{{$}}
3343
// CHECK-NEXT: NSError:
@@ -44,6 +54,8 @@
4454
// CHECK-NEXT: TU: SNSomeProtocol
4555
// CHECK-NEXT: UIActionSheet:
4656
// CHECK-NEXT: TU: UIActionSheet
57+
// CHECK-NEXT: __CCItem:
58+
// CHECK-NEXT: TU: __CCItem
4759
// CHECK-NEXT: accessibilityFloat():
4860
// CHECK-NEXT: NSAccessibility: -[NSAccessibility accessibilityFloat]
4961
// CHECK-NEXT: categoryMethodWithX(_:y:):

0 commit comments

Comments
 (0)