@@ -100,6 +100,20 @@ static bool looksLikeInitMethod(ObjCSelector selector) {
100
100
return !(firstPiece.size () > 4 && clang::isLowercase (firstPiece[4 ]));
101
101
}
102
102
103
+ // Enters and leaves a new lexical scope when emitting
104
+ // members of a Swift type.
105
+ struct CxxEmissionScopeRAII {
106
+ DeclAndTypePrinter &printer;
107
+ CxxDeclEmissionScope &prevScope;
108
+ CxxDeclEmissionScope scope;
109
+
110
+ CxxEmissionScopeRAII (DeclAndTypePrinter &printer)
111
+ : printer(printer), prevScope(printer.getCxxDeclEmissionScope()) {
112
+ printer.setCxxDeclEmissionScope (scope);
113
+ }
114
+ ~CxxEmissionScopeRAII () { printer.setCxxDeclEmissionScope (prevScope); }
115
+ };
116
+
103
117
class DeclAndTypePrinter ::Implementation
104
118
: private DeclVisitor<DeclAndTypePrinter::Implementation>,
105
119
private TypeVisitor<DeclAndTypePrinter::Implementation, void ,
@@ -188,6 +202,12 @@ class DeclAndTypePrinter::Implementation
188
202
}
189
203
190
204
private:
205
+ void recordEmittedDeclInCurrentCxxLexicalScope (const ValueDecl *vd) {
206
+ assert (outputLang == OutputLanguageMode::Cxx);
207
+ owningPrinter.getCxxDeclEmissionScope ().emittedDeclarationNames .insert (
208
+ cxx_translation::getNameForCxx (vd));
209
+ }
210
+
191
211
// / Prints a protocol adoption list: <code><NSCoding, NSCopying></code>
192
212
// /
193
213
// / This method filters out non-ObjC protocols.
@@ -215,6 +235,11 @@ class DeclAndTypePrinter::Implementation
215
235
// / Prints the members of a class, extension, or protocol.
216
236
template <bool AllowDelayed = false , typename R>
217
237
void printMembers (R &&members) {
238
+ CxxEmissionScopeRAII cxxScopeRAII (owningPrinter);
239
+ // FIXME: Actually track emitted members in nested
240
+ // lexical scopes.
241
+ // FIXME: Emit unavailable C++ decls for not emitted
242
+ // nested members.
218
243
bool protocolMembersOptional = false ;
219
244
for (const Decl *member : members) {
220
245
auto VD = dyn_cast<ValueDecl>(member);
@@ -301,6 +326,7 @@ class DeclAndTypePrinter::Implementation
301
326
ClangValueTypePrinter::forwardDeclType (os, CD, owningPrinter);
302
327
ClangClassTypePrinter (os).printClassTypeDecl (
303
328
CD, [&]() { printMembers (CD->getMembers ()); }, owningPrinter);
329
+ recordEmittedDeclInCurrentCxxLexicalScope (CD);
304
330
return ;
305
331
}
306
332
@@ -363,6 +389,7 @@ class DeclAndTypePrinter::Implementation
363
389
}
364
390
},
365
391
owningPrinter);
392
+ recordEmittedDeclInCurrentCxxLexicalScope (SD);
366
393
}
367
394
368
395
void visitExtensionDecl (ExtensionDecl *ED) {
@@ -843,6 +870,7 @@ class DeclAndTypePrinter::Implementation
843
870
printMembers (ED->getMembers ());
844
871
},
845
872
owningPrinter);
873
+ recordEmittedDeclInCurrentCxxLexicalScope (ED);
846
874
}
847
875
848
876
void visitEnumDecl (EnumDecl *ED) {
@@ -984,6 +1012,39 @@ class DeclAndTypePrinter::Implementation
984
1012
sel.getSelectorPieces ().front ().str () == " init" ;
985
1013
}
986
1014
1015
+ // / Returns true if the given function overload is safe to emit in the current
1016
+ // / C++ lexical scope.
1017
+ bool canPrintOverloadOfFunction (const AbstractFunctionDecl *funcDecl) const {
1018
+ assert (outputLang == OutputLanguageMode::Cxx);
1019
+ auto &overloads =
1020
+ owningPrinter.getCxxDeclEmissionScope ().emittedFunctionOverloads ;
1021
+ auto cxxName = cxx_translation::getNameForCxx (funcDecl);
1022
+ auto overloadIt = overloads.find (cxxName);
1023
+ if (overloadIt == overloads.end ()) {
1024
+ overloads.insert (std::make_pair (
1025
+ cxxName,
1026
+ llvm::SmallVector<const AbstractFunctionDecl *>({funcDecl})));
1027
+ return true ;
1028
+ }
1029
+ auto selfArity =
1030
+ funcDecl->getParameters () ? funcDecl->getParameters ()->size () : 0 ;
1031
+ for (const auto *overload : overloadIt->second ) {
1032
+ auto arity =
1033
+ overload->getParameters () ? overload->getParameters ()->size () : 0 ;
1034
+ // Avoid printing out an overload with the same and arity, as that might
1035
+ // be an ambiguous overload on the C++ side.
1036
+ // FIXME: we should take types into account, not all overloads with the
1037
+ // same arity are ambiguous in C++.
1038
+ if (selfArity == arity) {
1039
+ owningPrinter.getCxxDeclEmissionScope ()
1040
+ .additionalUnrepresentableDeclarations .push_back (funcDecl);
1041
+ return false ;
1042
+ }
1043
+ }
1044
+ overloadIt->second .push_back (funcDecl);
1045
+ return true ;
1046
+ }
1047
+
987
1048
void printAbstractFunctionAsMethod (AbstractFunctionDecl *AFD,
988
1049
bool isClassMethod,
989
1050
bool isNSUIntegerSubscript = false ,
@@ -1023,6 +1084,12 @@ class DeclAndTypePrinter::Implementation
1023
1084
if (!dispatchInfo)
1024
1085
return ;
1025
1086
}
1087
+ // FIXME: handle getters/setters ambiguities here too.
1088
+ if (!isa<AccessorDecl>(AFD)) {
1089
+ if (!canPrintOverloadOfFunction (AFD))
1090
+ return ;
1091
+ }
1092
+
1026
1093
owningPrinter.prologueOS << cFuncPrologueOS.str ();
1027
1094
1028
1095
printDocumentationComment (AFD);
@@ -1746,10 +1813,16 @@ class DeclAndTypePrinter::Implementation
1746
1813
llvm::raw_string_ostream cFuncPrologueOS (cFuncDecl);
1747
1814
auto funcABI = Implementation (cFuncPrologueOS, owningPrinter, outputLang)
1748
1815
.printSwiftABIFunctionSignatureAsCxxFunction (FD);
1749
- if (!funcABI)
1816
+ if (!funcABI) {
1817
+ owningPrinter.getCxxDeclEmissionScope ()
1818
+ .additionalUnrepresentableDeclarations .push_back (FD);
1819
+ return ;
1820
+ }
1821
+ if (!canPrintOverloadOfFunction (FD))
1750
1822
return ;
1751
1823
owningPrinter.prologueOS << cFuncPrologueOS.str ();
1752
1824
printAbstractFunctionAsCxxFunctionThunk (FD, *funcABI);
1825
+ recordEmittedDeclInCurrentCxxLexicalScope (FD);
1753
1826
return ;
1754
1827
}
1755
1828
if (FD->getDeclContext ()->isTypeContext ())
@@ -2835,6 +2908,12 @@ bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) {
2835
2908
!excludeForObjCImplementation (VD);
2836
2909
}
2837
2910
2911
+ bool DeclAndTypePrinter::isVisible (const ValueDecl *vd) const {
2912
+ return outputLang == OutputLanguageMode::Cxx
2913
+ ? cxx_translation::isVisibleToCxx (vd, minRequiredAccess)
2914
+ : isVisibleToObjC (vd, minRequiredAccess);
2915
+ }
2916
+
2838
2917
void DeclAndTypePrinter::print (const Decl *D) {
2839
2918
getImpl ().print (D);
2840
2919
}
0 commit comments