diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index c8c098e2973f0..7c7044830f3d4 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -90,7 +90,7 @@ fn create_wrapper_function( .collect(); let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, from_name, false); - if tcx.sess.target.options.default_hidden_visibility { + if tcx.sess.default_hidden_visibility() { #[cfg(feature="master")] func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 798014d668e22..7acd18d69edda 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -76,7 +76,7 @@ pub(crate) unsafe fn codegen( // __rust_alloc_error_handler_should_panic let name = OomStrategy::SYMBOL; let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); - if tcx.sess.target.default_hidden_visibility { + if tcx.sess.default_hidden_visibility() { llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); } let val = tcx.sess.opts.unstable_opts.oom.should_panic(); @@ -85,7 +85,7 @@ pub(crate) unsafe fn codegen( let name = NO_ALLOC_SHIM_IS_UNSTABLE; let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); - if tcx.sess.target.default_hidden_visibility { + if tcx.sess.default_hidden_visibility() { llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); } let llval = llvm::LLVMConstInt(i8, 0, False); @@ -130,7 +130,7 @@ fn create_wrapper_function( None }; - if tcx.sess.target.default_hidden_visibility { + if tcx.sess.default_hidden_visibility() { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } if tcx.sess.must_emit_unwind_tables() { diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 164b12cf8d411..78c0725a63784 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -84,7 +84,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { fn_type: &'ll Type, ) -> &'ll Value { // Declare C ABI functions with the visibility used by C by default. - let visibility = if self.tcx.sess.target.default_hidden_visibility { + let visibility = if self.tcx.sess.default_hidden_visibility() { llvm::Visibility::Hidden } else { llvm::Visibility::Default @@ -107,7 +107,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { unnamed: llvm::UnnamedAddr, fn_type: &'ll Type, ) -> &'ll Value { - let visibility = if self.tcx.sess.target.default_hidden_visibility { + let visibility = if self.tcx.sess.default_hidden_visibility() { llvm::Visibility::Hidden } else { llvm::Visibility::Default diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ce58b2ab06170..25fa2b375473e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -748,6 +748,7 @@ fn test_unstable_options_tracking_hash() { tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); + tracked!(default_hidden_visibility, Some(true)); tracked!(dep_info_omit_d_target, true); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index c2b307910e42b..e06935d4e4762 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -883,7 +883,7 @@ fn mono_item_visibility<'tcx>( } fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility { - if !tcx.sess.target.default_hidden_visibility { + if !tcx.sess.default_hidden_visibility() { return Visibility::Default; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d666c5d4d702c..a3835c085dac7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1552,6 +1552,8 @@ options! { "compress debug info sections (none, zlib, zstd, default: none)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), + default_hidden_visibility: Option = (None, parse_opt_bool, [TRACKED], + "overrides the `default_hidden_visibility` setting of the target"), dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves (default: no)"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 24c7459392abe..69b861ea38068 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -961,6 +961,14 @@ impl Session { termize::dimensions().map_or(default_column_width, |(w, _)| w) } } + + /// Whether the default visibility of symbols should be "hidden" rather than "default". + pub fn default_hidden_visibility(&self) -> bool { + self.opts + .unstable_opts + .default_hidden_visibility + .unwrap_or(self.target.options.default_hidden_visibility) + } } // JUSTIFICATION: defn of the suggested wrapper fns diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 24893bda9e7c4..a78df69f187ee 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2094,7 +2094,11 @@ pub struct TargetOptions { pub no_builtins: bool, /// The default visibility for symbols in this target should be "hidden" - /// rather than "default" + /// rather than "default". + /// + /// This value typically shouldn't be accessed directly, but through + /// the `rustc_session::Session::default_hidden_visibility` method, which + /// allows `rustc` users to override this setting using cmdline flags. pub default_hidden_visibility: bool, /// Whether a .debug_gdb_scripts section will be added to the output object file diff --git a/src/doc/unstable-book/src/compiler-flags/default-hidden-visibility.md b/src/doc/unstable-book/src/compiler-flags/default-hidden-visibility.md new file mode 100644 index 0000000000000..579add4a9d985 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/default-hidden-visibility.md @@ -0,0 +1,12 @@ +# `default-hidden-visibility` + +The tracking issue for this feature is: https://github.com/rust-lang/compiler-team/issues/656 + +------------------------ + +This flag can be used to override the target's +[`default_hidden_visibility`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_target/spec/struct.TargetOptions.html#structfield.default_hidden_visibility) +setting. +Using `-Zdefault_hidden_visibility=yes` is roughly equivalent to Clang's +[`-fvisibility=hidden`](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fvisibility) +cmdline flag. diff --git a/tests/codegen/default-hidden-visibility.rs b/tests/codegen/default-hidden-visibility.rs new file mode 100644 index 0000000000000..9e5e545f0d939 --- /dev/null +++ b/tests/codegen/default-hidden-visibility.rs @@ -0,0 +1,31 @@ +// Verifies that `Session::default_hidden_visibility` is affected when using the related cmdline +// flag. This is a regression test for https://github.com/rust-lang/compiler-team/issues/656. See +// also https://github.com/rust-lang/rust/issues/73295 and +// https://github.com/rust-lang/rust/issues/37530. + +// revisions:DEFAULT YES NO +//[YES] compile-flags: -Zdefault-hidden-visibility=yes +//[NO] compile-flags: -Zdefault-hidden-visibility=no + +// The test scenario is specifically about visibility of symbols exported out of dynamically linked +// libraries. +#![crate_type = "dylib"] + +// The test scenario needs to use a Rust-public, but non-explicitly-exported symbol +// (e.g. the test doesn't use `#[no_mangle]`, because currently it implies that +// the symbol should be exported; we don't want that - we want to test the *default* +// export setting instead). +#[used] +pub static tested_symbol: [u8; 6] = *b"foobar"; + +// Exact LLVM IR differs depending on the target triple (e.g. `hidden constant` +// vs `internal constant` vs `constant`). Because of this, we only apply the +// specific test expectations below to one specific target triple. If needed, +// additional targets can be covered by adding copies of this test file with +// a different `only-X` directive. +// +// only-x86_64-unknown-linux-gnu + +// DEFAULT: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = constant +// YES: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = hidden constant +// NO: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = constant