@@ -100,6 +100,20 @@ static bool looksLikeInitMethod(ObjCSelector selector) {
100100 return !(firstPiece.size () > 4 && clang::isLowercase (firstPiece[4 ]));
101101}
102102
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+
103117class DeclAndTypePrinter ::Implementation
104118 : private DeclVisitor<DeclAndTypePrinter::Implementation>,
105119 private TypeVisitor<DeclAndTypePrinter::Implementation, void ,
@@ -188,6 +202,12 @@ class DeclAndTypePrinter::Implementation
188202 }
189203
190204private:
205+ void recordEmittedDeclInCurrentCxxLexicalScope (const ValueDecl *vd) {
206+ assert (outputLang == OutputLanguageMode::Cxx);
207+ owningPrinter.getCxxDeclEmissionScope ().emittedDeclarationNames .insert (
208+ cxx_translation::getNameForCxx (vd));
209+ }
210+
191211 // / Prints a protocol adoption list: <code><NSCoding, NSCopying></code>
192212 // /
193213 // / This method filters out non-ObjC protocols.
@@ -215,6 +235,11 @@ class DeclAndTypePrinter::Implementation
215235 // / Prints the members of a class, extension, or protocol.
216236 template <bool AllowDelayed = false , typename R>
217237 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.
218243 bool protocolMembersOptional = false ;
219244 for (const Decl *member : members) {
220245 auto VD = dyn_cast<ValueDecl>(member);
@@ -301,6 +326,7 @@ class DeclAndTypePrinter::Implementation
301326 ClangValueTypePrinter::forwardDeclType (os, CD, owningPrinter);
302327 ClangClassTypePrinter (os).printClassTypeDecl (
303328 CD, [&]() { printMembers (CD->getMembers ()); }, owningPrinter);
329+ recordEmittedDeclInCurrentCxxLexicalScope (CD);
304330 return ;
305331 }
306332
@@ -363,6 +389,7 @@ class DeclAndTypePrinter::Implementation
363389 }
364390 },
365391 owningPrinter);
392+ recordEmittedDeclInCurrentCxxLexicalScope (SD);
366393 }
367394
368395 void visitExtensionDecl (ExtensionDecl *ED) {
@@ -843,6 +870,7 @@ class DeclAndTypePrinter::Implementation
843870 printMembers (ED->getMembers ());
844871 },
845872 owningPrinter);
873+ recordEmittedDeclInCurrentCxxLexicalScope (ED);
846874 }
847875
848876 void visitEnumDecl (EnumDecl *ED) {
@@ -984,6 +1012,39 @@ class DeclAndTypePrinter::Implementation
9841012 sel.getSelectorPieces ().front ().str () == " init" ;
9851013 }
9861014
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+
9871048 void printAbstractFunctionAsMethod (AbstractFunctionDecl *AFD,
9881049 bool isClassMethod,
9891050 bool isNSUIntegerSubscript = false ,
@@ -1023,6 +1084,12 @@ class DeclAndTypePrinter::Implementation
10231084 if (!dispatchInfo)
10241085 return ;
10251086 }
1087+ // FIXME: handle getters/setters ambiguities here too.
1088+ if (!isa<AccessorDecl>(AFD)) {
1089+ if (!canPrintOverloadOfFunction (AFD))
1090+ return ;
1091+ }
1092+
10261093 owningPrinter.prologueOS << cFuncPrologueOS.str ();
10271094
10281095 printDocumentationComment (AFD);
@@ -1746,10 +1813,16 @@ class DeclAndTypePrinter::Implementation
17461813 llvm::raw_string_ostream cFuncPrologueOS (cFuncDecl);
17471814 auto funcABI = Implementation (cFuncPrologueOS, owningPrinter, outputLang)
17481815 .printSwiftABIFunctionSignatureAsCxxFunction (FD);
1749- if (!funcABI)
1816+ if (!funcABI) {
1817+ owningPrinter.getCxxDeclEmissionScope ()
1818+ .additionalUnrepresentableDeclarations .push_back (FD);
1819+ return ;
1820+ }
1821+ if (!canPrintOverloadOfFunction (FD))
17501822 return ;
17511823 owningPrinter.prologueOS << cFuncPrologueOS.str ();
17521824 printAbstractFunctionAsCxxFunctionThunk (FD, *funcABI);
1825+ recordEmittedDeclInCurrentCxxLexicalScope (FD);
17531826 return ;
17541827 }
17551828 if (FD->getDeclContext ()->isTypeContext ())
@@ -2835,6 +2908,12 @@ bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) {
28352908 !excludeForObjCImplementation (VD);
28362909}
28372910
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+
28382917void DeclAndTypePrinter::print (const Decl *D) {
28392918 getImpl ().print (D);
28402919}
0 commit comments