@@ -86,6 +86,30 @@ static Pattern *createTypedNamedPattern(VarDecl *decl) {
86
86
return P;
87
87
}
88
88
89
+ // / Create a var member for this struct, along with its pattern binding, and add
90
+ // / it as a member
91
+ static std::pair<VarDecl *, PatternBindingDecl *>
92
+ createVarWithPattern (ASTContext &cxt, DeclContext *dc, Identifier name, Type ty,
93
+ bool isLet, bool isImplicit,
94
+ Accessibility setterAccessibility) {
95
+ // Create a variable to store the underlying value.
96
+ auto var = new (cxt) VarDecl (
97
+ /* static*/ false ,
98
+ /* IsLet*/ isLet, SourceLoc (), name, ty, dc);
99
+ if (isImplicit)
100
+ var->setImplicit ();
101
+ var->setAccessibility (Accessibility::Public);
102
+ var->setSetterAccessibility (setterAccessibility);
103
+
104
+ // Create a pattern binding to describe the variable.
105
+ Pattern *varPattern = createTypedNamedPattern (var);
106
+ auto patternBinding =
107
+ PatternBindingDecl::create (cxt, SourceLoc (), StaticSpellingKind::None,
108
+ SourceLoc (), varPattern, nullptr , dc);
109
+
110
+ return {var, patternBinding};
111
+ }
112
+
89
113
#ifndef NDEBUG
90
114
static bool verifyNameMapping (MappedTypeNameKind NameMapping,
91
115
StringRef left, StringRef right) {
@@ -1286,11 +1310,6 @@ namespace {
1286
1310
// For now, fall through and treat as a struct
1287
1311
case clang::SwiftNewtypeAttr::NK_Struct: {
1288
1312
1289
- auto underlyingType = Impl.importType (
1290
- Decl->getUnderlyingType (), ImportTypeKind::Typedef,
1291
- isInSystemModule (DC),
1292
- Decl->getUnderlyingType ()->isBlockPointerType ());
1293
-
1294
1313
auto &cxt = Impl.SwiftContext ;
1295
1314
auto Loc = Impl.importSourceLoc (Decl->getLocation ());
1296
1315
@@ -1301,9 +1320,33 @@ namespace {
1301
1320
ProtocolDecl *protocols[] = {
1302
1321
cxt.getProtocol (KnownProtocolKind::RawRepresentable),
1303
1322
};
1304
- makeStructRawValued (structDecl, underlyingType,
1305
- {KnownProtocolKind::RawRepresentable},
1306
- protocols);
1323
+
1324
+ // Import the type of the underlying storage
1325
+ auto storedUnderlyingType = Impl.importType (
1326
+ Decl->getUnderlyingType (), ImportTypeKind::Value,
1327
+ isInSystemModule (DC),
1328
+ Decl->getUnderlyingType ()->isBlockPointerType ());
1329
+
1330
+ // Find a bridged type, which may be different
1331
+ auto computedPropertyUnderlyingType = Impl.importType (
1332
+ Decl->getUnderlyingType (), ImportTypeKind::Property,
1333
+ isInSystemModule (DC),
1334
+ Decl->getUnderlyingType ()->isBlockPointerType ());
1335
+
1336
+ if (storedUnderlyingType.getCanonicalTypeOrNull () ==
1337
+ computedPropertyUnderlyingType.getCanonicalTypeOrNull ()) {
1338
+ // Simple, our stored type is already bridged
1339
+ makeStructRawValued (structDecl, storedUnderlyingType,
1340
+ {KnownProtocolKind::RawRepresentable},
1341
+ protocols);
1342
+ } else {
1343
+ // We need to make a stored rawValue or storage type, and a
1344
+ // computed one of bridged type.
1345
+ makeStructRawValuedWithBridge (
1346
+ structDecl, storedUnderlyingType,
1347
+ computedPropertyUnderlyingType,
1348
+ {KnownProtocolKind::RawRepresentable}, protocols);
1349
+ }
1307
1350
1308
1351
Impl.ImportedDecls [Decl->getCanonicalDecl ()] = structDecl;
1309
1352
Impl.registerExternalDecl (structDecl);
@@ -1445,28 +1488,15 @@ namespace {
1445
1488
bool makeUnlabeledValueInit = false,
1446
1489
bool isImplicit = true) {
1447
1490
auto &cxt = Impl.SwiftContext ;
1448
- populateInheritedTypes (structDecl, protocols);
1449
-
1450
- // Note synthesized protocols
1451
- for (auto kind : synthesizedProtocolAttrs)
1452
- structDecl->getAttrs ().add (new (cxt) SynthesizedProtocolAttr (kind));
1491
+ addProtocolsToStruct (structDecl, synthesizedProtocolAttrs, protocols);
1453
1492
1454
1493
// Create a variable to store the underlying value.
1455
- auto varName = cxt.Id_rawValue ;
1456
- auto var = new (cxt) VarDecl (
1457
- /* static*/ false ,
1458
- /* IsLet*/ isLet, SourceLoc (), varName, underlyingType, structDecl);
1459
- if (isImplicit)
1460
- var->setImplicit ();
1461
- var->setAccessibility (Accessibility::Public);
1462
- var->setSetterAccessibility (setterAccessibility);
1494
+ VarDecl *var;
1495
+ PatternBindingDecl *patternBinding;
1496
+ std::tie (var, patternBinding) =
1497
+ createVarWithPattern (cxt, structDecl, cxt.Id_rawValue , underlyingType,
1498
+ isLet, isImplicit, setterAccessibility);
1463
1499
1464
- // Create a pattern binding to describe the variable.
1465
- Pattern *varPattern = createTypedNamedPattern (var);
1466
-
1467
- auto patternBinding = PatternBindingDecl::create (
1468
- cxt, SourceLoc (), StaticSpellingKind::None, SourceLoc (), varPattern,
1469
- nullptr , structDecl);
1470
1500
structDecl->setHasDelayedMembers ();
1471
1501
1472
1502
// Create constructors to initialize that value from a value of the
@@ -1480,11 +1510,101 @@ namespace {
1480
1510
createValueConstructor (structDecl, var,
1481
1511
/* wantCtorParamNames=*/ true ,
1482
1512
/* wantBody=*/ !Impl.hasFinishedTypeChecking ()));
1483
-
1484
1513
structDecl->addMember (patternBinding);
1485
1514
structDecl->addMember (var);
1486
1515
}
1487
1516
1517
+ // / Make a struct declaration into a raw-value-backed struct, with
1518
+ // / bridged computed rawValue property which differs from stored backing
1519
+ // /
1520
+ // / \param structDecl the struct to make a raw value for
1521
+ // / \param storedUnderlyingType the type of the stored raw value
1522
+ // / \param bridgedType the type of the 'rawValue' computed property bridge
1523
+ // / \param synthesizedProtocolAttrs synthesized protocol attributes to add
1524
+ // / \param protocols the protocols to make this struct conform to
1525
+ // /
1526
+ // / This will perform most of the work involved in making a new Swift struct
1527
+ // / be backed by a stored raw value and computed raw value of bridged type.
1528
+ // / This will populated derived protocols and synthesized protocols, add the
1529
+ // / new variable and pattern bindings, and create the inits parameterized
1530
+ // / over a bridged type that will cast to the stored type, as appropriate.
1531
+ // /
1532
+ template <unsigned N> void makeStructRawValuedWithBridge (
1533
+ StructDecl *structDecl,
1534
+ Type storedUnderlyingType,
1535
+ Type bridgedType,
1536
+ ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1537
+ ProtocolDecl *const (&protocols)[N]) {
1538
+ auto &cxt = Impl.SwiftContext ;
1539
+ addProtocolsToStruct (structDecl, synthesizedProtocolAttrs,
1540
+ protocols);
1541
+
1542
+ auto storedVarName = cxt.getIdentifier (" _rawValue" );
1543
+ auto computedVarName = cxt.Id_rawValue ;
1544
+
1545
+ // Create a variable to store the underlying value.
1546
+ VarDecl *storedVar;
1547
+ PatternBindingDecl *storedPatternBinding;
1548
+ std::tie (storedVar, storedPatternBinding) = createVarWithPattern (
1549
+ cxt, structDecl, storedVarName, storedUnderlyingType, /* isLet=*/ false ,
1550
+ /* isImplicit=*/ true , Accessibility::Private);
1551
+
1552
+ //
1553
+ // Create a computed value variable
1554
+ auto dre = new (cxt) DeclRefExpr (
1555
+ storedVar, {}, true , AccessSemantics::Ordinary, storedUnderlyingType);
1556
+ auto coerce = new (cxt)
1557
+ CoerceExpr (dre, {}, {nullptr , bridgedType});
1558
+ auto computedVar = cast<VarDecl>(Impl.createConstant (
1559
+ computedVarName, structDecl, bridgedType, coerce,
1560
+ ConstantConvertKind::Coerce, false , {}));
1561
+ computedVar->setImplicit ();
1562
+ computedVar->setAccessibility (Accessibility::Public);
1563
+
1564
+ // Create a pattern binding to describe the variable.
1565
+
1566
+ Pattern *computedVarPattern = createTypedNamedPattern (computedVar);
1567
+ auto computedPatternBinding = PatternBindingDecl::create (
1568
+ cxt, SourceLoc (), StaticSpellingKind::None, SourceLoc (),
1569
+ computedVarPattern, nullptr , structDecl);
1570
+
1571
+ auto init = createValueConstructor (structDecl, computedVar,
1572
+ /* wantCtorParamNames=*/ true ,
1573
+ /* wantBody=*/ false );
1574
+ // Insert our custom init body
1575
+ if (!Impl.hasFinishedTypeChecking ()) {
1576
+ auto selfDecl = ParamDecl::createSelf (SourceLoc (), structDecl,
1577
+ /* static*/ false , /* inout*/ true );
1578
+ // Construct left-hand side.
1579
+ Expr *lhs = new (cxt) DeclRefExpr (selfDecl, DeclNameLoc (),
1580
+ /* Implicit=*/ true );
1581
+ lhs = new (cxt) MemberRefExpr (lhs, SourceLoc (), storedVar,
1582
+ DeclNameLoc (), /* Implicit=*/ true );
1583
+
1584
+ // Construct right-hand side.
1585
+ // FIXME: get the parameter from the init, and plug it in here.
1586
+ auto rhs = new (cxt)
1587
+ DeclRefExpr (init->getParameterList (1 )->get (0 ), DeclNameLoc (),
1588
+ /* Implicit=*/ true );
1589
+
1590
+ // Add assignment.
1591
+ auto assign = new (cxt) AssignExpr (lhs, SourceLoc (), rhs,
1592
+ /* Implicit=*/ true );
1593
+ auto body = BraceStmt::create (cxt, SourceLoc (), {assign}, SourceLoc ());
1594
+ init->setBody (body);
1595
+
1596
+ // We want to inline away as much of this as we can
1597
+ init->getAttrs ().add (new (cxt) TransparentAttr (/* implicit*/ true ));
1598
+ }
1599
+
1600
+ structDecl->setHasDelayedMembers ();
1601
+ structDecl->addMember (init);
1602
+ structDecl->addMember (storedPatternBinding);
1603
+ structDecl->addMember (storedVar);
1604
+ structDecl->addMember (computedPatternBinding);
1605
+ structDecl->addMember (computedVar);
1606
+ }
1607
+
1488
1608
// / \brief Create a constructor that initializes a struct from its members.
1489
1609
ConstructorDecl *createValueConstructor (StructDecl *structDecl,
1490
1610
ArrayRef<VarDecl *> members,
@@ -1711,6 +1831,20 @@ namespace {
1711
1831
nominal->setCheckedInheritanceClause ();
1712
1832
}
1713
1833
1834
+ // / Add protocol conformances and synthesized protocol attributes
1835
+ template <unsigned N>
1836
+ void
1837
+ addProtocolsToStruct (StructDecl *structDecl,
1838
+ ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1839
+ ProtocolDecl *const (&protocols)[N]) {
1840
+ populateInheritedTypes (structDecl, protocols);
1841
+
1842
+ // Note synthesized protocols
1843
+ for (auto kind : synthesizedProtocolAttrs)
1844
+ structDecl->getAttrs ().add (new (Impl.SwiftContext )
1845
+ SynthesizedProtocolAttr (kind));
1846
+ }
1847
+
1714
1848
NominalTypeDecl *importAsOptionSetType (DeclContext *dc,
1715
1849
Identifier name,
1716
1850
const clang::EnumDecl *decl) {
@@ -6200,9 +6334,14 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
6200
6334
ClangNode ClangN) {
6201
6335
auto &context = SwiftContext;
6202
6336
6203
- auto var = createDeclWithClangNode<VarDecl>(ClangN,
6204
- isStatic, /* IsLet*/ false ,
6205
- SourceLoc (), name, type, dc);
6337
+ VarDecl *var = nullptr ;
6338
+ if (ClangN) {
6339
+ var = createDeclWithClangNode<VarDecl>(ClangN, isStatic, /* IsLet*/ false ,
6340
+ SourceLoc (), name, type, dc);
6341
+ } else {
6342
+ var = new (SwiftContext)
6343
+ VarDecl (isStatic, /* IsLet*/ false , SourceLoc (), name, type, dc);
6344
+ }
6206
6345
6207
6346
// Form the argument patterns.
6208
6347
SmallVector<ParameterList*, 3 > getterArgs;
0 commit comments