Skip to content

Commit b5d29b5

Browse files
committed
[swift_newtype] Also newtype up CF Ref types.
Code cleaup and generalization to also catch typedefs of CF reference types. Tests will be included in a subsequent commit, as this now exhibits a latent problem when interacting with Unmanaged.
1 parent fee9c2a commit b5d29b5

File tree

1 file changed

+109
-98
lines changed

1 file changed

+109
-98
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 109 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,104 @@ namespace {
13071307
return alias;
13081308
}
13091309

1310+
/// Create a swift_newtype struct corresponding to a typedef. Returns
1311+
/// nullptr if unable.
1312+
Decl *importSwiftNewtype(const clang::TypedefNameDecl *decl,
1313+
clang::SwiftNewtypeAttr *newtypeAttr,
1314+
DeclContext *dc, Identifier name) {
1315+
switch (newtypeAttr->getNewtypeKind()) {
1316+
case clang::SwiftNewtypeAttr::NK_Enum:
1317+
// TODO: import as closed enum instead
1318+
// For now, fall through and treat as a struct
1319+
case clang::SwiftNewtypeAttr::NK_Struct:
1320+
break;
1321+
// No other cases yet
1322+
}
1323+
1324+
auto &cxt = Impl.SwiftContext;
1325+
auto Loc = Impl.importSourceLoc(decl->getLocation());
1326+
1327+
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
1328+
decl, Loc, name, Loc, None, nullptr, dc);
1329+
structDecl->computeType();
1330+
1331+
// Import the type of the underlying storage
1332+
auto storedUnderlyingType = Impl.importType(
1333+
decl->getUnderlyingType(), ImportTypeKind::Value,
1334+
isInSystemModule(dc), decl->getUnderlyingType()->isBlockPointerType(),
1335+
OTK_None);
1336+
1337+
// Find a bridged type, which may be different
1338+
auto computedPropertyUnderlyingType = Impl.importType(
1339+
decl->getUnderlyingType(), ImportTypeKind::Property,
1340+
isInSystemModule(dc), decl->getUnderlyingType()->isBlockPointerType(),
1341+
OTK_None);
1342+
1343+
bool isBridged =
1344+
!storedUnderlyingType->isEqual(computedPropertyUnderlyingType);
1345+
1346+
// Determine the set of protocols to which the synthesized
1347+
// type will conform.
1348+
SmallVector<ProtocolDecl *, 4> protocols;
1349+
SmallVector<KnownProtocolKind, 4> synthesizedProtocols;
1350+
1351+
// Local function to add a known protocol.
1352+
auto addKnown = [&](KnownProtocolKind kind) {
1353+
if (auto proto = cxt.getProtocol(kind)) {
1354+
protocols.push_back(proto);
1355+
synthesizedProtocols.push_back(kind);
1356+
}
1357+
};
1358+
1359+
// Add conformances that are always available.
1360+
addKnown(KnownProtocolKind::RawRepresentable);
1361+
addKnown(KnownProtocolKind::SwiftNewtypeWrapper);
1362+
1363+
// Local function to add a known protocol only when the
1364+
// underlying type conforms to it.
1365+
auto computedNominal = computedPropertyUnderlyingType->getAnyNominal();
1366+
auto transferKnown = [&](KnownProtocolKind kind) {
1367+
if (!computedNominal)
1368+
return;
1369+
1370+
auto proto = cxt.getProtocol(kind);
1371+
if (!proto)
1372+
return;
1373+
1374+
SmallVector<ProtocolConformance *, 1> conformances;
1375+
if (computedNominal->lookupConformance(
1376+
computedNominal->getParentModule(), proto, conformances)) {
1377+
protocols.push_back(proto);
1378+
synthesizedProtocols.push_back(kind);
1379+
}
1380+
};
1381+
1382+
// Transfer conformances. Each of these needs a forwarding
1383+
// implementation in the standard library.
1384+
transferKnown(KnownProtocolKind::Equatable);
1385+
transferKnown(KnownProtocolKind::Hashable);
1386+
transferKnown(KnownProtocolKind::Comparable);
1387+
transferKnown(KnownProtocolKind::ObjectiveCBridgeable);
1388+
1389+
if (!isBridged) {
1390+
// Simple, our stored type is equivalent to our computed
1391+
// type.
1392+
makeStructRawValued(structDecl, storedUnderlyingType,
1393+
synthesizedProtocols, protocols);
1394+
} else {
1395+
// We need to make a stored rawValue or storage type, and a
1396+
// computed one of bridged type.
1397+
makeStructRawValuedWithBridge(structDecl, storedUnderlyingType,
1398+
computedPropertyUnderlyingType,
1399+
synthesizedProtocols, protocols);
1400+
}
1401+
1402+
Impl.ImportedDecls[{decl->getCanonicalDecl(), useSwift2Name}] =
1403+
structDecl;
1404+
Impl.registerExternalDecl(structDecl);
1405+
return structDecl;
1406+
}
1407+
13101408
Decl *VisitTypedefNameDecl(const clang::TypedefNameDecl *Decl) {
13111409
Optional<ImportedName> swift3Name;
13121410
auto importedName = importFullName(Decl, swift3Name);
@@ -1390,6 +1488,13 @@ namespace {
13901488
if (!underlying)
13911489
return nullptr;
13921490

1491+
// Check for a newtype
1492+
if (auto newtypeAttr =
1493+
Impl.getSwiftNewtypeAttr(Decl, useSwift2Name))
1494+
if (auto newtype =
1495+
importSwiftNewtype(Decl, newtypeAttr, DC, Name))
1496+
return newtype;
1497+
13931498
// Create a typealias for this CF typedef.
13941499
TypeAliasDecl *typealias = nullptr;
13951500
typealias = Impl.createDeclWithClangNode<TypeAliasDecl>(
@@ -1467,104 +1572,10 @@ namespace {
14671572
return nullptr;
14681573

14691574
// Check for swift_newtype
1470-
if (!SwiftType) {
1471-
if (auto newtypeAttr = Impl.getSwiftNewtypeAttr(Decl, useSwift2Name)) {
1472-
switch (newtypeAttr->getNewtypeKind()) {
1473-
case clang::SwiftNewtypeAttr::NK_Enum:
1474-
// TODO: import as closed enum instead
1475-
1476-
// For now, fall through and treat as a struct
1477-
case clang::SwiftNewtypeAttr::NK_Struct: {
1478-
1479-
auto &cxt = Impl.SwiftContext;
1480-
auto Loc = Impl.importSourceLoc(Decl->getLocation());
1481-
1482-
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
1483-
Decl, Loc, Name, Loc, None, nullptr, DC);
1484-
structDecl->computeType();
1485-
1486-
// Import the type of the underlying storage
1487-
auto storedUnderlyingType = Impl.importType(
1488-
Decl->getUnderlyingType(), ImportTypeKind::Value,
1489-
isInSystemModule(DC),
1490-
Decl->getUnderlyingType()->isBlockPointerType(),
1491-
OTK_None);
1492-
1493-
// Find a bridged type, which may be different
1494-
auto computedPropertyUnderlyingType = Impl.importType(
1495-
Decl->getUnderlyingType(), ImportTypeKind::Property,
1496-
isInSystemModule(DC),
1497-
Decl->getUnderlyingType()->isBlockPointerType(),
1498-
OTK_None);
1499-
1500-
bool isBridged =
1501-
!storedUnderlyingType->isEqual(computedPropertyUnderlyingType);
1502-
1503-
// Determine the set of protocols to which the synthesized
1504-
// type will conform.
1505-
SmallVector<ProtocolDecl *, 4> protocols;
1506-
SmallVector<KnownProtocolKind, 4> synthesizedProtocols;
1507-
1508-
// Local function to add a known protocol.
1509-
auto addKnown = [&](KnownProtocolKind kind) {
1510-
if (auto proto = cxt.getProtocol(kind)) {
1511-
protocols.push_back(proto);
1512-
synthesizedProtocols.push_back(kind);
1513-
}
1514-
};
1515-
1516-
// Add conformances that are always available.
1517-
addKnown(KnownProtocolKind::RawRepresentable);
1518-
addKnown(KnownProtocolKind::SwiftNewtypeWrapper);
1519-
1520-
// Local function to add a known protocol only when the
1521-
// underlying type conforms to it.
1522-
auto computedNominal =
1523-
computedPropertyUnderlyingType->getAnyNominal();
1524-
auto transferKnown = [&](KnownProtocolKind kind) {
1525-
if (!computedNominal) return;
1526-
1527-
auto proto = cxt.getProtocol(kind);
1528-
if (!proto) return;
1529-
1530-
SmallVector<ProtocolConformance *, 1> conformances;
1531-
if (computedNominal->lookupConformance(
1532-
computedNominal->getParentModule(), proto, conformances)) {
1533-
protocols.push_back(proto);
1534-
synthesizedProtocols.push_back(kind);
1535-
}
1536-
};
1537-
1538-
// Transfer conformances. Each of these needs a forwarding
1539-
// implementation in the standard library.
1540-
transferKnown(KnownProtocolKind::Equatable);
1541-
transferKnown(KnownProtocolKind::Hashable);
1542-
transferKnown(KnownProtocolKind::Comparable);
1543-
transferKnown(KnownProtocolKind::ObjectiveCBridgeable);
1544-
1545-
if (!isBridged) {
1546-
// Simple, our stored type is equivalent to our computed
1547-
// type.
1548-
makeStructRawValued(structDecl, storedUnderlyingType,
1549-
synthesizedProtocols, protocols);
1550-
} else {
1551-
// We need to make a stored rawValue or storage type, and a
1552-
// computed one of bridged type.
1553-
makeStructRawValuedWithBridge(
1554-
structDecl, storedUnderlyingType,
1555-
computedPropertyUnderlyingType,
1556-
synthesizedProtocols, protocols);
1557-
}
1558-
1559-
Impl.ImportedDecls[{Decl->getCanonicalDecl(), useSwift2Name}]
1560-
= structDecl;
1561-
Impl.registerExternalDecl(structDecl);
1562-
return structDecl;
1563-
}
1564-
}
1565-
1566-
}
1567-
}
1575+
if (!SwiftType)
1576+
if (auto newtypeAttr = Impl.getSwiftNewtypeAttr(Decl, useSwift2Name))
1577+
if (auto newtype = importSwiftNewtype(Decl, newtypeAttr, DC, Name))
1578+
return newtype;
15681579

15691580
if (!SwiftType) {
15701581
// Import typedefs of blocks as their fully-bridged equivalent Swift

0 commit comments

Comments
 (0)