@@ -64,14 +64,35 @@ namespace inferred_attributes {
64
64
}
65
65
}
66
66
67
+ namespace {
68
+ enum class MakeStructRawValuedFlags {
69
+ // / whether to also create an unlabeled init
70
+ MakeUnlabeledValueInit = 0x01 ,
71
+
72
+ // / whether the raw value should be a let
73
+ IsLet = 0x02 ,
74
+
75
+ // / whether to mark the rawValue as implicit
76
+ IsImplicit = 0x04 ,
77
+ };
78
+ using MakeStructRawValuedOptions = OptionSet<MakeStructRawValuedFlags>;
79
+ }
80
+
81
+ static MakeStructRawValuedOptions
82
+ getDefaultMakeStructRawValuedOptions () {
83
+ MakeStructRawValuedOptions opts;
84
+ opts -= MakeStructRawValuedFlags::MakeUnlabeledValueInit; // default off
85
+ opts |= MakeStructRawValuedFlags::IsLet; // default on
86
+ opts |= MakeStructRawValuedFlags::IsImplicit; // default on
87
+ return opts;
88
+ }
67
89
68
90
static bool isInSystemModule (DeclContext *D) {
69
91
if (cast<ClangModuleUnit>(D->getModuleScopeContext ())->isSystemModule ())
70
92
return true ;
71
93
return false ;
72
94
}
73
95
74
-
75
96
// / Create a typedpattern(namedpattern(decl))
76
97
static Pattern *createTypedNamedPattern (VarDecl *decl) {
77
98
ASTContext &Ctx = decl->getASTContext ();
@@ -1328,11 +1349,20 @@ namespace {
1328
1349
Decl *importSwiftNewtype (const clang::TypedefNameDecl *decl,
1329
1350
clang::SwiftNewtypeAttr *newtypeAttr,
1330
1351
DeclContext *dc, Identifier name) {
1352
+ // The only (current) difference between swift_newtype(struct) and
1353
+ // swift_newtype(enum), until we can get real enum support, is that enums
1354
+ // have no un-labeld inits(). This is because enums are to be considered
1355
+ // closed, and if constructed from a rawValue, should be very explicit.
1356
+ bool unlabeledCtor = false ;
1357
+
1331
1358
switch (newtypeAttr->getNewtypeKind ()) {
1332
1359
case clang::SwiftNewtypeAttr::NK_Enum:
1333
- // TODO: import as closed enum instead
1334
- // For now, fall through and treat as a struct
1360
+ unlabeledCtor = false ;
1361
+ // TODO: import as closed enum instead
1362
+ break ;
1363
+
1335
1364
case clang::SwiftNewtypeAttr::NK_Struct:
1365
+ unlabeledCtor = true ;
1336
1366
break ;
1337
1367
// No other cases yet
1338
1368
}
@@ -1420,14 +1450,19 @@ namespace {
1420
1450
if (!isBridged) {
1421
1451
// Simple, our stored type is equivalent to our computed
1422
1452
// type.
1453
+ auto options = getDefaultMakeStructRawValuedOptions ();
1454
+ if (unlabeledCtor)
1455
+ options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
1456
+
1423
1457
makeStructRawValued (structDecl, storedUnderlyingType,
1424
- synthesizedProtocols, protocols);
1458
+ synthesizedProtocols, protocols, options );
1425
1459
} else {
1426
1460
// We need to make a stored rawValue or storage type, and a
1427
1461
// computed one of bridged type.
1428
1462
makeStructRawValuedWithBridge (structDecl, storedUnderlyingType,
1429
1463
computedPropertyUnderlyingType,
1430
- synthesizedProtocols, protocols);
1464
+ synthesizedProtocols, protocols,
1465
+ /* makeUnlabeledValueInit=*/ unlabeledCtor);
1431
1466
}
1432
1467
1433
1468
Impl.ImportedDecls [{decl->getCanonicalDecl (), useSwift2Name}] =
@@ -1692,39 +1727,37 @@ namespace {
1692
1727
// / \param synthesizedProtocolAttrs synthesized protocol attributes to add
1693
1728
// / \param protocols the protocols to make this struct conform to
1694
1729
// / \param setterAccessibility the accessibility of the raw value's setter
1695
- // / \param isLet whether the raw value should be a let
1696
- // / \param makeUnlabeledValueInit whether to also create an unlabeled init
1697
- // / \param isImplicit whether to mark the rawValue as implicit
1698
1730
// /
1699
1731
// / This will perform most of the work involved in making a new Swift struct
1700
1732
// / be backed by a raw value. This will populated derived protocols and
1701
1733
// / synthesized protocols, add the new variable and pattern bindings, and
1702
1734
// / create the inits parameterized over a raw value
1703
1735
// /
1704
1736
void makeStructRawValued (
1705
- StructDecl *structDecl,
1706
- Type underlyingType,
1737
+ StructDecl *structDecl, Type underlyingType,
1707
1738
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1708
1739
ArrayRef<ProtocolDecl *> protocols,
1709
- Accessibility setterAccessibility = Accessibility::Private,
1710
- bool isLet = true ,
1711
- bool makeUnlabeledValueInit = false ,
1712
- bool isImplicit = true ) {
1740
+ MakeStructRawValuedOptions options =
1741
+ getDefaultMakeStructRawValuedOptions (),
1742
+ Accessibility setterAccessibility = Accessibility::Private) {
1713
1743
auto &cxt = Impl.SwiftContext ;
1714
1744
addProtocolsToStruct (structDecl, synthesizedProtocolAttrs, protocols);
1715
1745
1716
1746
// Create a variable to store the underlying value.
1717
1747
VarDecl *var;
1718
1748
PatternBindingDecl *patternBinding;
1719
- std::tie (var, patternBinding) =
1720
- createVarWithPattern (cxt, structDecl, cxt.Id_rawValue , underlyingType,
1721
- isLet, isImplicit, setterAccessibility);
1749
+ std::tie (var, patternBinding) = createVarWithPattern (
1750
+ cxt, structDecl, cxt.Id_rawValue , underlyingType,
1751
+ options.contains (MakeStructRawValuedFlags::IsLet),
1752
+ options.contains (MakeStructRawValuedFlags::IsImplicit),
1753
+ setterAccessibility);
1722
1754
1723
1755
structDecl->setHasDelayedMembers ();
1724
1756
1725
1757
// Create constructors to initialize that value from a value of the
1726
1758
// underlying type.
1727
- if (makeUnlabeledValueInit)
1759
+ if (options.contains (
1760
+ MakeStructRawValuedFlags::MakeUnlabeledValueInit))
1728
1761
structDecl->addMember (createValueConstructor (
1729
1762
structDecl, var,
1730
1763
/* wantCtorParamNames=*/ false ,
@@ -1753,14 +1786,12 @@ namespace {
1753
1786
// / over a bridged type that will cast to the stored type, as appropriate.
1754
1787
// /
1755
1788
void makeStructRawValuedWithBridge (
1756
- StructDecl *structDecl,
1757
- Type storedUnderlyingType,
1758
- Type bridgedType,
1789
+ StructDecl *structDecl, Type storedUnderlyingType, Type bridgedType,
1759
1790
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1760
- ArrayRef<ProtocolDecl *> protocols) {
1791
+ ArrayRef<ProtocolDecl *> protocols,
1792
+ bool makeUnlabeledValueInit = false ) {
1761
1793
auto &cxt = Impl.SwiftContext ;
1762
- addProtocolsToStruct (structDecl, synthesizedProtocolAttrs,
1763
- protocols);
1794
+ addProtocolsToStruct (structDecl, synthesizedProtocolAttrs, protocols);
1764
1795
1765
1796
auto storedVarName = cxt.getIdentifier (" _rawValue" );
1766
1797
auto computedVarName = cxt.Id_rawValue ;
@@ -1774,46 +1805,70 @@ namespace {
1774
1805
1775
1806
//
1776
1807
// Create a computed value variable
1777
- auto computedVar = new (cxt) VarDecl ( /* static */ false ,
1778
- /* IsLet */ false ,
1779
- SourceLoc (), computedVarName,
1780
- bridgedType, structDecl);
1808
+ auto computedVar =
1809
+ new (cxt) VarDecl ( /* static */ false ,
1810
+ /* IsLet */ false , SourceLoc (), computedVarName,
1811
+ bridgedType, structDecl);
1781
1812
computedVar->setImplicit ();
1782
1813
computedVar->setAccessibility (Accessibility::Public);
1783
1814
computedVar->setSetterAccessibility (Accessibility::Private);
1784
1815
1785
1816
// Create the getter for the computed value variable.
1786
- auto computedVarGetter = makeNewtypeBridgedRawValueGetter (Impl,
1787
- structDecl,
1788
- computedVar,
1789
- storedVar);
1817
+ auto computedVarGetter = makeNewtypeBridgedRawValueGetter (
1818
+ Impl, structDecl, computedVar, storedVar);
1790
1819
1791
1820
// Create a pattern binding to describe the variable.
1792
1821
Pattern *computedVarPattern = createTypedNamedPattern (computedVar);
1793
1822
auto computedPatternBinding = PatternBindingDecl::create (
1794
1823
cxt, SourceLoc (), StaticSpellingKind::None, SourceLoc (),
1795
1824
computedVarPattern, nullptr , structDecl);
1796
1825
1797
- auto init = createValueConstructor (structDecl, computedVar,
1798
- /* wantCtorParamNames=*/ true ,
1826
+ auto init = createRawValueBridgingConstructor (
1827
+ structDecl, computedVar, storedVar,
1828
+ /* wantLabel*/ true , !Impl.hasFinishedTypeChecking ());
1829
+
1830
+ ConstructorDecl *unlabeledCtor = nullptr ;
1831
+ if (makeUnlabeledValueInit)
1832
+ unlabeledCtor = createRawValueBridgingConstructor (
1833
+ structDecl, computedVar, storedVar,
1834
+ /* wantLabel*/ false , !Impl.hasFinishedTypeChecking ());
1835
+
1836
+ structDecl->setHasDelayedMembers ();
1837
+ if (unlabeledCtor)
1838
+ structDecl->addMember (unlabeledCtor);
1839
+ structDecl->addMember (init);
1840
+ structDecl->addMember (storedPatternBinding);
1841
+ structDecl->addMember (storedVar);
1842
+ structDecl->addMember (computedPatternBinding);
1843
+ structDecl->addMember (computedVar);
1844
+ structDecl->addMember (computedVarGetter);
1845
+ }
1846
+
1847
+ // / Create a rawValue-ed constructor that bridges to its underlying storage.
1848
+ ConstructorDecl *createRawValueBridgingConstructor (
1849
+ StructDecl *structDecl, VarDecl *computedRawValue,
1850
+ VarDecl *storedRawValue, bool wantLabel, bool wantBody) {
1851
+ auto &cxt = Impl.SwiftContext ;
1852
+ auto init = createValueConstructor (structDecl, computedRawValue,
1853
+ /* wantCtorParamNames=*/ wantLabel,
1799
1854
/* wantBody=*/ false );
1800
1855
// Insert our custom init body
1801
- if (!Impl. hasFinishedTypeChecking () ) {
1856
+ if (wantBody ) {
1802
1857
auto selfDecl = init->getParameterList (0 )->get (0 );
1803
1858
1804
1859
// Construct left-hand side.
1805
1860
Expr *lhs = new (cxt) DeclRefExpr (selfDecl, DeclNameLoc (),
1806
1861
/* Implicit=*/ true );
1807
- lhs = new (cxt) MemberRefExpr (lhs, SourceLoc (), storedVar ,
1862
+ lhs = new (cxt) MemberRefExpr (lhs, SourceLoc (), storedRawValue ,
1808
1863
DeclNameLoc (), /* Implicit=*/ true );
1809
1864
1810
1865
// Construct right-hand side.
1811
1866
// FIXME: get the parameter from the init, and plug it in here.
1812
1867
auto rhs = new (cxt)
1813
- CoerceExpr (new (cxt) DeclRefExpr (
1814
- init-> getParameterList ( 1 )-> get ( 0 ),
1815
- DeclNameLoc ( ),
1816
- /* Implicit= */ true ), {}, {nullptr , storedUnderlyingType });
1868
+ CoerceExpr (new (cxt) DeclRefExpr (init-> getParameterList ( 1 )-> get ( 0 ),
1869
+ DeclNameLoc (),
1870
+ /* Implicit= */ true ),
1871
+ {}, {nullptr , storedRawValue-> getType () });
1817
1872
1818
1873
// Add assignment.
1819
1874
auto assign = new (cxt) AssignExpr (lhs, SourceLoc (), rhs,
@@ -1822,13 +1877,7 @@ namespace {
1822
1877
init->setBody (body);
1823
1878
}
1824
1879
1825
- structDecl->setHasDelayedMembers ();
1826
- structDecl->addMember (init);
1827
- structDecl->addMember (storedPatternBinding);
1828
- structDecl->addMember (storedVar);
1829
- structDecl->addMember (computedPatternBinding);
1830
- structDecl->addMember (computedVar);
1831
- structDecl->addMember (computedVarGetter);
1880
+ return init;
1832
1881
}
1833
1882
1834
1883
// / \brief Create a constructor that initializes a struct from its members.
@@ -2176,12 +2225,16 @@ namespace {
2176
2225
ProtocolDecl *protocols[]
2177
2226
= {cxt.getProtocol (KnownProtocolKind::RawRepresentable),
2178
2227
cxt.getProtocol (KnownProtocolKind::Equatable)};
2228
+
2229
+ auto options = getDefaultMakeStructRawValuedOptions ();
2230
+ options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
2231
+ options -= MakeStructRawValuedFlags::IsLet;
2232
+ options -= MakeStructRawValuedFlags::IsImplicit;
2233
+
2179
2234
makeStructRawValued (structDecl, underlyingType,
2180
2235
{KnownProtocolKind::RawRepresentable}, protocols,
2181
- /* setterAccessibility=*/ Accessibility::Public,
2182
- /* isLet=*/ false ,
2183
- /* makeUnlabeledValueInit=*/ true ,
2184
- /* isImplicit=*/ false );
2236
+ options,
2237
+ /* setterAccessibility=*/ Accessibility::Public);
2185
2238
2186
2239
result = structDecl;
2187
2240
break ;
0 commit comments