make it possible to silence linker warnings with a crate-level attribute
this was slightly complicated because codegen_ssa doesn't have access to a tcx.
This commit is contained in:
parent
c0822ed9b8
commit
537218afb2
5 changed files with 85 additions and 11 deletions
|
@ -15,13 +15,14 @@ use rustc_ast::CRATE_NODE_ID;
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::memmap::Mmap;
|
use rustc_data_structures::memmap::Mmap;
|
||||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||||
use rustc_errors::DiagCtxtHandle;
|
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
|
||||||
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
|
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
|
||||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::LintDiagnostic;
|
||||||
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
|
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
|
||||||
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
|
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
|
use rustc_middle::lint::lint_level;
|
||||||
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||||
|
@ -30,6 +31,7 @@ use rustc_session::config::{
|
||||||
OutputType, PrintKind, SplitDwarfKind, Strip,
|
OutputType, PrintKind, SplitDwarfKind, Strip,
|
||||||
};
|
};
|
||||||
use rustc_session::cstore::DllImport;
|
use rustc_session::cstore::DllImport;
|
||||||
|
use rustc_session::lint::builtin::LINKER_MESSAGES;
|
||||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||||
use rustc_session::search_paths::PathKind;
|
use rustc_session::search_paths::PathKind;
|
||||||
use rustc_session::utils::NativeLibKind;
|
use rustc_session::utils::NativeLibKind;
|
||||||
|
@ -750,7 +752,7 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(codegen_ssa_linker_output)]
|
#[diag(codegen_ssa_linker_output)]
|
||||||
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
|
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
|
||||||
/// end up with inconsistent languages within the same diagnostic.
|
/// end up with inconsistent languages within the same diagnostic.
|
||||||
|
@ -1038,6 +1040,13 @@ fn link_natively(
|
||||||
sess.dcx().abort_if_errors();
|
sess.dcx().abort_if_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (level, src) = codegen_results.crate_info.lint_levels.linker_messages;
|
||||||
|
let lint = |msg| {
|
||||||
|
lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| {
|
||||||
|
LinkerOutput { inner: msg }.decorate_lint(diag)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
if !prog.stderr.is_empty() {
|
if !prog.stderr.is_empty() {
|
||||||
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
|
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
|
||||||
let stderr = escape_string(&prog.stderr);
|
let stderr = escape_string(&prog.stderr);
|
||||||
|
@ -1046,12 +1055,10 @@ fn link_natively(
|
||||||
.strip_prefix("warning: ")
|
.strip_prefix("warning: ")
|
||||||
.unwrap_or(&stderr)
|
.unwrap_or(&stderr)
|
||||||
.replace(": warning: ", ": ");
|
.replace(": warning: ", ": ");
|
||||||
sess.dcx().emit_warn(LinkerOutput { inner: format!("linker stderr: {stderr}") });
|
lint(format!("linker stderr: {stderr}"));
|
||||||
}
|
}
|
||||||
if !prog.stdout.is_empty() && sess.opts.verbose {
|
if !prog.stdout.is_empty() && sess.opts.verbose {
|
||||||
sess.dcx().emit_warn(LinkerOutput {
|
lint(format!("linker stdout: {}", escape_string(&prog.stdout)))
|
||||||
inner: format!("linker stdout: {}", escape_string(&prog.stdout)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
@ -29,18 +29,23 @@ use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::UnordMap;
|
||||||
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_hir::def_id::CrateNum;
|
use rustc_hir::def_id::CrateNum;
|
||||||
use rustc_macros::{Decodable, Encodable, HashStable};
|
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||||
use rustc_middle::dep_graph::WorkProduct;
|
use rustc_middle::dep_graph::WorkProduct;
|
||||||
|
use rustc_middle::lint::LintLevelSource;
|
||||||
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||||
use rustc_middle::middle::dependency_format::Dependencies;
|
use rustc_middle::middle::dependency_format::Dependencies;
|
||||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_middle::util::Providers;
|
use rustc_middle::util::Providers;
|
||||||
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
|
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
|
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
|
||||||
use rustc_session::cstore::{self, CrateSource};
|
use rustc_session::cstore::{self, CrateSource};
|
||||||
|
use rustc_session::lint::Level;
|
||||||
|
use rustc_session::lint::builtin::LINKER_MESSAGES;
|
||||||
use rustc_session::utils::NativeLibKind;
|
use rustc_session::utils::NativeLibKind;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
|
@ -303,3 +308,19 @@ impl CodegenResults {
|
||||||
Ok((codegen_results, outputs))
|
Ok((codegen_results, outputs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A list of lint levels used in codegen.
|
||||||
|
///
|
||||||
|
/// When using `-Z link-only`, we don't have access to the tcx and must work
|
||||||
|
/// solely from the `.rlink` file. `Lint`s are defined too early to be encodeable.
|
||||||
|
/// Instead, encode exactly the information we need.
|
||||||
|
#[derive(Copy, Clone, Debug, Encodable, Decodable)]
|
||||||
|
pub struct CodegenLintLevels {
|
||||||
|
linker_messages: (Level, LintLevelSource),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CodegenLintLevels {
|
||||||
|
pub fn from_tcx(tcx: TyCtxt<'_>) -> Self {
|
||||||
|
Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ declare_lint_pass! {
|
||||||
LARGE_ASSIGNMENTS,
|
LARGE_ASSIGNMENTS,
|
||||||
LATE_BOUND_LIFETIME_ARGUMENTS,
|
LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||||
LEGACY_DERIVE_HELPERS,
|
LEGACY_DERIVE_HELPERS,
|
||||||
|
LINKER_MESSAGES,
|
||||||
LONG_RUNNING_CONST_EVAL,
|
LONG_RUNNING_CONST_EVAL,
|
||||||
LOSSY_PROVENANCE_CASTS,
|
LOSSY_PROVENANCE_CASTS,
|
||||||
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
|
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
|
||||||
|
@ -4085,6 +4086,39 @@ declare_lint! {
|
||||||
"call to foreign functions or function pointers with FFI-unwind ABI"
|
"call to foreign functions or function pointers with FFI-unwind ABI"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// The `linker_messages` lint forwards warnings from the linker.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust,ignore (needs CLI args, platform-specific)
|
||||||
|
/// extern "C" {
|
||||||
|
/// fn foo();
|
||||||
|
/// }
|
||||||
|
/// fn main () { unsafe { foo(); } }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// On Linux, using `gcc -Wl,--warn-unresolved-symbols` as a linker, this will produce
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// warning: linker stderr: rust-lld: undefined symbol: foo
|
||||||
|
/// >>> referenced by rust_out.69edbd30df4ae57d-cgu.0
|
||||||
|
/// >>> rust_out.rust_out.69edbd30df4ae57d-cgu.0.rcgu.o:(rust_out::main::h3a90094b06757803)
|
||||||
|
/// |
|
||||||
|
/// = note: `#[warn(linker_messages)]` on by default
|
||||||
|
///
|
||||||
|
/// warning: 1 warning emitted
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// Linkers emit platform-specific and program-specific warnings that cannot be predicted in advance by the rust compiler.
|
||||||
|
/// They are forwarded by default, but can be disabled by adding `#![allow(linker_messages)]` at the crate root.
|
||||||
|
pub LINKER_MESSAGES,
|
||||||
|
Warn,
|
||||||
|
"warnings emitted at runtime by the target-specific linker program"
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `named_arguments_used_positionally` lint detects cases where named arguments are only
|
/// The `named_arguments_used_positionally` lint detects cases where named arguments are only
|
||||||
/// used positionally in format strings. This usage is valid but potentially very confusing.
|
/// used positionally in format strings. This usage is valid but potentially very confusing.
|
||||||
|
|
|
@ -161,7 +161,19 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation
|
||||||
/// Setting for how to handle a lint.
|
/// Setting for how to handle a lint.
|
||||||
///
|
///
|
||||||
/// See: <https://doc.rust-lang.org/rustc/lints/levels.html>
|
/// See: <https://doc.rust-lang.org/rustc/lints/levels.html>
|
||||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)]
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
PartialEq,
|
||||||
|
PartialOrd,
|
||||||
|
Eq,
|
||||||
|
Ord,
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
Encodable,
|
||||||
|
Decodable,
|
||||||
|
HashStable_Generic
|
||||||
|
)]
|
||||||
pub enum Level {
|
pub enum Level {
|
||||||
/// The `allow` level will not issue any message.
|
/// The `allow` level will not issue any message.
|
||||||
Allow,
|
Allow,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
use rustc_errors::{Diag, MultiSpan};
|
use rustc_errors::{Diag, MultiSpan};
|
||||||
use rustc_hir::{HirId, ItemLocalId};
|
use rustc_hir::{HirId, ItemLocalId};
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS};
|
use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS};
|
||||||
use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId};
|
use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId};
|
||||||
|
@ -15,7 +15,7 @@ use tracing::instrument;
|
||||||
use crate::ty::TyCtxt;
|
use crate::ty::TyCtxt;
|
||||||
|
|
||||||
/// How a lint level was set.
|
/// How a lint level was set.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, HashStable, Debug)]
|
||||||
pub enum LintLevelSource {
|
pub enum LintLevelSource {
|
||||||
/// Lint is at the default level as declared in rustc.
|
/// Lint is at the default level as declared in rustc.
|
||||||
Default,
|
Default,
|
||||||
|
@ -173,7 +173,7 @@ impl TyCtxt<'_> {
|
||||||
/// This struct represents a lint expectation and holds all required information
|
/// This struct represents a lint expectation and holds all required information
|
||||||
/// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after
|
/// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after
|
||||||
/// the `LateLintPass` has completed.
|
/// the `LateLintPass` has completed.
|
||||||
#[derive(Clone, Debug, HashStable)]
|
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
|
||||||
pub struct LintExpectation {
|
pub struct LintExpectation {
|
||||||
/// The reason for this expectation that can optionally be added as part of
|
/// The reason for this expectation that can optionally be added as part of
|
||||||
/// the attribute. It will be displayed as part of the lint message.
|
/// the attribute. It will be displayed as part of the lint message.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue