Skip to content

Commit 20832fd

Browse files
committed
Add -emit-public-type-metadata-accessors to work around metadata linkage bug.
IRGen can introduce calls to type metadata accessors for types that should not be visible to the current translate, which can manifest in linker errors within a module (for references to private types when whole module optimization is disabled) or across modules (for references to private/internal types in another module). Introduce a new compiler flag `-emit-public-type-metadata-accessors` that emits all type metadata accessors with public linkage, to work around the problem in affected projects. This flag is intended to go away once we have a proper solution. This bug has been around in Swift "forever", but compiling the overlays using -enable-resilience has exacerbated the problem and caused regressions. This is a short-term fix to rdar://problem/40229755 while we work on the correct long-term fix.
1 parent aa5cb47 commit 20832fd

File tree

7 files changed

+48
-0
lines changed

7 files changed

+48
-0
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ namespace swift {
223223
/// Enables key path resilience.
224224
bool EnableKeyPathResilience = false;
225225

226+
/// Enables public emission of private metadata accessors.
227+
bool EmitPublicTypeMetadataAccessors = false;
228+
226229
/// If set to true, the diagnosis engine can assume the emitted diagnostics
227230
/// will be used in editor. This usually leads to more aggressive fixit.
228231
bool DiagnosticsEditorMode = false;

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ def warn_swift3_objc_inference : Flag<["-"], "warn-swift3-objc-inference">,
355355
Alias<warn_swift3_objc_inference_complete>,
356356
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, HelpHidden]>;
357357

358+
def emit_public_type_metadata_accessors :
359+
Flag<["-"], "emit-public-type-metadata-accessors">,
360+
Flags<[FrontendOption]>,
361+
HelpText<"Emit all type metadata accessors as public">;
362+
358363
def Rpass_EQ : Joined<["-"], "Rpass=">,
359364
Flags<[FrontendOption]>,
360365
HelpText<"Report performed transformations by optimization passes whose "

lib/Driver/ToolChains.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
183183
options::OPT_warn_swift3_objc_inference_minimal,
184184
options::OPT_warn_swift3_objc_inference_complete);
185185
inputArgs.AddLastArg(arguments, options::OPT_typo_correction_limit);
186+
inputArgs.AddLastArg(arguments,
187+
options::OPT_emit_public_type_metadata_accessors);
186188
inputArgs.AddLastArg(arguments, options::OPT_enable_app_extension);
187189
inputArgs.AddLastArg(arguments, options::OPT_enable_testing);
188190
inputArgs.AddLastArg(arguments, options::OPT_g_Group);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
309309
}
310310
}
311311

312+
Opts.EmitPublicTypeMetadataAccessors =
313+
Args.hasArg(OPT_emit_public_type_metadata_accessors);
314+
312315
Opts.EnableNSKeyedArchiverDiagnostics =
313316
Args.hasFlag(OPT_enable_nskeyedarchiver_diagnostics,
314317
OPT_disable_nskeyedarchiver_diagnostics,

lib/IRGen/MetadataRequest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,17 @@ bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) {
589589
return false;
590590
}
591591

592+
/// Determine whether we should promote the type metadata access function
593+
/// for the given nominal type to "public".
594+
static bool promoteMetadataAccessFunctionToPublic(
595+
const NominalTypeDecl *nominal) {
596+
ASTContext &ctx = nominal->getASTContext();
597+
598+
// When -emit-public-type-metadata-accessors is provided, promote all
599+
// of the metadata access functions to public.
600+
return ctx.LangOpts.EmitPublicTypeMetadataAccessors;
601+
}
602+
592603
/// Return the standard access strategy for getting a non-dependent
593604
/// type metadata object.
594605
MetadataAccessStrategy irgen::getTypeMetadataAccessStrategy(CanType type) {
@@ -621,8 +632,12 @@ MetadataAccessStrategy irgen::getTypeMetadataAccessStrategy(CanType type) {
621632
case FormalLinkage::PublicUnique:
622633
return MetadataAccessStrategy::PublicUniqueAccessor;
623634
case FormalLinkage::HiddenUnique:
635+
if (promoteMetadataAccessFunctionToPublic(nominal))
636+
return MetadataAccessStrategy::PublicUniqueAccessor;
624637
return MetadataAccessStrategy::HiddenUniqueAccessor;
625638
case FormalLinkage::Private:
639+
if (promoteMetadataAccessFunctionToPublic(nominal))
640+
return MetadataAccessStrategy::PublicUniqueAccessor;
626641
return MetadataAccessStrategy::PrivateAccessor;
627642

628643
case FormalLinkage::PublicNonUnique:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
func foo() -> Any {
2+
return Wrapper()
3+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %swift -module-name test -target x86_64-apple-macosx10.9 -emit-ir -parse-stdlib -emit-public-type-metadata-accessors -primary-file %s %S/Inputs/emit_public_type_metadata_accessors_other.swift | %FileCheck --check-prefix=CHECK-PUBLIC %s
2+
3+
// RUN: %swift -module-name test -target x86_64-apple-macosx10.9 -emit-ir -parse-stdlib -primary-file %s %S/Inputs/emit_public_type_metadata_accessors_other.swift | %FileCheck --check-prefix=CHECK-NONPUBLIC %s
4+
5+
private class C { }
6+
7+
// CHECK-PUBLIC: define swiftcc %swift.metadata_response @"$S4test3Foo33_DEC9477CC6E8E6E7A9CE422B1DBE7EA4LLVMa"
8+
// CHECK-NONPUBLIC: define internal swiftcc %swift.metadata_response @"$S4test3Foo33_DEC9477CC6E8E6E7A9CE422B1DBE7EA4LLVMa"
9+
private struct Foo {
10+
private let c: C = C()
11+
}
12+
13+
public struct Wrapper {
14+
private let foo: Foo = Foo()
15+
}
16+
17+

0 commit comments

Comments
 (0)