Skip to content

Commit 4c24669

Browse files
committed
[interop][SwiftToCxx] add 'has-expose-attr-or-stdlib' mode to -clang-header-expose-decls flag
This mode allows the user to fallback to the old behavior that required @expose annotations, while still having standard library interfaces emitted in one header
1 parent 65a4674 commit 4c24669

File tree

5 files changed

+40
-15
lines changed

5 files changed

+40
-15
lines changed

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,10 @@ 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

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,18 @@ 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);
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);
318325
}
319326

320327
Opts.StrictImplicitModuleContext = Args.hasArg(OPT_strict_implicit_module_context,

lib/PrintAsClang/PrintAsClang.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -566,11 +566,18 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
566566
bool requiresExplicitExpose =
567567
!frontendOpts.ClangHeaderExposedDecls.has_value() ||
568568
*frontendOpts.ClangHeaderExposedDecls ==
569-
FrontendOptions::ClangHeaderExposeBehavior::HasExposeAttr;
570-
// Default dependency behavior is used when the -clang-header-expose-decls
571-
// flag is not specified.
572-
bool defaultDependencyBehavior =
573-
!frontendOpts.ClangHeaderExposedDecls.has_value();
569+
FrontendOptions::ClangHeaderExposeBehavior::HasExposeAttr ||
570+
*frontendOpts.ClangHeaderExposedDecls ==
571+
FrontendOptions::ClangHeaderExposeBehavior::
572+
HasExposeAttrOrImplicitDeps;
573+
// Swift stdlib dependencies are emitted into the same header when
574+
// -clang-header-expose-decls flag is not specified, or when it allows
575+
// implicit dependency emission.
576+
bool addStdlibDepsInline =
577+
!frontendOpts.ClangHeaderExposedDecls.has_value() ||
578+
*frontendOpts.ClangHeaderExposedDecls ==
579+
FrontendOptions::ClangHeaderExposeBehavior::
580+
HasExposeAttrOrImplicitDeps;
574581

575582
std::string moduleContentsBuf;
576583
llvm::raw_string_ostream moduleContents{moduleContentsBuf};
@@ -581,7 +588,7 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
581588
writeImports(os, deps.imports, *M, bridgingHeader, frontendOpts,
582589
clangHeaderSearchInfo, /*useCxxImport=*/true);
583590
// Embed the standard library directly.
584-
if (defaultDependencyBehavior && deps.dependsOnStandardLibrary) {
591+
if (addStdlibDepsInline && deps.dependsOnStandardLibrary) {
585592
assert(!M->isStdlibModule());
586593
SwiftToClangInteropContext interopContext(
587594
*M->getASTContext().getStdlibModule(), irGenOpts);
@@ -592,7 +599,7 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
592599
interopContext,
593600
/*requiresExposedAttribute=*/true);
594601
os << "#endif // " << macroGuard << "\n";
595-
}
602+
}
596603

597604
os << moduleContents.str();
598605
});

test/Interop/SwiftToCxx/expose-attr/expose-swift-decls-to-cxx.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
// RUN: %target-swift-frontend -parse-as-library %t/Expose.swiftinterface -enable-library-evolution -disable-objc-attr-requires-foundation-module -typecheck -module-name Expose -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr -emit-clang-header-path %t/expose.h
1515
// RUN: %FileCheck %s < %t/expose.h
1616

17+
// RUN: %empty-directory(%t)
18+
// RUN: %target-swift-frontend %s -enable-library-evolution -typecheck -emit-module-interface-path %t/Expose.swiftinterface -module-name Expose
19+
// RUN: %target-swift-frontend -parse-as-library %t/Expose.swiftinterface -enable-library-evolution -disable-objc-attr-requires-foundation-module -typecheck -module-name Expose -clang-header-expose-decls=has-expose-attr-or-stdlib -emit-clang-header-path %t/expose.h
20+
// RUN: %FileCheck %s < %t/expose.h
21+
1722
@_expose(Cxx)
1823
public func exposed1() {
1924
}

test/Interop/SwiftToCxx/stdlib/stdlib-dep-inline-in-cxx.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
// RUN: %empty-directory(%t)
22

33
// RUN: %target-swift-frontend -typecheck %s -typecheck -module-name UseOptional -enable-experimental-cxx-interop -emit-clang-header-path %t/stdlib.h
4-
// RUN: %target-swift-frontend -typecheck %s -typecheck -module-name UseOptional2 -enable-experimental-cxx-interop -emit-clang-header-path %t/stdlib2.h
5-
64
// RUN: %FileCheck %s < %t/stdlib.h
75

6+
// RUN: %target-swift-frontend -typecheck %s -typecheck -module-name UseOptional -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -emit-clang-header-path %t/stdlib_expose_flag.h
7+
// RUN: %FileCheck %s < %t/stdlib_expose_flag.h
8+
9+
// RUN: %target-swift-frontend -typecheck %s -typecheck -module-name UseOptional2 -enable-experimental-cxx-interop -emit-clang-header-path %t/stdlib2.h
10+
811
// RUN: cat %t/stdlib.h %t/stdlib2.h > %t/two_includes.h
912

1013
// RUN: %check-interop-cxx-header-in-clang(-DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY %t/two_includes.h -Wno-unused-private-field -Wno-unused-function)

0 commit comments

Comments
 (0)