[cxx-interop] Emit C++ declarations only when '-clang-header-expose-public-decl' is enabled

This fix also ensures that we only emit C++ functions for now
This commit is contained in:
Alex Lorenz
2022-03-20 20:22:02 -07:00
parent 2e3aa87737
commit 80bc75ab9b
14 changed files with 43 additions and 21 deletions

View File

@@ -378,6 +378,10 @@ public:
/// '.../lib/swift', otherwise '.../lib/swift_static'.
bool UseSharedResourceFolder = true;
/// Indicates whether to expose all public declarations in the generated clang
/// header.
bool ExposePublicDeclsInClangHeader = false;
/// \return true if the given action only parses without doing other compilation steps.
static bool shouldActionOnlyParse(ActionType);

View File

@@ -1031,4 +1031,9 @@ def skip_import_in_public_interface:
HelpText<"Skip the import statement corresponding to a module name "
"when printing the public interface.">;
def clang_header_expose_public_decls:
Flag<["-"], "clang-header-expose-public-decls">,
HelpText<"Expose all public declarations in the generated clang header">,
Flags<[FrontendOption, HelpHidden]>;
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

View File

@@ -26,13 +26,14 @@ namespace swift {
/// The Objective-C compatible declarations are printed into a block that
/// ensures that those declarations are only usable when the header is
/// compiled in Objective-C mode.
/// The C++ compatible declarations are printed into a block that ensures
/// that those declarations are only usable when the header is compiled in
/// C++ mode.
/// The C++ compatible declarations are printed into a block that ensures
/// that those declarations are only usable when the header is compiled in
/// C++ mode.
///
/// Returns true on error.
bool printAsClangHeader(raw_ostream &out, ModuleDecl *M,
StringRef bridgingHeader);
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader);
}
#endif

View File

@@ -274,6 +274,8 @@ bool ArgsToFrontendOptionsConverter::convert(
Opts.EnableIncrementalDependencyVerifier |= Args.hasArg(OPT_verify_incremental_dependencies);
Opts.UseSharedResourceFolder = !Args.hasArg(OPT_use_static_resource_dir);
Opts.DisableBuildingInterface = Args.hasArg(OPT_disable_building_interface);
Opts.ExposePublicDeclsInClangHeader =
Args.hasArg(OPT_clang_header_expose_public_decls);
computeImportObjCHeaderOptions();
computeImplicitImportModuleNames(OPT_import_module, /*isTestable=*/false);

View File

@@ -179,13 +179,15 @@ static bool writeSIL(SILModule &SM, const PrimarySpecificPaths &PSPs,
///
/// \see swift::printAsClangHeader
static bool printAsClangHeaderIfNeeded(StringRef outputPath, ModuleDecl *M,
StringRef bridgingHeader) {
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader) {
if (outputPath.empty())
return false;
return withOutputFile(M->getDiags(), outputPath,
[&](raw_ostream &out) -> bool {
return printAsClangHeader(out, M, bridgingHeader);
});
return withOutputFile(
M->getDiags(), outputPath, [&](raw_ostream &out) -> bool {
return printAsClangHeader(out, M, bridgingHeader,
ExposePublicDeclsInClangHeader);
});
}
/// Prints the stable module interface for \p M to \p outputPath.
@@ -826,7 +828,8 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
}
hadAnyError |= printAsClangHeaderIfNeeded(
Invocation.getClangHeaderOutputPathForAtMostOnePrimary(),
Instance.getMainModule(), BridgingHeaderPathForPrint);
Instance.getMainModule(), BridgingHeaderPathForPrint,
opts.ExposePublicDeclsInClangHeader);
}
// Only want the header if there's been any errors, ie. there's not much

View File

@@ -124,13 +124,15 @@ class ModuleWriter {
std::vector<const Decl *> declsToWrite;
DelayedMemberSet delayedMembers;
DeclAndTypePrinter printer;
OutputLanguageMode outputLangMode;
public:
ModuleWriter(raw_ostream &os, raw_ostream &prologueOS,
llvm::SmallPtrSetImpl<ImportModuleTy> &imports, ModuleDecl &mod,
AccessLevel access, OutputLanguageMode outputLang)
: os(os), imports(imports), M(mod),
printer(M, os, prologueOS, delayedMembers, access, outputLang) {}
printer(M, os, prologueOS, delayedMembers, access, outputLang),
outputLangMode(outputLang) {}
/// Returns true if we added the decl's module to the import set, false if
/// the decl is a local decl.
@@ -576,7 +578,11 @@ public:
const Decl *D = declsToWrite.back();
bool success = true;
if (isa<ValueDecl>(D)) {
if (outputLangMode == OutputLanguageMode::Cxx) {
if (auto FD = dyn_cast<FuncDecl>(D))
success = writeFunc(FD);
// FIXME: Warn on unsupported exported decl.
} else if (isa<ValueDecl>(D)) {
if (auto CD = dyn_cast<ClassDecl>(D))
success = writeClass(CD);
else if (auto PD = dyn_cast<ProtocolDecl>(D))

View File

@@ -458,7 +458,8 @@ static std::string getModuleContentsCxxString(ModuleDecl &M) {
}
bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
StringRef bridgingHeader) {
StringRef bridgingHeader,
bool ExposePublicDeclsInClangHeader) {
llvm::PrettyStackTraceString trace("While generating Clang header");
SmallPtrSet<ImportModuleTy, 8> imports;
@@ -472,7 +473,7 @@ bool swift::printAsClangHeader(raw_ostream &os, ModuleDecl *M,
emitObjCConditional(os, [&] { os << objcModuleContents.str(); });
emitCxxConditional(os, [&] {
// FIXME: Expose Swift with @expose by default.
if (M->getASTContext().LangOpts.EnableCXXInterop) {
if (ExposePublicDeclsInClangHeader) {
os << getModuleContentsCxxString(*M);
}
});

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %S/cdecl.swift -typecheck -module-name CdeclFunctions -enable-cxx-interop -emit-clang-header-path %t/functions.h
// RUN: %target-swift-frontend %S/cdecl.swift -typecheck -module-name CdeclFunctions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/cdecl-execution.o
// RUN: %target-interop-build-swift %S/cdecl.swift -o %t/cdecl-execution -Xlinker %t/cdecl-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -module-name CdeclFunctions -enable-cxx-interop -emit-clang-header-path %t/cdecl.h
// RUN: %target-swift-frontend %s -typecheck -module-name CdeclFunctions -clang-header-expose-public-decls -emit-clang-header-path %t/cdecl.h
// RUN: %FileCheck %s < %t/cdecl.h
// RUN: %check-interop-cxx-header-in-clang(%t/cdecl.h)

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -enable-cxx-interop -emit-clang-header-path %t/functions.h
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h
// RUN: %FileCheck %s < %t/functions.h
// RUN: %check-interop-cxx-header-in-clang(%t/functions.h)

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %S/swift-functions.swift -typecheck -module-name Functions -enable-cxx-interop -emit-clang-header-path %t/functions.h
// RUN: %target-swift-frontend %S/swift-functions.swift -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-functions-execution.o
// RUN: %target-interop-build-swift %S/swift-functions.swift -o %t/swift-functions-execution -Xlinker %t/swift-functions-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -enable-cxx-interop -emit-clang-header-path %t/functions.h
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h
// RUN: %FileCheck %s < %t/functions.h
// RUN: %check-interop-cxx-header-in-clang(%t/functions.h)

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -module-name Test -enable-cxx-interop -emit-clang-header-path %t/empty.h
// RUN: %target-swift-frontend %s -typecheck -module-name Test -clang-header-expose-public-decls -emit-clang-header-path %t/empty.h
// RUN: %FileCheck %s < %t/empty.h
// RUN: %check-interop-cxx-header-in-clang(%t/empty.h)

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -typecheck -enable-cxx-interop -emit-clang-header-path %t/empty.h
// RUN: %target-swift-frontend %s -typecheck -clang-header-expose-public-decls -emit-clang-header-path %t/empty.h
// RUN: %FileCheck %s < %t/empty.h
// CHECK-LABEL: #ifndef EMPTY_SWIFT_H