Skip to content

Commit aff3568

Browse files
committed
[interop][SwiftToCxx] emit unavailable type stubs for top level types that could not be emitted in the C++ section of the generated header
1 parent 01086bc commit aff3568

18 files changed

+288
-87
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,10 @@ ERROR(expose_enum_case_type_to_cxx,none,
16941694
"enum %0 can not be represented in C++ as one of its cases has an associated value with type that can't be represented in C++", (ValueDecl *))
16951695
ERROR(expose_enum_case_tuple_to_cxx,none,
16961696
"enum %0 can not yet be represented in C++ as one of its cases has multiple associated values", (ValueDecl *))
1697+
ERROR(unexposed_other_decl_in_cxx,none,
1698+
"%0 %1 is not yet exposed to C++", (DescriptiveDeclKind, ValueDecl *))
1699+
ERROR(unsupported_other_decl_in_cxx,none,
1700+
"Swift %0 %1 cannot be represented in C++", (DescriptiveDeclKind, ValueDecl *))
16971701

16981702
ERROR(attr_methods_only,none,
16991703
"only methods can be declared %0", (DeclAttribute))

include/swift/AST/SwiftNameTranslation.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
#ifndef SWIFT_NAME_TRANSLATION_H
1414
#define SWIFT_NAME_TRANSLATION_H
1515

16-
#include "swift/AST/Identifier.h"
1716
#include "swift/AST/AttrKind.h"
17+
#include "swift/AST/DiagnosticEngine.h"
18+
#include "swift/AST/Identifier.h"
1819

1920
namespace swift {
2021
class ValueDecl;
@@ -78,6 +79,9 @@ enum RepresentationError {
7879
UnrepresentableEnumCaseTuple,
7980
};
8081

82+
/// Constructs a diagnostic that describes the given C++ representation error.
83+
Diagnostic diagnoseRepresenationError(RepresentationError error, ValueDecl *vd);
84+
8185
struct DeclRepresentation {
8286
RepresentationKind kind;
8387
llvm::Optional<RepresentationError> error;

lib/AST/SwiftNameTranslation.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/SwiftNameTranslation.h"
1818
#include "swift/AST/ASTContext.h"
1919
#include "swift/AST/Decl.h"
20+
#include "swift/AST/DiagnosticsSema.h"
2021
#include "swift/AST/LazyResolver.h"
2122
#include "swift/AST/Module.h"
2223
#include "swift/AST/ParameterList.h"
@@ -283,3 +284,37 @@ bool swift::cxx_translation::isVisibleToCxx(const ValueDecl *VD,
283284
}
284285
return false;
285286
}
287+
288+
Diagnostic
289+
swift::cxx_translation::diagnoseRepresenationError(RepresentationError error,
290+
ValueDecl *vd) {
291+
switch (error) {
292+
case UnrepresentableObjC:
293+
return Diagnostic(diag::expose_unsupported_objc_decl_to_cxx,
294+
vd->getDescriptiveKind(), vd);
295+
case UnrepresentableAsync:
296+
return Diagnostic(diag::expose_unsupported_async_decl_to_cxx,
297+
vd->getDescriptiveKind(), vd);
298+
case UnrepresentableIsolatedInActor:
299+
return Diagnostic(diag::expose_unsupported_actor_isolated_to_cxx,
300+
vd->getDescriptiveKind(), vd);
301+
case UnrepresentableRequiresClientEmission:
302+
return Diagnostic(diag::expose_unsupported_client_emission_to_cxx,
303+
vd->getDescriptiveKind(), vd);
304+
case UnrepresentableGeneric:
305+
return Diagnostic(diag::expose_generic_decl_to_cxx,
306+
vd->getDescriptiveKind(), vd);
307+
case UnrepresentableGenericRequirements:
308+
return Diagnostic(diag::expose_generic_requirement_to_cxx,
309+
vd->getDescriptiveKind(), vd);
310+
case UnrepresentableThrows:
311+
return Diagnostic(diag::expose_throwing_to_cxx, vd->getDescriptiveKind(),
312+
vd);
313+
case UnrepresentableIndirectEnum:
314+
return Diagnostic(diag::expose_indirect_enum_cxx, vd);
315+
case UnrepresentableEnumCaseType:
316+
return Diagnostic(diag::expose_enum_case_type_to_cxx, vd);
317+
case UnrepresentableEnumCaseTuple:
318+
return Diagnostic(diag::expose_enum_case_tuple_to_cxx, vd);
319+
}
320+
}

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
103117
class DeclAndTypePrinter::Implementation
104118
: private DeclVisitor<DeclAndTypePrinter::Implementation>,
105119
private TypeVisitor<DeclAndTypePrinter::Implementation, void,
@@ -188,6 +202,12 @@ class DeclAndTypePrinter::Implementation
188202
}
189203

190204
private:
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>&lt;NSCoding, NSCopying&gt;</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) {
@@ -1746,10 +1774,14 @@ class DeclAndTypePrinter::Implementation
17461774
llvm::raw_string_ostream cFuncPrologueOS(cFuncDecl);
17471775
auto funcABI = Implementation(cFuncPrologueOS, owningPrinter, outputLang)
17481776
.printSwiftABIFunctionSignatureAsCxxFunction(FD);
1749-
if (!funcABI)
1777+
if (!funcABI) {
1778+
owningPrinter.getCxxDeclEmissionScope()
1779+
.additionalUnrepresentableDeclarations.push_back(FD);
17501780
return;
1781+
}
17511782
owningPrinter.prologueOS << cFuncPrologueOS.str();
17521783
printAbstractFunctionAsCxxFunctionThunk(FD, *funcABI);
1784+
recordEmittedDeclInCurrentCxxLexicalScope(FD);
17531785
return;
17541786
}
17551787
if (FD->getDeclContext()->isTypeContext())

lib/PrintAsClang/DeclAndTypePrinter.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ class PrimitiveTypeMapping;
3030
class ValueDecl;
3131
class SwiftToClangInteropContext;
3232

33+
/// Tracks which C++ declarations have been emitted in a lexical
34+
/// C++ scope.
35+
struct CxxDeclEmissionScope {
36+
/// Additional Swift declarations that are unrepresentable in C++.
37+
std::vector<const ValueDecl *> additionalUnrepresentableDeclarations;
38+
/// Records the C++ declaration names already emitted in this lexical scope.
39+
llvm::StringSet<> emittedDeclarationNames;
40+
};
41+
3342
/// Responsible for printing a Swift Decl or Type in Objective-C, to be
3443
/// included in a Swift module's ObjC compatibility header.
3544
class DeclAndTypePrinter {
@@ -45,6 +54,7 @@ class DeclAndTypePrinter {
4554
raw_ostream &prologueOS;
4655
raw_ostream &outOfLineDefinitionsOS;
4756
const DelayedMemberSet &delayedMembers;
57+
CxxDeclEmissionScope *cxxDeclEmissionScope;
4858
PrimitiveTypeMapping &typeMapping;
4959
SwiftToClangInteropContext &interopContext;
5060
AccessLevel minRequiredAccess;
@@ -63,22 +73,31 @@ class DeclAndTypePrinter {
6373
DeclAndTypePrinter(ModuleDecl &mod, raw_ostream &out, raw_ostream &prologueOS,
6474
raw_ostream &outOfLineDefinitionsOS,
6575
DelayedMemberSet &delayed,
76+
CxxDeclEmissionScope &topLevelEmissionScope,
6677
PrimitiveTypeMapping &typeMapping,
6778
SwiftToClangInteropContext &interopContext,
6879
AccessLevel access, bool requiresExposedAttribute,
6980
llvm::StringSet<> &exposedModules,
7081
OutputLanguageMode outputLang)
7182
: M(mod), os(out), prologueOS(prologueOS),
7283
outOfLineDefinitionsOS(outOfLineDefinitionsOS), delayedMembers(delayed),
73-
typeMapping(typeMapping), interopContext(interopContext),
74-
minRequiredAccess(access),
84+
cxxDeclEmissionScope(&topLevelEmissionScope), typeMapping(typeMapping),
85+
interopContext(interopContext), minRequiredAccess(access),
7586
requiresExposedAttribute(requiresExposedAttribute),
7687
exposedModules(exposedModules), outputLang(outputLang) {}
7788

7889
PrimitiveTypeMapping &getTypeMapping() { return typeMapping; }
7990

8091
SwiftToClangInteropContext &getInteropContext() { return interopContext; }
8192

93+
CxxDeclEmissionScope &getCxxDeclEmissionScope() {
94+
return *cxxDeclEmissionScope;
95+
}
96+
97+
void setCxxDeclEmissionScope(CxxDeclEmissionScope &scope) {
98+
cxxDeclEmissionScope = &scope;
99+
}
100+
82101
/// Returns true if \p VD should be included in a compatibility header for
83102
/// the options the printer was constructed with.
84103
bool shouldInclude(const ValueDecl *VD);

0 commit comments

Comments
 (0)