Skip to content

Commit e0eec4d

Browse files
authored
Merge pull request swiftlang#40923 from hyp/emit-cxx-interface-option
[interop] add an option to emit C++ header interface for a module
2 parents 0bf1389 + 6486c3c commit e0eec4d

16 files changed

+183
-30
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ ERROR(error_mode_cannot_emit_reference_dependencies,none,
119119
"this mode does not support emitting reference dependency files", ())
120120
ERROR(error_mode_cannot_emit_header,none,
121121
"this mode does not support emitting Objective-C headers", ())
122+
ERROR(error_mode_cannot_emit_cxx_header,none,
123+
"this mode does not support emitting C++ headers", ())
122124
ERROR(error_mode_cannot_emit_loaded_module_trace,none,
123125
"this mode does not support emitting the loaded module trace", ())
124126
ERROR(error_mode_cannot_emit_module,none,

include/swift/Basic/SupplementaryOutputPaths.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ struct SupplementaryOutputPaths {
3131
/// \sa swift::printAsObjC
3232
std::string ObjCHeaderOutputPath;
3333

34+
/// The path to which we should emit a C++ header for the module.
35+
///
36+
/// Currently only makes sense when the compiler has whole module knowledge.
37+
/// The modes for which it makes sense include both WMO and the "merge
38+
/// modules" job that happens after the normal compilation jobs. That's where
39+
/// the header is emitted in single-file mode, since it needs whole-module
40+
/// information.
41+
///
42+
/// \sa swift::printAsCxx
43+
std::string CxxHeaderOutputPath;
44+
3445
/// The path to which we should emit a serialized module.
3546
/// It is valid whenever there are any inputs.
3647
///
@@ -160,7 +171,9 @@ struct SupplementaryOutputPaths {
160171
/// Apply a given function for each existing (non-empty string) supplementary output
161172
void forEachSetOutput(llvm::function_ref<void(const std::string&)> fn) const {
162173
if (!ObjCHeaderOutputPath.empty())
163-
fn(ObjCHeaderOutputPath);
174+
fn(ObjCHeaderOutputPath);
175+
if (!CxxHeaderOutputPath.empty())
176+
fn(CxxHeaderOutputPath);
164177
if (!ModuleOutputPath.empty())
165178
fn(ModuleOutputPath);
166179
if (!ModuleSourceInfoOutputPath.empty())
@@ -196,14 +209,16 @@ struct SupplementaryOutputPaths {
196209
}
197210

198211
bool empty() const {
199-
return ObjCHeaderOutputPath.empty() && ModuleOutputPath.empty() &&
200-
ModuleDocOutputPath.empty() && DependenciesFilePath.empty() &&
212+
return ObjCHeaderOutputPath.empty() && CxxHeaderOutputPath.empty() &&
213+
ModuleOutputPath.empty() && ModuleDocOutputPath.empty() &&
214+
DependenciesFilePath.empty() &&
201215
ReferenceDependenciesFilePath.empty() &&
202216
SerializedDiagnosticsPath.empty() && LoadedModuleTracePath.empty() &&
203217
TBDPath.empty() && ModuleInterfaceOutputPath.empty() &&
204-
ModuleSourceInfoOutputPath.empty() && ABIDescriptorOutputPath.empty() &&
205-
ModuleSemanticInfoOutputPath.empty() &&
206-
YAMLOptRecordPath.empty() && BitstreamOptRecordPath.empty();
218+
ModuleSourceInfoOutputPath.empty() &&
219+
ABIDescriptorOutputPath.empty() &&
220+
ModuleSemanticInfoOutputPath.empty() && YAMLOptRecordPath.empty() &&
221+
BitstreamOptRecordPath.empty();
207222
}
208223
};
209224
} // namespace swift

include/swift/Frontend/Frontend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class CompilerInvocation {
388388
std::string getOutputFilenameForAtMostOnePrimary() const;
389389
std::string getMainInputFilenameForDebugInfoForAtMostOnePrimary() const;
390390
std::string getObjCHeaderOutputPathForAtMostOnePrimary() const;
391+
std::string getCxxHeaderOutputPathForAtMostOnePrimary() const;
391392
std::string getModuleOutputPathForAtMostOnePrimary() const;
392393
std::string
393394
getReferenceDependenciesFilePathForPrimary(StringRef filename) const;

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ class FrontendInputsAndOutputs {
250250
bool hasDependenciesPath() const;
251251
bool hasReferenceDependenciesPath() const;
252252
bool hasObjCHeaderOutputPath() const;
253+
bool hasCxxHeaderOutputPath() const;
253254
bool hasLoadedModuleTracePath() const;
254255
bool hasModuleOutputPath() const;
255256
bool hasModuleDocOutputPath() const;

include/swift/Frontend/FrontendOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ class FrontendOptions {
450450
private:
451451
static bool canActionEmitDependencies(ActionType);
452452
static bool canActionEmitReferenceDependencies(ActionType);
453-
static bool canActionEmitObjCHeader(ActionType);
453+
static bool canActionEmitClangHeader(ActionType);
454454
static bool canActionEmitLoadedModuleTrace(ActionType);
455455
static bool canActionEmitModule(ActionType);
456456
static bool canActionEmitModuleDoc(ActionType);

include/swift/Option/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,14 @@ def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
532532
SupplementaryOutput]>,
533533
MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;
534534

535+
def emit_cxx_header : Flag<["-"], "emit-cxx-header">,
536+
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>,
537+
HelpText<"Emit a C++ header file">;
538+
def emit_cxx_header_path : Separate<["-"], "emit-cxx-header-path">,
539+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
540+
SupplementaryOutput]>,
541+
MetaVarName<"<path>">, HelpText<"Emit a C++ header file to <path>">;
542+
535543
def static : Flag<["-"], "static">,
536544
Flags<[FrontendOption, ModuleInterfaceOption, NoInteractiveOption]>,
537545
HelpText<"Make this module statically linkable and make the output of -emit-library a static library.">;

include/swift/PrintAsObjC/PrintAsObjC.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ namespace swift {
2626
///
2727
/// Returns true on error.
2828
bool printAsObjC(raw_ostream &out, ModuleDecl *M, StringRef bridgingHeader);
29+
30+
/// Print the C++-compatible declarations in a module as a Clang header.
31+
///
32+
/// Returns true on error.
33+
bool printAsCXX(raw_ostream &os, ModuleDecl *M);
2934
}
3035

3136
#endif

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,11 +623,16 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
623623
diag::error_mode_cannot_emit_reference_dependencies);
624624
return true;
625625
}
626-
if (!FrontendOptions::canActionEmitObjCHeader(Opts.RequestedAction) &&
626+
if (!FrontendOptions::canActionEmitClangHeader(Opts.RequestedAction) &&
627627
Opts.InputsAndOutputs.hasObjCHeaderOutputPath()) {
628628
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
629629
return true;
630630
}
631+
if (!FrontendOptions::canActionEmitClangHeader(Opts.RequestedAction) &&
632+
Opts.InputsAndOutputs.hasCxxHeaderOutputPath()) {
633+
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_cxx_header);
634+
return true;
635+
}
631636
if (!FrontendOptions::canActionEmitLoadedModuleTrace(Opts.RequestedAction) &&
632637
Opts.InputsAndOutputs.hasLoadedModuleTracePath()) {
633638
Diags.diagnose(SourceLoc(),

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
310310

311311
auto objCHeaderOutput = getSupplementaryFilenamesFromArguments(
312312
options::OPT_emit_objc_header_path);
313+
auto cxxHeaderOutput =
314+
getSupplementaryFilenamesFromArguments(options::OPT_emit_cxx_header_path);
313315
auto moduleOutput =
314316
getSupplementaryFilenamesFromArguments(options::OPT_emit_module_path);
315317
auto moduleDocOutput =
@@ -339,8 +341,8 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
339341
options::OPT_emit_module_semantic_info_path);
340342
auto optRecordOutput = getSupplementaryFilenamesFromArguments(
341343
options::OPT_save_optimization_record_path);
342-
if (!objCHeaderOutput || !moduleOutput || !moduleDocOutput ||
343-
!dependenciesFile || !referenceDependenciesFile ||
344+
if (!objCHeaderOutput || !cxxHeaderOutput || !moduleOutput ||
345+
!moduleDocOutput || !dependenciesFile || !referenceDependenciesFile ||
344346
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD ||
345347
!moduleInterfaceOutput || !privateModuleInterfaceOutput ||
346348
!moduleSourceInfoOutput || !moduleSummaryOutput || !abiDescriptorOutput ||
@@ -354,6 +356,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
354356
for (unsigned i = 0; i < N; ++i) {
355357
SupplementaryOutputPaths sop;
356358
sop.ObjCHeaderOutputPath = (*objCHeaderOutput)[i];
359+
sop.CxxHeaderOutputPath = (*cxxHeaderOutput)[i];
357360
sop.ModuleOutputPath = (*moduleOutput)[i];
358361
sop.ModuleDocOutputPath = (*moduleDocOutput)[i];
359362
sop.DependenciesFilePath = (*dependenciesFile)[i];
@@ -439,6 +442,11 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
439442
file_types::TY_ObjCHeader, "",
440443
defaultSupplementaryOutputPathExcludingExtension);
441444

445+
auto cxxHeaderOutputPath = determineSupplementaryOutputFilename(
446+
OPT_emit_cxx_header, pathsFromArguments.CxxHeaderOutputPath,
447+
file_types::TY_ObjCHeader, "",
448+
defaultSupplementaryOutputPathExcludingExtension);
449+
442450
auto loadedModuleTracePath = determineSupplementaryOutputFilename(
443451
OPT_emit_loaded_module_trace, pathsFromArguments.LoadedModuleTracePath,
444452
file_types::TY_ModuleTrace, "",
@@ -493,6 +501,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
493501

494502
SupplementaryOutputPaths sop;
495503
sop.ObjCHeaderOutputPath = objcHeaderOutputPath;
504+
sop.CxxHeaderOutputPath = cxxHeaderOutputPath;
496505
sop.ModuleOutputPath = moduleOutputPath;
497506
sop.ModuleDocOutputPath = moduleDocOutputPath;
498507
sop.DependenciesFilePath = dependenciesFilePath;
@@ -578,6 +587,7 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
578587
return paths;
579588
const std::pair<file_types::ID, std::string &> typesAndStrings[] = {
580589
{file_types::TY_ObjCHeader, paths.ObjCHeaderOutputPath},
590+
{file_types::TY_ObjCHeader, paths.CxxHeaderOutputPath},
581591
{file_types::TY_SwiftModuleFile, paths.ModuleOutputPath},
582592
{file_types::TY_SwiftModuleDocFile, paths.ModuleDocOutputPath},
583593
{file_types::TY_SwiftSourceInfoFile, paths.ModuleSourceInfoOutputPath},
@@ -606,17 +616,16 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
606616
Optional<std::vector<SupplementaryOutputPaths>>
607617
SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap() const {
608618
if (Arg *A = Args.getLastArg(
609-
options::OPT_emit_objc_header_path,
610-
options::OPT_emit_module_path,
611-
options::OPT_emit_module_doc_path,
612-
options::OPT_emit_dependencies_path,
613-
options::OPT_emit_reference_dependencies_path,
614-
options::OPT_serialize_diagnostics_path,
615-
options::OPT_emit_loaded_module_trace_path,
616-
options::OPT_emit_module_interface_path,
617-
options::OPT_emit_private_module_interface_path,
618-
options::OPT_emit_module_source_info_path,
619-
options::OPT_emit_tbd_path)) {
619+
options::OPT_emit_objc_header_path, options::OPT_emit_cxx_header_path,
620+
options::OPT_emit_module_path, options::OPT_emit_module_doc_path,
621+
options::OPT_emit_dependencies_path,
622+
options::OPT_emit_reference_dependencies_path,
623+
options::OPT_serialize_diagnostics_path,
624+
options::OPT_emit_loaded_module_trace_path,
625+
options::OPT_emit_module_interface_path,
626+
options::OPT_emit_private_module_interface_path,
627+
options::OPT_emit_module_source_info_path,
628+
options::OPT_emit_tbd_path)) {
620629
Diags.diagnose(SourceLoc(),
621630
diag::error_cannot_have_supplementary_outputs,
622631
A->getSpelling(), "-supplementary-output-file-map");

lib/Frontend/Frontend.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ CompilerInvocation::getObjCHeaderOutputPathForAtMostOnePrimary() const {
9696
return getPrimarySpecificPathsForAtMostOnePrimary()
9797
.SupplementaryOutputs.ObjCHeaderOutputPath;
9898
}
99+
std::string
100+
CompilerInvocation::getCxxHeaderOutputPathForAtMostOnePrimary() const {
101+
return getPrimarySpecificPathsForAtMostOnePrimary()
102+
.SupplementaryOutputs.CxxHeaderOutputPath;
103+
}
99104
std::string CompilerInvocation::getModuleOutputPathForAtMostOnePrimary() const {
100105
return getPrimarySpecificPathsForAtMostOnePrimary()
101106
.SupplementaryOutputs.ModuleOutputPath;

0 commit comments

Comments
 (0)