Skip to content

Commit de5d500

Browse files
authored
Merge pull request #74940 from tshortli/private-module-interface-flags-6.0
[6.0] Change interface printing behaviors for `-package-name` and `-project-name`
2 parents aa9094e + 05a6d11 commit de5d500

File tree

8 files changed

+207
-59
lines changed

8 files changed

+207
-59
lines changed

include/swift/Frontend/ModuleInterfaceSupport.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#define SWIFT_COMPILER_VERSION_KEY "swift-compiler-version"
2222
#define SWIFT_MODULE_FLAGS_KEY "swift-module-flags"
2323
#define SWIFT_MODULE_FLAGS_IGNORABLE_KEY "swift-module-flags-ignorable"
24-
#define SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY "swift-module-flags-ignorable-private"
2524

2625
namespace swift {
2726

@@ -42,18 +41,26 @@ struct ModuleInterfaceOptions {
4241
/// [TODO: Clang-type-plumbing] This check should go away.
4342
bool PrintFullConvention = false;
4443

45-
/// Copy of all the command-line flags passed at .swiftinterface
46-
/// generation time, re-applied to CompilerInvocation when reading
47-
/// back .swiftinterface and reconstructing .swiftmodule.
48-
std::string Flags;
44+
struct InterfaceFlags {
45+
/// Copy of all the command-line flags passed at .swiftinterface
46+
/// generation time, re-applied to CompilerInvocation when reading
47+
/// back .swiftinterface and reconstructing .swiftmodule.
48+
std::string Flags = "";
4949

50-
/// Flags that should be emitted to the .swiftinterface file but are OK to be
51-
/// ignored by the earlier version of the compiler.
52-
std::string IgnorableFlags;
50+
/// Flags that should be emitted to the .swiftinterface file but are OK to
51+
/// be ignored by the earlier version of the compiler.
52+
std::string IgnorableFlags = "";
53+
};
5354

54-
/// Ignorable flags that should only be printed in .private.swiftinterface file;
55-
/// e.g. -package-name PACKAGE_ID
56-
std::string IgnorablePrivateFlags;
55+
/// Flags which appear in all .swiftinterface files.
56+
InterfaceFlags PublicFlags = {};
57+
58+
/// Flags which appear in both the private and package .swiftinterface files,
59+
/// but not the public interface.
60+
InterfaceFlags PrivateFlags = {};
61+
62+
/// Flags which appear only in the .package.swiftinterface.
63+
InterfaceFlags PackageFlags = {};
5764

5865
/// Print imports with both @_implementationOnly and @_spi, only applies
5966
/// when PrintSPIs is true.
@@ -62,6 +69,10 @@ struct ModuleInterfaceOptions {
6269
/// Print imports that are missing from the source and used in API.
6370
bool PrintMissingImports = true;
6471

72+
/// If true, package-name flag is not printed in either public or private
73+
/// interface file.
74+
bool DisablePackageNameForNonPackageInterface = false;
75+
6576
/// Intentionally print invalid syntax into the file.
6677
bool DebugPrintInvalidSyntax = false;
6778

include/swift/Option/Options.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ namespace options {
4242
SwiftAPIDigesterOption = (1 << 17),
4343
NewDriverOnlyOption = (1 << 18),
4444
ModuleInterfaceOptionIgnorable = (1 << 19),
45-
ModuleInterfaceOptionIgnorablePrivate = (1 << 20),
46-
ArgumentIsFileList = (1 << 21),
47-
CacheInvariant = (1 << 22),
45+
ArgumentIsFileList = (1 << 20),
46+
CacheInvariant = (1 << 21),
4847
};
4948

5049
enum ID {

include/swift/Option/Options.td

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,6 @@ def ModuleInterfaceOption : OptionFlag;
5656
// The option can be safely ignored by the older compiler.
5757
def ModuleInterfaceOptionIgnorable : OptionFlag;
5858

59-
// The option should be written into a .private.swiftinterface or
60-
// .package.swiftinterface module interface file, and read/parsed from
61-
// there when reconstituting a .swiftmodule from it.
62-
// The option can be safely ignored by the older compiler.
63-
def ModuleInterfaceOptionIgnorablePrivate : OptionFlag;
64-
6559
// The option causes the output of a supplementary output, or is the path option
6660
// for a supplementary output. E.g., `-emit-module` and `-emit-module-path`.
6761
def SupplementaryOutput : OptionFlag;
@@ -717,6 +711,11 @@ def disable_bridging_pch : Flag<["-"], "disable-bridging-pch">,
717711
Flags<[HelpHidden]>,
718712
HelpText<"Disable automatic generation of bridging PCH files">;
719713

714+
def disable_print_package_name_for_non_package_interface :
715+
Flag<["-"], "disable-print-package-name-for-non-package-interface">,
716+
Flags<[FrontendOption, NoDriverOption, ModuleInterfaceOption, HelpHidden]>,
717+
HelpText<"Disable adding package name to public or private interface">;
718+
720719
def lto : Joined<["-"], "lto=">,
721720
Flags<[FrontendOption, NoInteractiveOption]>,
722721
HelpText<"Specify the LTO type to either 'llvm-thin' or 'llvm-full'">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
419419
Args.hasArg(OPT_debug_emit_invalid_swiftinterface_syntax);
420420
Opts.PrintMissingImports =
421421
!Args.hasArg(OPT_disable_print_missing_imports_in_module_interface);
422+
Opts.DisablePackageNameForNonPackageInterface |= Args.hasArg(OPT_disable_print_package_name_for_non_package_interface);
422423

423424
if (const Arg *A = Args.getLastArg(OPT_library_level)) {
424425
StringRef contents = A->getValue();
@@ -434,6 +435,10 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
434435
/// Checks if an arg is generally allowed to be included
435436
/// in a module interface
436437
static bool ShouldIncludeModuleInterfaceArg(const Arg *A) {
438+
if (!A->getOption().hasFlag(options::ModuleInterfaceOption) &&
439+
!A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable))
440+
return false;
441+
437442
if (!A->getOption().matches(options::OPT_enable_experimental_feature))
438443
return true;
439444

@@ -444,46 +449,69 @@ static bool ShouldIncludeModuleInterfaceArg(const Arg *A) {
444449
return true;
445450
}
446451

452+
static bool IsPackageInterfaceFlag(const Arg *A, ArgList &Args) {
453+
return A->getOption().matches(options::OPT_package_name) &&
454+
Args.hasArg(
455+
options::OPT_disable_print_package_name_for_non_package_interface);
456+
}
457+
458+
static bool IsPrivateInterfaceFlag(const Arg *A, ArgList &Args) {
459+
return A->getOption().matches(options::OPT_project_name);
460+
}
461+
447462
/// Save a copy of any flags marked as ModuleInterfaceOption, if running
448463
/// in a mode that is going to emit a .swiftinterface file.
449464
static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
450465
FrontendOptions &FOpts,
451466
ArgList &Args, DiagnosticEngine &Diags) {
452467
if (!FOpts.InputsAndOutputs.hasModuleInterfaceOutputPath())
453468
return;
454-
ArgStringList RenderedArgs;
455-
ArgStringList RenderedArgsIgnorable;
456-
ArgStringList RenderedArgsIgnorablePrivate;
469+
470+
struct RenderedInterfaceArgs {
471+
ArgStringList Standard = {};
472+
ArgStringList Ignorable = {};
473+
};
474+
475+
RenderedInterfaceArgs PublicArgs{};
476+
RenderedInterfaceArgs PrivateArgs{};
477+
RenderedInterfaceArgs PackageArgs{};
478+
479+
auto interfaceArgListForArg = [&](Arg *A) -> ArgStringList & {
480+
bool ignorable =
481+
A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable);
482+
if (IsPackageInterfaceFlag(A, Args))
483+
return ignorable ? PackageArgs.Ignorable : PackageArgs.Standard;
484+
485+
if (IsPrivateInterfaceFlag(A, Args))
486+
return ignorable ? PrivateArgs.Ignorable : PrivateArgs.Standard;
487+
488+
return ignorable ? PublicArgs.Ignorable : PublicArgs.Standard;
489+
};
490+
457491
for (auto A : Args) {
458492
if (!ShouldIncludeModuleInterfaceArg(A))
459493
continue;
460494

461-
if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorablePrivate)) {
462-
A->render(Args, RenderedArgsIgnorablePrivate);
463-
} else if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) {
464-
A->render(Args, RenderedArgsIgnorable);
465-
} else if (A->getOption().hasFlag(options::ModuleInterfaceOption)) {
466-
A->render(Args, RenderedArgs);
467-
}
468-
}
469-
{
470-
llvm::raw_string_ostream OS(Opts.Flags);
471-
interleave(RenderedArgs,
472-
[&](const char *Argument) { PrintArg(OS, Argument, StringRef()); },
473-
[&] { OS << " "; });
474-
}
475-
{
476-
llvm::raw_string_ostream OS(Opts.IgnorablePrivateFlags);
477-
interleave(RenderedArgsIgnorablePrivate,
478-
[&](const char *Argument) { PrintArg(OS, Argument, StringRef()); },
479-
[&] { OS << " "; });
480-
}
481-
{
482-
llvm::raw_string_ostream OS(Opts.IgnorableFlags);
483-
interleave(RenderedArgsIgnorable,
484-
[&](const char *Argument) { PrintArg(OS, Argument, StringRef()); },
485-
[&] { OS << " "; });
486-
}
495+
ArgStringList &ArgList = interfaceArgListForArg(A);
496+
A->render(Args, ArgList);
497+
}
498+
499+
auto updateInterfaceOpts = [](ModuleInterfaceOptions::InterfaceFlags &Flags,
500+
RenderedInterfaceArgs &RenderedArgs) {
501+
auto printFlags = [](std::string &str, ArgStringList argList) {
502+
llvm::raw_string_ostream OS(str);
503+
interleave(
504+
argList,
505+
[&](const char *Argument) { PrintArg(OS, Argument, StringRef()); },
506+
[&] { OS << " "; });
507+
};
508+
printFlags(Flags.Flags, RenderedArgs.Standard);
509+
printFlags(Flags.IgnorableFlags, RenderedArgs.Ignorable);
510+
};
511+
512+
updateInterfaceOpts(Opts.PublicFlags, PublicArgs);
513+
updateInterfaceOpts(Opts.PrivateFlags, PrivateArgs);
514+
updateInterfaceOpts(Opts.PackageFlags, PackageArgs);
487515
}
488516

489517
enum class CxxCompatMode {

lib/Frontend/ModuleInterfaceSupport.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ static void printToolVersionAndFlagsComment(raw_ostream &out,
5959
<< InterfaceFormatVersion << "\n";
6060
out << "// " SWIFT_COMPILER_VERSION_KEY ": "
6161
<< ToolsVersion << "\n";
62-
out << "// " SWIFT_MODULE_FLAGS_KEY ": "
63-
<< Opts.Flags;
62+
out << "// " SWIFT_MODULE_FLAGS_KEY ": " << Opts.PublicFlags.Flags;
63+
64+
if (Opts.InterfaceContentMode >= PrintOptions::InterfaceMode::Private &&
65+
!Opts.PrivateFlags.Flags.empty())
66+
out << " " << Opts.PrivateFlags.Flags;
67+
68+
if (Opts.InterfaceContentMode >= PrintOptions::InterfaceMode::Package &&
69+
!Opts.PackageFlags.Flags.empty())
70+
out << " " << Opts.PackageFlags.Flags;
6471

6572
// Insert additional -module-alias flags
6673
if (Opts.AliasModuleNames) {
@@ -96,15 +103,28 @@ static void printToolVersionAndFlagsComment(raw_ostream &out,
96103
}
97104
out << "\n";
98105

99-
if (!Opts.IgnorableFlags.empty()) {
100-
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_KEY ": "
101-
<< Opts.IgnorableFlags << "\n";
102-
}
106+
// Add swift-module-flags-ignorable: if non-empty.
107+
{
108+
llvm::SmallVector<StringRef, 4> ignorableFlags;
109+
110+
if (!Opts.PublicFlags.IgnorableFlags.empty())
111+
ignorableFlags.push_back(Opts.PublicFlags.IgnorableFlags);
103112

104-
auto hasPrivateIgnorableFlags = !Opts.printPublicInterface() && !Opts.IgnorablePrivateFlags.empty();
105-
if (hasPrivateIgnorableFlags) {
106-
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY ": "
107-
<< Opts.IgnorablePrivateFlags << "\n";
113+
if (Opts.InterfaceContentMode >= PrintOptions::InterfaceMode::Private &&
114+
!Opts.PrivateFlags.IgnorableFlags.empty())
115+
ignorableFlags.push_back(Opts.PrivateFlags.IgnorableFlags);
116+
117+
if (Opts.InterfaceContentMode >= PrintOptions::InterfaceMode::Package &&
118+
!Opts.PackageFlags.IgnorableFlags.empty())
119+
ignorableFlags.push_back(Opts.PackageFlags.IgnorableFlags);
120+
121+
if (!ignorableFlags.empty()) {
122+
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_KEY ": ";
123+
llvm::interleave(
124+
ignorableFlags, [&out](StringRef str) { out << str; },
125+
[&out] { out << " "; });
126+
out << "\n";
127+
}
108128
}
109129
}
110130

lib/Sema/TypeCheckAttr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,12 @@ bool AttributeChecker::visitAbstractAccessControlAttr(
10581058
D->getASTContext().LangOpts.PackageName.empty() &&
10591059
File && File->Kind != SourceFileKind::Interface) {
10601060
// `package` modifier used outside of a package.
1061+
// Error if a source file contains a package decl or `package import` but
1062+
// no package-name is passed.
1063+
// Note that if the file containing the package decl is a public (or private)
1064+
// interface file, the decl must be @usableFromInline (or "inlinable"),
1065+
// effectively getting "public" visibility; in such case, package-name is
1066+
// not needed, and typecheck on those decls are skipped.
10611067
diagnose(attr->getLocation(), diag::access_control_requires_package_name,
10621068
isa<ValueDecl>(D), D);
10631069
return true;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %empty-directory(%t)
2+
3+
/// Do not print package-name for public or private interfaces
4+
// RUN: %target-build-swift -emit-module %s -I %t \
5+
// RUN: -module-name Bar -package-name foopkg \
6+
// RUN: -enable-library-evolution -swift-version 6 \
7+
// RUN: -package-name barpkg \
8+
// RUN: -Xfrontend -disable-print-package-name-for-non-package-interface \
9+
// RUN: -emit-module-interface-path %t/Bar.swiftinterface \
10+
// RUN: -emit-private-module-interface-path %t/Bar.private.swiftinterface \
11+
// RUN: -emit-package-module-interface-path %t/Bar.package.swiftinterface
12+
13+
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/Bar.swiftinterface
14+
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/Bar.private.swiftinterface
15+
// RUN: %FileCheck %s --check-prefix=CHECK-PACKAGE < %t/Bar.package.swiftinterface
16+
17+
// CHECK-PUBLIC-NOT: -package-name foopkg
18+
// CHECK-PUBLIC-NOT: -package-name barpkg
19+
// CHECK-PRIVATE-NOT: -package-name foopkg
20+
// CHECK-PRIVATE-NOT: -package-name barpkg
21+
// CHECK-PACKAGE-NOT: -package-name foopkg
22+
23+
// CHECK-PUBLIC: -enable-library-evolution -swift-version 6 -disable-print-package-name-for-non-package-interface -module-name Bar
24+
// CHECK-PRIVATE: -enable-library-evolution -swift-version 6 -disable-print-package-name-for-non-package-interface -module-name Bar
25+
// CHECK-PACKAGE: -enable-library-evolution -swift-version 6 -disable-print-package-name-for-non-package-interface -module-name Bar -package-name barpkg
26+
27+
/// Verify building modules from non-package interfaces succeeds without the package-name flag.
28+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Bar.swiftinterface -o %t/Bar.swiftmodule -module-name Bar
29+
// RUN: rm -rf %t/Bar.swiftmodule
30+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Bar.private.swiftinterface -o %t/Bar.swiftmodule -module-name Bar
31+
// RUN: rm -rf %t/Bar.swiftmodule
32+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Bar.package.swiftinterface -o %t/Bar.swiftmodule -module-name Bar
33+
34+
// RUN: rm -rf %t/Bar.swiftmodule
35+
// RUN: rm -rf %t/Bar.swiftinterface
36+
// RUN: rm -rf %t/Bar.private.swiftinterface
37+
// RUN: rm -rf %t/Bar.package.swiftinterface
38+
39+
/// By default, -package-name is printed in all interfaces.
40+
// RUN: %target-build-swift -emit-module %s -I %t \
41+
// RUN: -module-name Bar -package-name barpkg \
42+
// RUN: -enable-library-evolution -swift-version 6 \
43+
// RUN: -emit-module-interface-path %t/Bar.swiftinterface \
44+
// RUN: -emit-private-module-interface-path %t/Bar.private.swiftinterface \
45+
// RUN: -emit-package-module-interface-path %t/Bar.package.swiftinterface
46+
47+
// RUN: %FileCheck %s < %t/Bar.swiftinterface
48+
// RUN: %FileCheck %s < %t/Bar.private.swiftinterface
49+
// RUN: %FileCheck %s < %t/Bar.package.swiftinterface
50+
51+
// CHECK: -enable-library-evolution -package-name barpkg -swift-version 6 -module-name Bar
52+
53+
/// Building modules from non-package interfaces with package-name (default mode) should succeed.
54+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Bar.swiftinterface -o %t/Bar.swiftmodule -module-name Bar
55+
// RUN: rm -rf %t/Bar.swiftmodule
56+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Bar.private.swiftinterface -o %t/Bar.swiftmodule -module-name Bar
57+
// RUN: rm -rf %t/Bar.swiftmodule
58+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Bar.package.swiftinterface -o %t/Bar.swiftmodule -module-name Bar
59+
60+
public struct PubStruct {}
61+
@_spi(bar) public struct SPIStruct {}
62+
package struct PkgStruct {}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module %s -I %t \
4+
// RUN: -module-name Library -project-name ProjectName \
5+
// RUN: -enable-library-evolution -swift-version 5 \
6+
// RUN: -emit-module-interface-path %t/Library.swiftinterface \
7+
// RUN: -emit-private-module-interface-path %t/Library.private.swiftinterface \
8+
// RUN: -emit-package-module-interface-path %t/Library.package.swiftinterface
9+
10+
// RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -module-name Library
11+
// RUN: %target-swift-typecheck-module-from-interface(%t/Library.private.swiftinterface) -module-name Library
12+
// RUN: %target-swift-typecheck-module-from-interface(%t/Library.package.swiftinterface) -module-name Library
13+
14+
// RUN: %FileCheck %s < %t/Library.swiftinterface --check-prefix CHECK-PUBLIC
15+
// RUN: %FileCheck %s < %t/Library.private.swiftinterface --check-prefix CHECK-NONPUBLIC
16+
// RUN: %FileCheck %s < %t/Library.package.swiftinterface --check-prefix CHECK-NONPUBLIC
17+
18+
// CHECK-PUBLIC-NOT: -project-name
19+
20+
// CHECK-NONPUBLIC: swift-module-flags-ignorable:
21+
// CHECK-NONPUBLIC-SAME: -project-name ProjectName
22+
23+
public func foo() {}

0 commit comments

Comments
 (0)