mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Introduce "-internal" variant of bridging header import flags
The flags "-import-bridging-header" and "-import-pch" import a bridging header, treating the contents as a public import. Introduce "internal-" variants of both flags that provide the same semantics, but are intended to treat the imported contents as if they came in through an internal import. This is just plumbing of the options for the moment.
This commit is contained in:
@@ -636,6 +636,8 @@ NOTE(dependency_scan_unexpected_variant_module_map_note, none,
|
||||
NOTE(dependency_scan_unexpected_variant_extra_arg_note, none,
|
||||
"%select{first|second}0 module command-line has extra argument: '%1'", (bool, StringRef))
|
||||
|
||||
ERROR(bridging_header_and_pch_internal_mismatch,none,
|
||||
"bridging header and precompiled header options mismatch on internal vs. public import", ())
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_MACROS
|
||||
#include "DefineDiagnosticMacros.h"
|
||||
|
||||
@@ -1046,6 +1046,10 @@ namespace swift {
|
||||
/// The bridging header PCH file.
|
||||
std::string BridgingHeaderPCH;
|
||||
|
||||
/// Whether the bridging header and PCH file are considered to be
|
||||
/// internal imports.
|
||||
bool BridgingHeaderIsInternal = false;
|
||||
|
||||
/// When automatically generating a precompiled header from the bridging
|
||||
/// header, place it in this directory.
|
||||
std::string PrecompiledHeaderOutputDir;
|
||||
|
||||
@@ -66,12 +66,16 @@ public:
|
||||
|
||||
bool isOutputFileDirectory() const;
|
||||
|
||||
/// An Objective-C header to import and make implicitly visible.
|
||||
/// A C header to import and make implicitly visible.
|
||||
std::string ImplicitObjCHeaderPath;
|
||||
|
||||
/// An Objective-C pch to import and make implicitly visible.
|
||||
/// A C pch to import and make implicitly visible.
|
||||
std::string ImplicitObjCPCHPath;
|
||||
|
||||
/// Whether the imported C header or precompiled header is considered
|
||||
/// an internal import (vs. the default, a public import).
|
||||
bool ImportHeaderAsInternal = false;
|
||||
|
||||
/// The map of aliases and real names of imported or referenced modules.
|
||||
llvm::StringMap<std::string> ModuleAliasMap;
|
||||
|
||||
|
||||
@@ -353,10 +353,19 @@ def import_bridging_header : Separate<["-"], "import-bridging-header">,
|
||||
def import_objc_header : Separate<["-"], "import-objc-header">,
|
||||
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
|
||||
Alias<import_bridging_header>;
|
||||
|
||||
def internal_import_bridging_header : Separate<["-"], "internal-import-bridging-header">,
|
||||
Flags<[FrontendOption, ArgumentIsPath]>,
|
||||
HelpText<"Imports an C header file as an internal import">;
|
||||
|
||||
def import_pch : Separate<["-"], "import-pch">,
|
||||
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
|
||||
HelpText<"Import bridging header PCH file">;
|
||||
|
||||
def internal_import_pch : Separate<["-"], "internal-import-pch">,
|
||||
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
|
||||
HelpText<"Import bridging header PCH file as internal">;
|
||||
|
||||
def pch_output_dir: Separate<["-"], "pch-output-dir">,
|
||||
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
|
||||
HelpText<"Directory to persist automatically created precompiled bridging headers">;
|
||||
|
||||
@@ -2714,6 +2714,7 @@ ClangImporter::Implementation::Implementation(
|
||||
DisableSwiftBridgeAttr(ctx.ClangImporterOpts.DisableSwiftBridgeAttr),
|
||||
BridgingHeaderExplicitlyRequested(
|
||||
!ctx.ClangImporterOpts.BridgingHeader.empty()),
|
||||
BridgingHeaderIsInternal(ctx.ClangImporterOpts.BridgingHeaderIsInternal),
|
||||
DisableOverlayModules(ctx.ClangImporterOpts.DisableOverlayModules),
|
||||
EnableClangSPI(ctx.ClangImporterOpts.EnableClangSPI),
|
||||
IsReadingBridgingPCH(false),
|
||||
|
||||
@@ -481,6 +481,7 @@ public:
|
||||
const bool ImportForwardDeclarations;
|
||||
const bool DisableSwiftBridgeAttr;
|
||||
const bool BridgingHeaderExplicitlyRequested;
|
||||
const bool BridgingHeaderIsInternal;
|
||||
const bool DisableOverlayModules;
|
||||
const bool EnableClangSPI;
|
||||
|
||||
|
||||
@@ -144,7 +144,8 @@ static void validateLegacyUnsupportedArgs(DiagnosticEngine &diags,
|
||||
|
||||
static void validateBridgingHeaderArgs(DiagnosticEngine &diags,
|
||||
const ArgList &args) {
|
||||
if (!args.hasArgNoClaim(options::OPT_import_bridging_header))
|
||||
if (!args.hasArgNoClaim(options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header))
|
||||
return;
|
||||
|
||||
if (args.hasArgNoClaim(options::OPT_import_underlying_module))
|
||||
@@ -1521,7 +1522,9 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
|
||||
if (Args.hasFlag(options::OPT_enable_bridging_pch,
|
||||
options::OPT_disable_bridging_pch,
|
||||
true)) {
|
||||
if (Arg *A = Args.getLastArg(options::OPT_import_bridging_header)) {
|
||||
if (Arg *A = Args.getLastArg(
|
||||
options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header)) {
|
||||
StringRef Value = A->getValue();
|
||||
auto Ty = TC.lookupTypeForExtension(llvm::sys::path::extension(Value));
|
||||
if (Ty == file_types::TY_ClangHeader) {
|
||||
|
||||
@@ -522,19 +522,28 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
addCommonFrontendArgs(context.OI, context.Output, context.Args, Arguments);
|
||||
addRuntimeLibraryFlags(context.OI, Arguments);
|
||||
|
||||
// Pass along an -import-objc-header arg, replacing the argument with the name
|
||||
// of any input PCH to the current action if one is present.
|
||||
if (context.Args.hasArgNoClaim(options::OPT_import_bridging_header)) {
|
||||
// Pass along an -(internal-)?import-bridging-header arg, replacing the
|
||||
// argument with the name of any input PCH to the current action if one is
|
||||
// present.
|
||||
if (context.Args.hasArgNoClaim(options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header)) {
|
||||
bool ForwardAsIs = true;
|
||||
bool bridgingPCHIsEnabled =
|
||||
context.Args.hasFlag(options::OPT_enable_bridging_pch,
|
||||
options::OPT_disable_bridging_pch, true);
|
||||
bool usePersistentPCH = bridgingPCHIsEnabled &&
|
||||
context.Args.hasArg(options::OPT_pch_output_dir);
|
||||
bool isInternalImport = context.Args.getLastArgNoClaim(
|
||||
options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header)
|
||||
->getOption().getID() == options::OPT_internal_import_bridging_header;
|
||||
if (!usePersistentPCH) {
|
||||
for (auto *IJ : context.Inputs) {
|
||||
if (!IJ->getOutput().getAnyOutputForType(file_types::TY_PCH).empty()) {
|
||||
Arguments.push_back("-import-objc-header");
|
||||
if (isInternalImport)
|
||||
Arguments.push_back("-internal-import-bridging-header");
|
||||
else
|
||||
Arguments.push_back("-import-bridging-header");
|
||||
addInputsOfType(Arguments, context.Inputs, context.Args,
|
||||
file_types::TY_PCH);
|
||||
ForwardAsIs = false;
|
||||
@@ -543,7 +552,8 @@ ToolChain::constructInvocation(const CompileJobAction &job,
|
||||
}
|
||||
}
|
||||
if (ForwardAsIs) {
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header);
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header);
|
||||
}
|
||||
if (usePersistentPCH) {
|
||||
context.Args.AddLastArg(Arguments, options::OPT_pch_output_dir);
|
||||
@@ -972,7 +982,8 @@ ToolChain::constructInvocation(const InterpretJobAction &job,
|
||||
addCommonFrontendArgs(context.OI, context.Output, context.Args, Arguments);
|
||||
addRuntimeLibraryFlags(context.OI, Arguments);
|
||||
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header);
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header);
|
||||
|
||||
context.Args.AddLastArg(Arguments, options::OPT_parse_sil);
|
||||
|
||||
@@ -1233,7 +1244,8 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
|
||||
options::OPT_omit_extension_block_symbols);
|
||||
context.Args.AddLastArg(Arguments, options::OPT_symbol_graph_minimum_access_level);
|
||||
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header);
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header);
|
||||
|
||||
Arguments.push_back("-module-name");
|
||||
Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
|
||||
@@ -1276,7 +1288,8 @@ ToolChain::constructInvocation(const VerifyModuleInterfaceJobAction &job,
|
||||
file_types::TY_SerializedDiagnostics,
|
||||
"-serialize-diagnostics-path");
|
||||
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header);
|
||||
context.Args.AddLastArg(Arguments, options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header);
|
||||
|
||||
Arguments.push_back("-module-name");
|
||||
Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
|
||||
@@ -1342,7 +1355,8 @@ ToolChain::constructInvocation(const REPLJobAction &job,
|
||||
addCommonFrontendArgs(context.OI, context.Output, context.Args, FrontendArgs);
|
||||
addRuntimeLibraryFlags(context.OI, FrontendArgs);
|
||||
|
||||
context.Args.AddLastArg(FrontendArgs, options::OPT_import_bridging_header);
|
||||
context.Args.AddLastArg(FrontendArgs, options::OPT_import_bridging_header,
|
||||
options::OPT_internal_import_bridging_header);
|
||||
context.Args.addAllArgs(FrontendArgs,
|
||||
{options::OPT_framework, options::OPT_L});
|
||||
ToolChain::addLinkedLibArgs(context.Args, FrontendArgs);
|
||||
|
||||
@@ -913,18 +913,40 @@ static inline bool isPCHFilenameExtension(StringRef path) {
|
||||
|
||||
void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() {
|
||||
using namespace options;
|
||||
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_bridging_header)) {
|
||||
// Legacy support for passing PCH file through `-import-objc-header`.
|
||||
bool hadNormalBridgingHeader = false;
|
||||
if (const Arg *A = Args.getLastArgNoClaim(
|
||||
OPT_import_bridging_header,
|
||||
OPT_internal_import_bridging_header)) {
|
||||
// Legacy support for passing PCH file through `-import-bridging-header`.
|
||||
if (isPCHFilenameExtension(A->getValue()))
|
||||
Opts.ImplicitObjCPCHPath = A->getValue();
|
||||
else
|
||||
Opts.ImplicitObjCHeaderPath = A->getValue();
|
||||
// If `-import-object-header` is used, it means the module has a direct
|
||||
// If `-import-bridging-header` is used, it means the module has a direct
|
||||
// bridging header dependency and it can be serialized into binary module.
|
||||
Opts.ModuleHasBridgingHeader |= true;
|
||||
|
||||
Opts.ImportHeaderAsInternal =
|
||||
A->getOption().getID() == OPT_internal_import_bridging_header;
|
||||
|
||||
hadNormalBridgingHeader = true;
|
||||
}
|
||||
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_pch))
|
||||
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_pch,
|
||||
OPT_internal_import_pch)) {
|
||||
Opts.ImplicitObjCPCHPath = A->getValue();
|
||||
|
||||
bool importAsInternal = A->getOption().getID() == OPT_internal_import_pch;
|
||||
|
||||
/// Don't let the bridging-header and precompiled-header options differ in
|
||||
/// whether they are treated as internal or public imports.
|
||||
if (hadNormalBridgingHeader &&
|
||||
importAsInternal != Opts.ImportHeaderAsInternal) {
|
||||
Diags.diagnose(SourceLoc(),
|
||||
diag::bridging_header_and_pch_internal_mismatch);
|
||||
}
|
||||
|
||||
Opts.ImportHeaderAsInternal = importAsInternal;
|
||||
}
|
||||
}
|
||||
void ArgsToFrontendOptionsConverter::
|
||||
computeImplicitImportModuleNames(OptSpecifier id, bool isTestable) {
|
||||
|
||||
@@ -363,6 +363,8 @@ setBridgingHeaderFromFrontendOptions(ClangImporterOptions &ImporterOpts,
|
||||
if (!FrontendOpts.InputsAndOutputs.hasInputs())
|
||||
return;
|
||||
|
||||
ImporterOpts.BridgingHeaderIsInternal = FrontendOpts.ImportHeaderAsInternal;
|
||||
|
||||
// If we aren't asked to output a bridging header, we don't need to set this.
|
||||
if (ImporterOpts.PrecompiledHeaderOutputDir.empty())
|
||||
return;
|
||||
@@ -2109,10 +2111,24 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args,
|
||||
else if (Args.hasArg(OPT_emit_pcm) || Args.hasArg(OPT_dump_pcm))
|
||||
Opts.Mode = ClangImporterOptions::Modes::PrecompiledModule;
|
||||
|
||||
if (auto *A = Args.getLastArg(OPT_import_bridging_header))
|
||||
bool hadNormalBridgingHeader = false;
|
||||
if (auto *A = Args.getLastArg(OPT_import_bridging_header,
|
||||
OPT_internal_import_bridging_header)) {
|
||||
Opts.BridgingHeader = A->getValue();
|
||||
if (auto *A = Args.getLastArg(OPT_import_pch))
|
||||
Opts.BridgingHeaderIsInternal =
|
||||
A->getOption().getID() == OPT_internal_import_bridging_header;
|
||||
}
|
||||
if (auto *A = Args.getLastArg(OPT_import_pch, OPT_internal_import_pch)) {
|
||||
Opts.BridgingHeaderPCH = A->getValue();
|
||||
bool importAsInternal = A->getOption().getID() == OPT_internal_import_pch;
|
||||
if (hadNormalBridgingHeader &&
|
||||
importAsInternal != Opts.BridgingHeaderIsInternal) {
|
||||
Diags.diagnose(SourceLoc(),
|
||||
diag::bridging_header_and_pch_internal_mismatch);
|
||||
}
|
||||
Opts.BridgingHeaderIsInternal = importAsInternal;
|
||||
}
|
||||
|
||||
Opts.DisableSwiftBridgeAttr |= Args.hasArg(OPT_disable_swift_bridge_attr);
|
||||
|
||||
Opts.DisableOverlayModules |= Args.hasArg(OPT_emit_imported_modules);
|
||||
|
||||
3
test/ClangImporter/Inputs/c-bridging-header.h
Normal file
3
test/ClangImporter/Inputs/c-bridging-header.h
Normal file
@@ -0,0 +1,3 @@
|
||||
typedef struct {
|
||||
double x, y;
|
||||
} MyPoint;
|
||||
50
test/ClangImporter/InternalBridgingHeader/pch.swift
Normal file
50
test/ClangImporter/InternalBridgingHeader/pch.swift
Normal file
@@ -0,0 +1,50 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: mkdir -p %t/tmp
|
||||
|
||||
// First test the explicit frontend-based bridging PCH generation and use works
|
||||
// RUN: %target-swift-frontend -emit-pch -o %t/c-bridging-header.pch %S/../Inputs/c-bridging-header.h
|
||||
// RUN: %target-typecheck-verify-swift -internal-import-bridging-header %t/c-bridging-header.pch
|
||||
|
||||
// Now test the driver-automated version is inert when disabled
|
||||
// Output path of the PCH differs in the new driver, so force SWIFT_USE_OLD_DRIVER for now.
|
||||
// RUN: env TMPDIR=%t/tmp/ SWIFT_USE_OLD_DRIVER=1 %target-swiftc_driver -typecheck -disable-bridging-pch -save-temps %s -internal-import-bridging-header %S/../Inputs/c-bridging-header.h
|
||||
// RUN: not ls %t/tmp/*.pch >/dev/null 2>&1
|
||||
|
||||
// Test the driver-automated version works by default
|
||||
// Output path of the PCH differs in the new driver, so force SWIFT_USE_OLD_DRIVER for now.
|
||||
// RUN: env TMPDIR=%t/tmp/ SWIFT_USE_OLD_DRIVER=1 %target-swiftc_driver -typecheck -save-temps %s -internal-import-bridging-header %S/../Inputs/c-bridging-header.h
|
||||
// RUN: ls %t/tmp/*.pch >/dev/null 2>&1
|
||||
// RUN: llvm-objdump --raw-clang-ast %t/tmp/*.pch | llvm-bcanalyzer -dump | %FileCheck %s
|
||||
// CHECK: ORIGINAL_FILE{{.*}}Inputs/c-bridging-header.h
|
||||
|
||||
// Test the driver-automated version deletes its PCH file when done
|
||||
// RUN: rm %t/tmp/*.pch
|
||||
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -typecheck %s -internal-import-bridging-header %S/../Inputs/c-bridging-header.h
|
||||
// RUN: not ls %t/tmp/*.pch >/dev/null 2>&1
|
||||
|
||||
// Test -emit-pch invocation but with a persistent PCH
|
||||
// RUN: %target-swift-frontend -emit-pch -pch-output-dir %t/pch %S/../Inputs/c-bridging-header.h
|
||||
// RUN: %target-typecheck-verify-swift -internal-import-bridging-header %S/../Inputs/c-bridging-header.h -pch-output-dir %t/pch -pch-disable-validation
|
||||
// RUN: ls %t/pch/*.pch >/dev/null 2>&1
|
||||
|
||||
// Test implicit use of persistent PCH
|
||||
// RUN: %target-typecheck-verify-swift -internal-import-bridging-header %S/../Inputs/c-bridging-header.h -pch-output-dir %t/pch2
|
||||
// RUN: ls %t/pch2/*.pch >/dev/null 2>&1
|
||||
|
||||
// RUN: touch %t/header.with.dot.h
|
||||
// RUN: touch %t/test.swift
|
||||
// RUN: %target-swift-frontend -typecheck %t/test.swift -internal-import-bridging-header %t/header.with.dot.h -pch-output-dir %t/pch_with_dot -module-cache-path %t/mcp1
|
||||
// RUN: %target-swift-frontend -typecheck %t/test.swift -internal-import-bridging-header %t/header.with.dot.h -pch-output-dir %t/pch_with_dot -module-cache-path %t/mcp2
|
||||
// RUN: ls %t/pch_with_dot/*swift*clang*.pch | count 2
|
||||
|
||||
// Test the driver-automated version using persistent PCH
|
||||
// RUN: %target-swiftc_driver -typecheck -save-temps %s -internal-import-bridging-header %S/../Inputs/c-bridging-header.h -pch-output-dir %t/pch3
|
||||
// RUN: ls %t/pch3/*.pch >/dev/null 2>&1
|
||||
// RUN: llvm-objdump --raw-clang-ast %t/pch3/*.pch | llvm-bcanalyzer -dump | %FileCheck %s -check-prefix=PERSISTENT
|
||||
// PERSISTENT: ORIGINAL_FILE{{.*}}Inputs/c-bridging-header.h
|
||||
|
||||
// Test that -pch-disable-validation works in that it won't implicitly create a PCH
|
||||
// RUN: not %target-swift-frontend -typecheck %s -internal-import-bridging-header %S/../Inputs/c-bridging-header.h -pch-output-dir %t/no-pch -pch-disable-validation 2>&1 | %FileCheck %s -check-prefix=NO-VALIDATION
|
||||
// NO-VALIDATION: PCH file {{.*}} not found
|
||||
|
||||
func getX(point: MyPoint) -> Double { point.x }
|
||||
Reference in New Issue
Block a user