Skip to content

Commit ba34e4f

Browse files
authored
Merge pull request #64046 from hyp/eng/cxx-interop-no-expose
[interop][SwiftToCxx] do not require @_expose when generating C++ interface for a Swift module
2 parents f3a6ce1 + af7ca77 commit ba34e4f

21 files changed

+132
-40
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,8 @@ ERROR(expose_generic_decl_to_cxx,none,
16231623
"generic %0 %1 can not yet be exposed to C++", (DescriptiveDeclKind, ValueDecl *))
16241624
ERROR(expose_generic_requirement_to_cxx,none,
16251625
"generic requirements for %0 %1 can not yet be represented in C++", (DescriptiveDeclKind, ValueDecl *))
1626+
ERROR(expose_throwing_to_cxx,none,
1627+
"%0 %1 can not yet be represented in C++ as it may throw an error", (DescriptiveDeclKind, ValueDecl *))
16261628

16271629
ERROR(attr_methods_only,none,
16281630
"only methods can be declared %0", (DeclAttribute))

include/swift/AST/SwiftNameTranslation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ enum RepresentationError {
7070
UnrepresentableIsolatedInActor,
7171
UnrepresentableRequiresClientEmission,
7272
UnrepresentableGeneric,
73-
UnrepresentableGenericRequirements
73+
UnrepresentableGenericRequirements,
74+
UnrepresentableThrows
7475
};
7576

7677
struct DeclRepresentation {

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ EXPERIMENTAL_FEATURE(RuntimeDiscoverableAttrs, false)
176176
/// signatures.
177177
EXPERIMENTAL_FEATURE(ImportSymbolicCXXDecls, false)
178178

179+
/// Generate bindings for functions that 'throw' in the C++ section of the generated Clang header.
180+
EXPERIMENTAL_FEATURE(GenerateBindingsForThrowingFunctionsInCXX, false)
181+
179182
#undef EXPERIMENTAL_FEATURE
180183
#undef UPCOMING_FEATURE
181184
#undef SUPPRESSIBLE_LANGUAGE_FEATURE

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,17 +406,16 @@ class FrontendOptions {
406406
/// Expose all public declarations in the generated header.
407407
AllPublic,
408408
/// Expose declarations only when they have expose attribute.
409-
HasExposeAttr
409+
HasExposeAttr,
410+
/// Expose declarations only when they have expose attribute or are the
411+
/// implicitly exposed Stdlib declarations.
412+
HasExposeAttrOrImplicitDeps
410413
};
411414

412415
/// Indicates which declarations should be exposed in the generated clang
413416
/// header.
414417
llvm::Optional<ClangHeaderExposeBehavior> ClangHeaderExposedDecls;
415418

416-
/// Emit C++ bindings for the exposed Swift declarations in the generated
417-
/// clang header.
418-
bool EnableExperimentalCxxInteropInClangHeader = false;
419-
420419
/// \return true if the given action only parses without doing other compilation steps.
421420
static bool shouldActionOnlyParse(ActionType);
422421

include/swift/Option/Options.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -671,11 +671,6 @@ def experimental_c_foreign_reference_types :
671671
Flags<[FrontendOption, HelpHidden, ModuleInterfaceOption]>,
672672
HelpText<"Enable experimental C foreign references types (with reference coutning).">;
673673

674-
def enable_experimental_cxx_interop_in_clang_header :
675-
Flag<["-"], "enable-experimental-cxx-interop-in-clang-header">,
676-
Flags<[FrontendOption, NoDriverOption, HelpHidden]>,
677-
HelpText<"Enable experimental Swift to C++ interop code generation in generated Clang header">;
678-
679674
def experimental_cxx_stdlib :
680675
Separate<["-"], "experimental-cxx-stdlib">,
681676
Flags<[HelpHidden]>,

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,10 @@ static bool usesFeatureBuiltinMacros(Decl *decl) {
32003200

32013201
static bool usesFeatureImportSymbolicCXXDecls(Decl *decl) { return false; }
32023202

3203+
static bool usesFeatureGenerateBindingsForThrowingFunctionsInCXX(Decl *decl) {
3204+
return false;
3205+
}
3206+
32033207
static bool usesFeatureFreestandingExpressionMacros(Decl *decl) {
32043208
auto macro = dyn_cast<MacroDecl>(decl);
32053209
if (!macro)

lib/AST/SwiftNameTranslation.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
179179
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
180180
if (AFD->hasAsync())
181181
return {Unsupported, UnrepresentableAsync};
182+
if (AFD->hasThrows() &&
183+
!AFD->getASTContext().LangOpts.hasFeature(
184+
Feature::GenerateBindingsForThrowingFunctionsInCXX))
185+
return {Unsupported, UnrepresentableThrows};
182186
// Don't expose @_alwaysEmitIntoClient functions as they require their
183187
// bodies to be emitted into client.
184188
if (AFD->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
@@ -194,6 +198,13 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
194198
typeDecl->getGenericSignature().getCanonicalSignature();
195199
}
196200
}
201+
if (const auto *varDecl = dyn_cast<VarDecl>(VD)) {
202+
// Check if any property accessor throws, do not expose it in that case.
203+
for (const auto *accessor : varDecl->getAllAccessors()) {
204+
if (accessor->hasThrows())
205+
return {Unsupported, UnrepresentableThrows};
206+
}
207+
}
197208
// Generic requirements are not yet supported in C++.
198209
if (genericSignature && !genericSignature->getRequirements().empty())
199210
return {Unsupported, UnrepresentableGenericRequirements};

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,19 @@ bool ArgsToFrontendOptionsConverter::convert(
310310
Opts.UseSharedResourceFolder = !Args.hasArg(OPT_use_static_resource_dir);
311311
Opts.DisableBuildingInterface = Args.hasArg(OPT_disable_building_interface);
312312
if (const Arg *A = Args.getLastArg(options::OPT_clang_header_expose_decls)) {
313-
Opts.ClangHeaderExposedDecls =
314-
llvm::StringSwitch<llvm::Optional<FrontendOptions::ClangHeaderExposeBehavior>>(A->getValue())
315-
.Case("all-public", FrontendOptions::ClangHeaderExposeBehavior::AllPublic)
316-
.Case("has-expose-attr", FrontendOptions::ClangHeaderExposeBehavior::HasExposeAttr)
317-
.Default(llvm::None);
318-
}
319-
Opts.EnableExperimentalCxxInteropInClangHeader =
320-
Args.hasArg(OPT_enable_experimental_cxx_interop_in_clang_header);
313+
Opts.ClangHeaderExposedDecls =
314+
llvm::StringSwitch<
315+
llvm::Optional<FrontendOptions::ClangHeaderExposeBehavior>>(
316+
A->getValue())
317+
.Case("all-public",
318+
FrontendOptions::ClangHeaderExposeBehavior::AllPublic)
319+
.Case("has-expose-attr",
320+
FrontendOptions::ClangHeaderExposeBehavior::HasExposeAttr)
321+
.Case("has-expose-attr-or-stdlib",
322+
FrontendOptions::ClangHeaderExposeBehavior::
323+
HasExposeAttrOrImplicitDeps)
324+
.Default(llvm::None);
325+
}
321326

322327
Opts.StrictImplicitModuleContext = Args.hasArg(OPT_strict_implicit_module_context,
323328
OPT_no_strict_implicit_module_context,

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,9 @@ class ModuleWriter {
661661
int result = getSortName(*rhs).compare(getSortName(*lhs));
662662
if (result != 0)
663663
return result;
664+
// Two overloaded functions can have the same name when emitting C++.
665+
if (isa<AbstractFunctionDecl>(*rhs) && isa<AbstractFunctionDecl>(*lhs))
666+
return result;
664667

665668
// Prefer value decls to extensions.
666669
assert(!(isa<ValueDecl>(*lhs) && isa<ValueDecl>(*rhs)));

lib/PrintAsClang/PrintAsClang.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -556,22 +556,31 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
556556
emitCxxConditional(os, [&] {
557557
// FIXME: Expose Swift with @expose by default.
558558
bool enableCxx = frontendOpts.ClangHeaderExposedDecls.has_value() ||
559-
frontendOpts.EnableExperimentalCxxInteropInClangHeader ||
560559
M->DeclContext::getASTContext().LangOpts.EnableCXXInterop;
561560
if (!enableCxx)
562561
return;
563562
// Include the shim header only in the C++ mode.
564563
ClangSyntaxPrinter(os).printIncludeForShimHeader(
565564
"_SwiftCxxInteroperability.h");
566565

566+
// Explicit @expose attribute is required only when the user specifies
567+
// -clang-header-expose-decls flag.
568+
// FIXME: should we detect any presence of @expose and require it then?
567569
bool requiresExplicitExpose =
570+
frontendOpts.ClangHeaderExposedDecls.has_value() &&
571+
(*frontendOpts.ClangHeaderExposedDecls ==
572+
FrontendOptions::ClangHeaderExposeBehavior::HasExposeAttr ||
573+
*frontendOpts.ClangHeaderExposedDecls ==
574+
FrontendOptions::ClangHeaderExposeBehavior::
575+
HasExposeAttrOrImplicitDeps);
576+
// Swift stdlib dependencies are emitted into the same header when
577+
// -clang-header-expose-decls flag is not specified, or when it allows
578+
// implicit dependency emission.
579+
bool addStdlibDepsInline =
568580
!frontendOpts.ClangHeaderExposedDecls.has_value() ||
569581
*frontendOpts.ClangHeaderExposedDecls ==
570-
FrontendOptions::ClangHeaderExposeBehavior::HasExposeAttr;
571-
// Default dependency behavior is used when the -clang-header-expose-decls
572-
// flag is not specified.
573-
bool defaultDependencyBehavior =
574-
!frontendOpts.ClangHeaderExposedDecls.has_value();
582+
FrontendOptions::ClangHeaderExposeBehavior::
583+
HasExposeAttrOrImplicitDeps;
575584

576585
std::string moduleContentsBuf;
577586
llvm::raw_string_ostream moduleContents{moduleContentsBuf};
@@ -582,7 +591,7 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
582591
writeImports(os, deps.imports, *M, bridgingHeader, frontendOpts,
583592
clangHeaderSearchInfo, /*useCxxImport=*/true);
584593
// Embed the standard library directly.
585-
if (defaultDependencyBehavior && deps.dependsOnStandardLibrary) {
594+
if (addStdlibDepsInline && deps.dependsOnStandardLibrary) {
586595
assert(!M->isStdlibModule());
587596
SwiftToClangInteropContext interopContext(
588597
*M->getASTContext().getStdlibModule(), irGenOpts);
@@ -593,7 +602,7 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
593602
interopContext,
594603
/*requiresExposedAttribute=*/true);
595604
os << "#endif // " << macroGuard << "\n";
596-
}
605+
}
597606

598607
os << moduleContents.str();
599608
});

0 commit comments

Comments
 (0)