@@ -1286,11 +1286,6 @@ namespace {
1286
1286
// For now, fall through and treat as a struct
1287
1287
case clang::SwiftNewtypeAttr::NK_Struct: {
1288
1288
1289
- auto underlyingType = Impl.importType (
1290
- Decl->getUnderlyingType (), ImportTypeKind::Typedef,
1291
- isInSystemModule (DC),
1292
- Decl->getUnderlyingType ()->isBlockPointerType ());
1293
-
1294
1289
auto &cxt = Impl.SwiftContext ;
1295
1290
auto Loc = Impl.importSourceLoc (Decl->getLocation ());
1296
1291
@@ -1301,9 +1296,33 @@ namespace {
1301
1296
ProtocolDecl *protocols[] = {
1302
1297
cxt.getProtocol (KnownProtocolKind::RawRepresentable),
1303
1298
};
1304
- makeStructRawValued (structDecl, underlyingType,
1305
- {KnownProtocolKind::RawRepresentable},
1306
- protocols);
1299
+
1300
+ // Import the type of the underlying storage
1301
+ auto storedUnderlyingType = Impl.importType (
1302
+ Decl->getUnderlyingType (), ImportTypeKind::Value,
1303
+ isInSystemModule (DC),
1304
+ Decl->getUnderlyingType ()->isBlockPointerType ());
1305
+
1306
+ // Find a bridged type, which may be different
1307
+ auto computedPropertyUnderlyingType = Impl.importType (
1308
+ Decl->getUnderlyingType (), ImportTypeKind::Property,
1309
+ isInSystemModule (DC),
1310
+ Decl->getUnderlyingType ()->isBlockPointerType ());
1311
+
1312
+ if (storedUnderlyingType.getCanonicalTypeOrNull () ==
1313
+ computedPropertyUnderlyingType.getCanonicalTypeOrNull ()) {
1314
+ // Simple, our stored type is already bridged
1315
+ makeStructRawValued (structDecl, storedUnderlyingType,
1316
+ {KnownProtocolKind::RawRepresentable},
1317
+ protocols);
1318
+ } else {
1319
+ // We need to make a stored rawValue or storage type, and a
1320
+ // computed one of bridged type.
1321
+ makeStructRawValuedWithBridge (
1322
+ structDecl, storedUnderlyingType,
1323
+ computedPropertyUnderlyingType,
1324
+ {KnownProtocolKind::RawRepresentable}, protocols);
1325
+ }
1307
1326
1308
1327
Impl.ImportedDecls [Decl->getCanonicalDecl ()] = structDecl;
1309
1328
Impl.registerExternalDecl (structDecl);
@@ -1485,6 +1504,112 @@ namespace {
1485
1504
structDecl->addMember (var);
1486
1505
}
1487
1506
1507
+ // / Make a struct declaration into a raw-value-backed struct, with
1508
+ // / bridged computed rawValue property which differs from stored backing
1509
+ // /
1510
+ // / \param structDecl the struct to make a raw value for
1511
+ // / \param storedUnderlyingType the type of the stored raw value
1512
+ // / \param bridgedType the type of the 'rawValue' computed property bridge
1513
+ // / \param synthesizedProtocolAttrs synthesized protocol attributes to add
1514
+ // / \param protocols the protocols to make this struct conform to
1515
+ // /
1516
+ // / This will perform most of the work involved in making a new Swift struct
1517
+ // / be backed by a stored raw value and computed raw value of bridged type.
1518
+ // / This will populated derived protocols and synthesized protocols, add the
1519
+ // / new variable and pattern bindings, and create the inits parameterized
1520
+ // / over a bridged type that will cast to the stored type, as appropriate.
1521
+ // /
1522
+ template <unsigned N> void makeStructRawValuedWithBridge (
1523
+ StructDecl *structDecl,
1524
+ Type storedUnderlyingType,
1525
+ Type bridgedType,
1526
+ ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1527
+ ProtocolDecl *const (&protocols)[N]) {
1528
+ auto &cxt = Impl.SwiftContext ;
1529
+ populateInheritedTypes (structDecl, protocols);
1530
+
1531
+ // Note synthesized protocols
1532
+ for (auto kind : synthesizedProtocolAttrs)
1533
+ structDecl->getAttrs ().add (new (cxt) SynthesizedProtocolAttr (kind));
1534
+
1535
+ auto storedVarName = cxt.getIdentifier (" _rawValue" );
1536
+ auto computedVarName = cxt.Id_rawValue ;
1537
+
1538
+ //
1539
+ // Create a variable to store the underlying value.
1540
+ auto storedVar = new (cxt) VarDecl (
1541
+ /* static*/ false ,
1542
+ /* IsLet*/ false , SourceLoc (), storedVarName, storedUnderlyingType,
1543
+ structDecl);
1544
+ storedVar->setImplicit ();
1545
+ storedVar->setAccessibility (Accessibility::Public);
1546
+ storedVar->setSetterAccessibility (Accessibility::Private);
1547
+
1548
+ // Create a pattern binding to describe the variable.
1549
+ Pattern *storedVarPattern = createTypedNamedPattern (storedVar);
1550
+ auto storedPatternBinding = PatternBindingDecl::create (
1551
+ cxt, SourceLoc (), StaticSpellingKind::None, SourceLoc (),
1552
+ storedVarPattern, nullptr , structDecl);
1553
+
1554
+ //
1555
+ // Create a computed value variable
1556
+ auto dre = new (cxt) DeclRefExpr (
1557
+ storedVar, {}, true , AccessSemantics::Ordinary, storedUnderlyingType);
1558
+ auto coerce = new (cxt)
1559
+ CoerceExpr (dre, {}, {nullptr , bridgedType});
1560
+ auto computedVar = cast<VarDecl>(Impl.createConstant (
1561
+ computedVarName, structDecl, bridgedType, coerce,
1562
+ ConstantConvertKind::Coerce, false , {}));
1563
+ computedVar->setImplicit ();
1564
+ computedVar->setAccessibility (Accessibility::Public);
1565
+
1566
+ // Create a pattern binding to describe the variable.
1567
+
1568
+ Pattern *computedVarPattern = createTypedNamedPattern (computedVar);
1569
+ auto computedPatternBinding = PatternBindingDecl::create (
1570
+ cxt, SourceLoc (), StaticSpellingKind::None, SourceLoc (),
1571
+ computedVarPattern, nullptr , structDecl);
1572
+
1573
+ auto init = createValueConstructor (structDecl, computedVar,
1574
+ /* wantCtorParamNames=*/ true ,
1575
+ /* wantBody=*/ false );
1576
+ // Insert our custom init body
1577
+ if (!Impl.hasFinishedTypeChecking ()) {
1578
+ auto selfDecl = ParamDecl::createSelf (SourceLoc (), structDecl,
1579
+ /* static*/ false , /* inout*/ true );
1580
+ // Construct left-hand side.
1581
+ Expr *lhs = new (cxt) DeclRefExpr (selfDecl, DeclNameLoc (),
1582
+ /* Implicit=*/ true );
1583
+ lhs = new (cxt) MemberRefExpr (lhs, SourceLoc (), storedVar,
1584
+ DeclNameLoc (), /* Implicit=*/ true );
1585
+
1586
+ // Construct right-hand side.
1587
+ // FIXME: get the parameter from the init, and plug it in here.
1588
+ auto rhs = new (cxt)
1589
+ DeclRefExpr (init->getParameterList (1 )->get (0 ), DeclNameLoc (),
1590
+ /* Implicit=*/ true );
1591
+
1592
+ // Add assignment.
1593
+ auto assign = new (cxt) AssignExpr (lhs, SourceLoc (), rhs,
1594
+ /* Implicit=*/ true );
1595
+ auto body = BraceStmt::create (cxt, SourceLoc (), {assign}, SourceLoc ());
1596
+ init->setBody (body);
1597
+
1598
+ // We want to inline away as much of this as we can
1599
+ init->getAttrs ().add (new (cxt) TransparentAttr (/* implicit*/ true ));
1600
+ }
1601
+
1602
+ // Create constructor for computed value
1603
+ structDecl->setHasDelayedMembers ();
1604
+
1605
+ structDecl->addMember (init);
1606
+
1607
+ structDecl->addMember (storedPatternBinding);
1608
+ structDecl->addMember (storedVar);
1609
+ structDecl->addMember (computedVar);
1610
+ structDecl->addMember (computedPatternBinding);
1611
+ }
1612
+
1488
1613
// / \brief Create a constructor that initializes a struct from its members.
1489
1614
ConstructorDecl *createValueConstructor (StructDecl *structDecl,
1490
1615
ArrayRef<VarDecl *> members,
@@ -6200,9 +6325,14 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
6200
6325
ClangNode ClangN) {
6201
6326
auto &context = SwiftContext;
6202
6327
6203
- auto var = createDeclWithClangNode<VarDecl>(ClangN,
6204
- isStatic, /* IsLet*/ false ,
6205
- SourceLoc (), name, type, dc);
6328
+ VarDecl *var = nullptr ;
6329
+ if (ClangN) {
6330
+ var = createDeclWithClangNode<VarDecl>(ClangN, isStatic, /* IsLet*/ false ,
6331
+ SourceLoc (), name, type, dc);
6332
+ } else {
6333
+ var = new (SwiftContext)
6334
+ VarDecl (isStatic, /* IsLet*/ false , SourceLoc (), name, type, dc);
6335
+ }
6206
6336
6207
6337
// Form the argument patterns.
6208
6338
SmallVector<ParameterList*, 3 > getterArgs;
0 commit comments