@@ -118,6 +118,8 @@ static bool isMistakableForInit(ObjCSelector selector) {
118
118
119
119
120
120
namespace {
121
+ using DelayedMemberSet = llvm::SmallSetVector<const ValueDecl *, 32 >;
122
+
121
123
class ObjCPrinter : private DeclVisitor <ObjCPrinter>,
122
124
private TypeVisitor<ObjCPrinter, void ,
123
125
Optional<OptionalTypeKind>>
@@ -134,6 +136,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
134
136
raw_ostream &os;
135
137
136
138
SmallVector<const FunctionType *, 4 > openFunctionTypes;
139
+ const DelayedMemberSet &delayedMembers;
137
140
138
141
Accessibility minRequiredAccess;
139
142
bool protocolMembersOptional = false ;
@@ -144,14 +147,31 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
144
147
friend TypeVisitor<ObjCPrinter>;
145
148
146
149
public:
147
- explicit ObjCPrinter (Module &mod, raw_ostream &out, Accessibility access)
148
- : M(mod), os(out), minRequiredAccess(access) {}
150
+ explicit ObjCPrinter (Module &mod, raw_ostream &out,
151
+ DelayedMemberSet &delayed, Accessibility access)
152
+ : M(mod), os(out), delayedMembers(delayed), minRequiredAccess(access) {}
149
153
150
154
void print (const Decl *D) {
151
155
PrettyStackTraceDecl trace (" printing" , D);
152
156
visit (const_cast <Decl *>(D));
153
157
}
154
158
159
+ void printAdHocCategory (iterator_range<const ValueDecl * const *> members) {
160
+ assert (members.begin () != members.end ());
161
+
162
+ const DeclContext *origDC = (*members.begin ())->getDeclContext ();
163
+ auto *baseClass = dyn_cast<ClassDecl>(origDC);
164
+ if (!baseClass) {
165
+ Type extendedTy = cast<ExtensionDecl>(origDC)->getExtendedType ();
166
+ baseClass = extendedTy->getClassOrBoundGenericClass ();
167
+ }
168
+
169
+ os << " @interface " << getNameForObjC (baseClass)
170
+ << " (SWIFT_EXTENSION(" << origDC->getParentModule ()->getName () << " ))\n " ;
171
+ printMembers</* allowDelayed*/ true >(members);
172
+ os << " @end\n\n " ;
173
+ }
174
+
155
175
bool shouldInclude (const ValueDecl *VD, bool checkParent = true ) {
156
176
if (!(VD->isObjC () || VD->getAttrs ().hasAttribute <CDeclAttr>()))
157
177
return false ;
@@ -198,19 +218,24 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
198
218
}
199
219
200
220
// / Prints the members of a class, extension, or protocol.
201
- void printMembers (DeclRange members) {
202
- for (auto member : members) {
221
+ template <bool AllowDelayed = false , typename R>
222
+ void printMembers (R &&members) {
223
+ for (const Decl *member : members) {
203
224
auto VD = dyn_cast<ValueDecl>(member);
204
225
if (!VD || !shouldInclude (VD) || isa<TypeDecl>(VD))
205
226
continue ;
206
227
if (auto FD = dyn_cast<FuncDecl>(VD))
207
228
if (FD->isAccessor ())
208
229
continue ;
230
+ if (!AllowDelayed && delayedMembers.count (VD)) {
231
+ os << " // '" << VD->getFullName () << " ' below\n " ;
232
+ continue ;
233
+ }
209
234
if (VD->getAttrs ().hasAttribute <OptionalAttr>() != protocolMembersOptional) {
210
235
protocolMembersOptional = VD->getAttrs ().hasAttribute <OptionalAttr>();
211
236
os << (protocolMembersOptional ? " @optional\n " : " @required\n " );
212
237
}
213
- visit (VD );
238
+ visit (const_cast <ValueDecl*>(VD) );
214
239
}
215
240
}
216
241
@@ -1509,6 +1534,7 @@ class ReferencedTypeFinder : private TypeVisitor<ReferencedTypeFinder> {
1509
1534
friend TypeVisitor;
1510
1535
1511
1536
llvm::function_ref<void (ReferencedTypeFinder &, const TypeDecl *)> Callback;
1537
+ bool IsWithinConstrainedObjCGeneric = false ;
1512
1538
1513
1539
ReferencedTypeFinder (decltype (Callback) callback) : Callback(callback) {}
1514
1540
@@ -1568,18 +1594,48 @@ class ReferencedTypeFinder : private TypeVisitor<ReferencedTypeFinder> {
1568
1594
visit (inout->getObjectType ());
1569
1595
}
1570
1596
1597
+ // / Returns true if \p archetype has any constraints other than being
1598
+ // / class-bound ("conforms to" AnyObject).
1599
+ static bool isConstrainedArchetype (const ArchetypeType *archetype) {
1600
+ if (archetype->getSuperclass ())
1601
+ return true ;
1602
+
1603
+ if (archetype->getConformsTo ().size () > 1 )
1604
+ return true ;
1605
+ if (archetype->getConformsTo ().size () == 0 )
1606
+ return false ;
1607
+
1608
+ const ProtocolDecl *proto = archetype->getConformsTo ().front ();
1609
+ if (auto knownKind = proto->getKnownProtocolKind ())
1610
+ return knownKind.getValue () != KnownProtocolKind::AnyObject;
1611
+ return true ;
1612
+ }
1613
+
1571
1614
void visitBoundGenericType (BoundGenericType *boundGeneric) {
1572
- for (auto argTy : boundGeneric->getGenericArgs ())
1615
+ bool isObjCGeneric = boundGeneric->getDecl ()->hasClangNode ();
1616
+
1617
+ for_each (boundGeneric->getGenericArgs (),
1618
+ boundGeneric->getDecl ()->getGenericParams ()->getPrimaryArchetypes (),
1619
+ [&](Type argTy, const ArchetypeType *archetype) {
1620
+ if (isObjCGeneric && isConstrainedArchetype (archetype))
1621
+ IsWithinConstrainedObjCGeneric = true ;
1573
1622
visit (argTy);
1574
- // Ignore the base type; that can't be exposed to Objective-C. Every
1575
- // bound generic type we care about gets mapped to a particular construct
1576
- // in Objective-C we care about. (For example, Optional<NSFoo> is mapped to
1577
- // NSFoo *.)
1623
+ IsWithinConstrainedObjCGeneric = false ;
1624
+ });
1625
+
1626
+ // Ignore the base type; that either can't be exposed to Objective-C or
1627
+ // was an Objective-C type to begin with. Every bound generic Swift type we
1628
+ // care about gets mapped to a particular construct in Objective-C.
1629
+ // (For example, Optional<NSFoo> is mapped to NSFoo *.)
1578
1630
}
1579
1631
1580
1632
public:
1581
1633
using TypeVisitor::visit;
1582
1634
1635
+ bool isWithinConstrainedObjCGeneric () const {
1636
+ return IsWithinConstrainedObjCGeneric;
1637
+ }
1638
+
1583
1639
static void walk (Type ty, decltype (Callback) callback) {
1584
1640
ReferencedTypeFinder (callback).visit (ty);
1585
1641
}
@@ -1603,13 +1659,14 @@ struct PointerLikeComparator {
1603
1659
1604
1660
class ModuleWriter {
1605
1661
enum class EmissionState {
1606
- DefinitionRequested = 0 ,
1607
- DefinitionInProgress ,
1662
+ NotYetDefined = 0 ,
1663
+ DefinitionRequested ,
1608
1664
Defined
1609
1665
};
1610
1666
1611
1667
llvm::DenseMap<const TypeDecl *, std::pair<EmissionState, bool >> seenTypes;
1612
1668
std::vector<const Decl *> declsToWrite;
1669
+ DelayedMemberSet delayedMembers;
1613
1670
1614
1671
using ImportModuleTy = PointerUnion<Module*, const clang::Module*>;
1615
1672
SmallSetVector<ImportModuleTy, 8 ,
@@ -1623,7 +1680,7 @@ class ModuleWriter {
1623
1680
ObjCPrinter printer;
1624
1681
public:
1625
1682
ModuleWriter (Module &mod, StringRef header, Accessibility access)
1626
- : M(mod), bridgingHeader(header), printer(M, os, access) {}
1683
+ : M(mod), bridgingHeader(header), printer(M, os, delayedMembers, access) {}
1627
1684
1628
1685
// / Returns true if we added the decl's module to the import set, false if
1629
1686
// / the decl is a local decl.
@@ -1660,6 +1717,19 @@ class ModuleWriter {
1660
1717
return true ;
1661
1718
}
1662
1719
1720
+ bool hasBeenRequested (const TypeDecl *D) const {
1721
+ return seenTypes.lookup (D).first >= EmissionState::DefinitionRequested;
1722
+ }
1723
+
1724
+ bool tryRequire (const TypeDecl *D) {
1725
+ if (addImport (D)) {
1726
+ seenTypes[D] = { EmissionState::Defined, true };
1727
+ return true ;
1728
+ }
1729
+ auto &state = seenTypes[D];
1730
+ return state.first == EmissionState::Defined;
1731
+ }
1732
+
1663
1733
bool require (const TypeDecl *D) {
1664
1734
if (addImport (D)) {
1665
1735
seenTypes[D] = { EmissionState::Defined, true };
@@ -1668,11 +1738,11 @@ class ModuleWriter {
1668
1738
1669
1739
auto &state = seenTypes[D];
1670
1740
switch (state.first ) {
1741
+ case EmissionState::NotYetDefined:
1671
1742
case EmissionState::DefinitionRequested:
1743
+ state.first = EmissionState::DefinitionRequested;
1672
1744
declsToWrite.push_back (D);
1673
1745
return false ;
1674
- case EmissionState::DefinitionInProgress:
1675
- llvm_unreachable (" circular requirements" );
1676
1746
case EmissionState::Defined:
1677
1747
return true ;
1678
1748
}
@@ -1717,7 +1787,17 @@ class ModuleWriter {
1717
1787
});
1718
1788
}
1719
1789
1720
- void forwardDeclareMemberTypes (DeclRange members) {
1790
+ bool forwardDeclareMemberTypes (DeclRange members, const Decl *container) {
1791
+ switch (container->getKind ()) {
1792
+ case DeclKind::Class:
1793
+ case DeclKind::Protocol:
1794
+ case DeclKind::Extension:
1795
+ break ;
1796
+ default :
1797
+ llvm_unreachable (" unexpected container kind" );
1798
+ }
1799
+
1800
+ bool hadAnyDelayedMembers = false ;
1721
1801
SmallVector<ValueDecl *, 4 > nestedTypes;
1722
1802
for (auto member : members) {
1723
1803
auto VD = dyn_cast<ValueDecl>(member);
@@ -1738,9 +1818,44 @@ class ModuleWriter {
1738
1818
continue ;
1739
1819
}
1740
1820
1821
+ bool needsToBeIndividuallyDelayed = false ;
1741
1822
ReferencedTypeFinder::walk (VD->getType (),
1742
- [this ](ReferencedTypeFinder &finder,
1743
- const TypeDecl *TD) {
1823
+ [&](ReferencedTypeFinder &finder,
1824
+ const TypeDecl *TD) {
1825
+ if (TD == container)
1826
+ return ;
1827
+
1828
+ if (finder.isWithinConstrainedObjCGeneric ()) {
1829
+ // We can delay individual members of classes; do so if necessary.
1830
+ if (isa<ClassDecl>(container)) {
1831
+ if (!tryRequire (TD)) {
1832
+ needsToBeIndividuallyDelayed = true ;
1833
+ hadAnyDelayedMembers = true ;
1834
+ }
1835
+ return ;
1836
+ }
1837
+
1838
+ // Extensions can always be delayed wholesale.
1839
+ if (isa<ExtensionDecl>(container)) {
1840
+ if (!require (TD))
1841
+ hadAnyDelayedMembers = true ;
1842
+ return ;
1843
+ }
1844
+
1845
+ // Protocols should be delayed wholesale unless we might have a cycle.
1846
+ auto *proto = cast<ProtocolDecl>(container);
1847
+ if (!hasBeenRequested (proto) || !hasBeenRequested (TD)) {
1848
+ if (!require (TD))
1849
+ hadAnyDelayedMembers = true ;
1850
+ return ;
1851
+ }
1852
+
1853
+ // Otherwise, we have a cyclic dependency. Give up and continue with
1854
+ // regular forward-declarations even though this will lead to an
1855
+ // error; there's nothing we can do here.
1856
+ // FIXME: It would be nice to diagnose this.
1857
+ }
1858
+
1744
1859
if (auto CD = dyn_cast<ClassDecl>(TD)) {
1745
1860
if (!forwardDeclare (CD)) {
1746
1861
(void )addImport (CD);
@@ -1758,13 +1873,18 @@ class ModuleWriter {
1758
1873
else
1759
1874
assert (false && " unknown local type decl" );
1760
1875
});
1876
+
1877
+ if (needsToBeIndividuallyDelayed) {
1878
+ assert (isa<ClassDecl>(container));
1879
+ delayedMembers.insert (VD);
1880
+ }
1761
1881
}
1762
1882
1763
1883
declsToWrite.insert (declsToWrite.end ()-1 , nestedTypes.rbegin (),
1764
1884
nestedTypes.rend ());
1765
1885
1766
1886
// Separate forward declarations from the class itself.
1767
- os << ' \n ' ;
1887
+ return !hadAnyDelayedMembers ;
1768
1888
}
1769
1889
1770
1890
bool writeClass (const ClassDecl *CD) {
@@ -1789,8 +1909,9 @@ class ModuleWriter {
1789
1909
if (!allRequirementsSatisfied)
1790
1910
return false ;
1791
1911
1912
+ (void )forwardDeclareMemberTypes (CD->getMembers (), CD);
1792
1913
seenTypes[CD] = { EmissionState::Defined, true };
1793
- forwardDeclareMemberTypes (CD-> getMembers ()) ;
1914
+ os << ' \n ' ;
1794
1915
printer.print (CD);
1795
1916
return true ;
1796
1917
}
@@ -1824,8 +1945,11 @@ class ModuleWriter {
1824
1945
if (!allRequirementsSatisfied)
1825
1946
return false ;
1826
1947
1948
+ if (!forwardDeclareMemberTypes (PD->getMembers (), PD))
1949
+ return false ;
1950
+
1827
1951
seenTypes[PD] = { EmissionState::Defined, true };
1828
- forwardDeclareMemberTypes (PD-> getMembers ()) ;
1952
+ os << ' \n ' ;
1829
1953
printer.print (PD);
1830
1954
return true ;
1831
1955
}
@@ -1842,7 +1966,13 @@ class ModuleWriter {
1842
1966
if (!allRequirementsSatisfied)
1843
1967
return false ;
1844
1968
1845
- forwardDeclareMemberTypes (ED->getMembers ());
1969
+ // This isn't rolled up into the previous set of requirements because
1970
+ // it /also/ prints forward declarations, and the header is a little
1971
+ // prettier if those are as close as possible to the necessary extension.
1972
+ if (!forwardDeclareMemberTypes (ED->getMembers (), ED))
1973
+ return false ;
1974
+
1975
+ os << ' \n ' ;
1846
1976
printer.print (ED);
1847
1977
return true ;
1848
1978
}
@@ -2186,6 +2316,17 @@ class ModuleWriter {
2186
2316
}
2187
2317
}
2188
2318
2319
+ if (!delayedMembers.empty ()) {
2320
+ auto groupBegin = delayedMembers.begin ();
2321
+ for (auto i = groupBegin, e = delayedMembers.end (); i != e; ++i) {
2322
+ if ((*i)->getDeclContext () != (*groupBegin)->getDeclContext ()) {
2323
+ printer.printAdHocCategory (make_range (groupBegin, i));
2324
+ groupBegin = i;
2325
+ }
2326
+ }
2327
+ printer.printAdHocCategory (make_range (groupBegin, delayedMembers.end ()));
2328
+ }
2329
+
2189
2330
writePrologue (out);
2190
2331
writeImports (out);
2191
2332
out <<
0 commit comments