lint: add bad opt access internal lint
Some command-line options accessible through `sess.opts` are best accessed through wrapper functions on `Session`, `TyCtxt` or otherwise, rather than through field access on the option struct in the `Session`. Adds a new lint which triggers on those options that should be accessed through a wrapper function so that this is prohibited. Options are annotated with a new attribute `rustc_lint_opt_deny_field_access` which can specify the error message (i.e. "use this other function instead") to be emitted. A simpler alternative would be to simply rename the options in the option type so that it is clear they should not be used, however this doesn't prevent uses, just discourages them. Another alternative would be to make the option fields private, and adding accessor functions on the option types, however the wrapper functions sometimes rely on additional state from `Session` or `TyCtxt` which wouldn't be available in an function on the option type, so the accessor would simply make the field available and its use would be discouraged too. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
f5e005f0ca
commit
7bab769b58
19 changed files with 509 additions and 300 deletions
|
@ -1,7 +1,7 @@
|
|||
use crate::cgu_reuse_tracker::CguReuseTracker;
|
||||
use crate::code_stats::CodeStats;
|
||||
pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
|
||||
use crate::config::{self, CrateType, OutputType, SwitchWithOptPath};
|
||||
use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
|
||||
use crate::parse::{add_feature_diagnostics, ParseSess};
|
||||
use crate::search_paths::{PathKind, SearchPath};
|
||||
use crate::{filesearch, lint};
|
||||
|
@ -583,11 +583,9 @@ impl Session {
|
|||
pub fn source_map(&self) -> &SourceMap {
|
||||
self.parse_sess.source_map()
|
||||
}
|
||||
pub fn verbose(&self) -> bool {
|
||||
self.opts.unstable_opts.verbose
|
||||
}
|
||||
|
||||
pub fn time_passes(&self) -> bool {
|
||||
self.opts.unstable_opts.time_passes || self.opts.unstable_opts.time
|
||||
self.opts.time_passes()
|
||||
}
|
||||
|
||||
/// Returns `true` if internal lints should be added to the lint store - i.e. if
|
||||
|
@ -597,29 +595,16 @@ impl Session {
|
|||
self.unstable_options() && !self.opts.actually_rustdoc
|
||||
}
|
||||
|
||||
pub fn instrument_mcount(&self) -> bool {
|
||||
self.opts.unstable_opts.instrument_mcount
|
||||
pub fn instrument_coverage(&self) -> bool {
|
||||
self.opts.cg.instrument_coverage() != InstrumentCoverage::Off
|
||||
}
|
||||
pub fn time_llvm_passes(&self) -> bool {
|
||||
self.opts.unstable_opts.time_llvm_passes
|
||||
|
||||
pub fn instrument_coverage_except_unused_generics(&self) -> bool {
|
||||
self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics
|
||||
}
|
||||
pub fn meta_stats(&self) -> bool {
|
||||
self.opts.unstable_opts.meta_stats
|
||||
}
|
||||
pub fn asm_comments(&self) -> bool {
|
||||
self.opts.unstable_opts.asm_comments
|
||||
}
|
||||
pub fn verify_llvm_ir(&self) -> bool {
|
||||
self.opts.unstable_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
|
||||
}
|
||||
pub fn print_llvm_passes(&self) -> bool {
|
||||
self.opts.unstable_opts.print_llvm_passes
|
||||
}
|
||||
pub fn binary_dep_depinfo(&self) -> bool {
|
||||
self.opts.unstable_opts.binary_dep_depinfo
|
||||
}
|
||||
pub fn mir_opt_level(&self) -> usize {
|
||||
self.opts.mir_opt_level()
|
||||
|
||||
pub fn instrument_coverage_except_unused_functions(&self) -> bool {
|
||||
self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedFunctions
|
||||
}
|
||||
|
||||
/// Gets the features enabled for the current compilation session.
|
||||
|
@ -637,103 +622,9 @@ impl Session {
|
|||
}
|
||||
}
|
||||
|
||||
/// Calculates the flavor of LTO to use for this compilation.
|
||||
pub fn lto(&self) -> config::Lto {
|
||||
// If our target has codegen requirements ignore the command line
|
||||
if self.target.requires_lto {
|
||||
return config::Lto::Fat;
|
||||
}
|
||||
|
||||
// If the user specified something, return that. If they only said `-C
|
||||
// lto` and we've for whatever reason forced off ThinLTO via the CLI,
|
||||
// then ensure we can't use a ThinLTO.
|
||||
match self.opts.cg.lto {
|
||||
config::LtoCli::Unspecified => {
|
||||
// The compiler was invoked without the `-Clto` flag. Fall
|
||||
// through to the default handling
|
||||
}
|
||||
config::LtoCli::No => {
|
||||
// The user explicitly opted out of any kind of LTO
|
||||
return config::Lto::No;
|
||||
}
|
||||
config::LtoCli::Yes | config::LtoCli::Fat | config::LtoCli::NoParam => {
|
||||
// All of these mean fat LTO
|
||||
return config::Lto::Fat;
|
||||
}
|
||||
config::LtoCli::Thin => {
|
||||
return if self.opts.cli_forced_thinlto_off {
|
||||
config::Lto::Fat
|
||||
} else {
|
||||
config::Lto::Thin
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Ok at this point the target doesn't require anything and the user
|
||||
// hasn't asked for anything. Our next decision is whether or not
|
||||
// we enable "auto" ThinLTO where we use multiple codegen units and
|
||||
// then do ThinLTO over those codegen units. The logic below will
|
||||
// either return `No` or `ThinLocal`.
|
||||
|
||||
// If processing command line options determined that we're incompatible
|
||||
// with ThinLTO (e.g., `-C lto --emit llvm-ir`) then return that option.
|
||||
if self.opts.cli_forced_thinlto_off {
|
||||
return config::Lto::No;
|
||||
}
|
||||
|
||||
// If `-Z thinlto` specified process that, but note that this is mostly
|
||||
// a deprecated option now that `-C lto=thin` exists.
|
||||
if let Some(enabled) = self.opts.unstable_opts.thinlto {
|
||||
if enabled {
|
||||
return config::Lto::ThinLocal;
|
||||
} else {
|
||||
return config::Lto::No;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's only one codegen unit and LTO isn't enabled then there's
|
||||
// no need for ThinLTO so just return false.
|
||||
if self.codegen_units() == 1 {
|
||||
return config::Lto::No;
|
||||
}
|
||||
|
||||
// Now we're in "defaults" territory. By default we enable ThinLTO for
|
||||
// optimized compiles (anything greater than O0).
|
||||
match self.opts.optimize {
|
||||
config::OptLevel::No => config::Lto::No,
|
||||
_ => config::Lto::ThinLocal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the panic strategy for this compile session. If the user explicitly selected one
|
||||
/// using '-C panic', use that, otherwise use the panic strategy defined by the target.
|
||||
pub fn panic_strategy(&self) -> PanicStrategy {
|
||||
self.opts.cg.panic.unwrap_or(self.target.panic_strategy)
|
||||
}
|
||||
pub fn fewer_names(&self) -> bool {
|
||||
if let Some(fewer_names) = self.opts.unstable_opts.fewer_names {
|
||||
fewer_names
|
||||
} else {
|
||||
let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
|
||||
|| self.opts.output_types.contains_key(&OutputType::Bitcode)
|
||||
// AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
|
||||
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
|
||||
!more_names
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unstable_options(&self) -> bool {
|
||||
self.opts.unstable_opts.unstable_options
|
||||
}
|
||||
pub fn is_nightly_build(&self) -> bool {
|
||||
self.opts.unstable_features.is_nightly_build()
|
||||
}
|
||||
pub fn is_sanitizer_cfi_enabled(&self) -> bool {
|
||||
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
|
||||
}
|
||||
pub fn overflow_checks(&self) -> bool {
|
||||
self.opts.cg.overflow_checks.unwrap_or(self.opts.debug_assertions)
|
||||
}
|
||||
|
||||
/// Check whether this compile session and crate type use static crt.
|
||||
pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool {
|
||||
|
@ -746,6 +637,8 @@ impl Session {
|
|||
let found_negative = requested_features.clone().any(|r| r == "-crt-static");
|
||||
let found_positive = requested_features.clone().any(|r| r == "+crt-static");
|
||||
|
||||
// JUSTIFICATION: necessary use of crate_types directly (see FIXME below)
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::bad_opt_access))]
|
||||
if found_positive || found_negative {
|
||||
found_positive
|
||||
} else if crate_type == Some(CrateType::ProcMacro)
|
||||
|
@ -760,18 +653,6 @@ impl Session {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn relocation_model(&self) -> RelocModel {
|
||||
self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
|
||||
}
|
||||
|
||||
pub fn code_model(&self) -> Option<CodeModel> {
|
||||
self.opts.cg.code_model.or(self.target.code_model)
|
||||
}
|
||||
|
||||
pub fn tls_model(&self) -> TlsModel {
|
||||
self.opts.unstable_opts.tls_model.unwrap_or(self.target.tls_model)
|
||||
}
|
||||
|
||||
pub fn is_wasi_reactor(&self) -> bool {
|
||||
self.target.options.os == "wasi"
|
||||
&& matches!(
|
||||
|
@ -780,49 +661,10 @@ impl Session {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn split_debuginfo(&self) -> SplitDebuginfo {
|
||||
self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo)
|
||||
}
|
||||
|
||||
pub fn stack_protector(&self) -> StackProtector {
|
||||
if self.target.options.supports_stack_protector {
|
||||
self.opts.unstable_opts.stack_protector
|
||||
} else {
|
||||
StackProtector::None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target_can_use_split_dwarf(&self) -> bool {
|
||||
!self.target.is_like_windows && !self.target.is_like_osx
|
||||
}
|
||||
|
||||
pub fn must_emit_unwind_tables(&self) -> bool {
|
||||
// This is used to control the emission of the `uwtable` attribute on
|
||||
// LLVM functions.
|
||||
//
|
||||
// Unwind tables are needed when compiling with `-C panic=unwind`, but
|
||||
// LLVM won't omit unwind tables unless the function is also marked as
|
||||
// `nounwind`, so users are allowed to disable `uwtable` emission.
|
||||
// Historically rustc always emits `uwtable` attributes by default, so
|
||||
// even they can be disabled, they're still emitted by default.
|
||||
//
|
||||
// On some targets (including windows), however, exceptions include
|
||||
// other events such as illegal instructions, segfaults, etc. This means
|
||||
// that on Windows we end up still needing unwind tables even if the `-C
|
||||
// panic=abort` flag is passed.
|
||||
//
|
||||
// You can also find more info on why Windows needs unwind tables in:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
|
||||
//
|
||||
// If a target requires unwind tables, then they must be emitted.
|
||||
// Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>`
|
||||
// value, if it is provided, or disable them, if not.
|
||||
self.target.requires_uwtable
|
||||
|| self.opts.cg.force_unwind_tables.unwrap_or(
|
||||
self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
|
||||
format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
|
||||
}
|
||||
|
@ -968,6 +810,280 @@ impl Session {
|
|||
ret
|
||||
}
|
||||
|
||||
pub fn rust_2015(&self) -> bool {
|
||||
self.edition() == Edition::Edition2015
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 edition?
|
||||
pub fn rust_2018(&self) -> bool {
|
||||
self.edition() >= Edition::Edition2018
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2021 edition?
|
||||
pub fn rust_2021(&self) -> bool {
|
||||
self.edition() >= Edition::Edition2021
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2024 edition?
|
||||
pub fn rust_2024(&self) -> bool {
|
||||
self.edition() >= Edition::Edition2024
|
||||
}
|
||||
|
||||
/// Returns `true` if we cannot skip the PLT for shared library calls.
|
||||
pub fn needs_plt(&self) -> bool {
|
||||
// Check if the current target usually needs PLT to be enabled.
|
||||
// The user can use the command line flag to override it.
|
||||
let needs_plt = self.target.needs_plt;
|
||||
|
||||
let dbg_opts = &self.opts.unstable_opts;
|
||||
|
||||
let relro_level = dbg_opts.relro_level.unwrap_or(self.target.relro_level);
|
||||
|
||||
// Only enable this optimization by default if full relro is also enabled.
|
||||
// In this case, lazy binding was already unavailable, so nothing is lost.
|
||||
// This also ensures `-Wl,-z,now` is supported by the linker.
|
||||
let full_relro = RelroLevel::Full == relro_level;
|
||||
|
||||
// If user didn't explicitly forced us to use / skip the PLT,
|
||||
// then try to skip it where possible.
|
||||
dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
|
||||
}
|
||||
|
||||
/// Checks if LLVM lifetime markers should be emitted.
|
||||
pub fn emit_lifetime_markers(&self) -> bool {
|
||||
self.opts.optimize != config::OptLevel::No
|
||||
// AddressSanitizer uses lifetimes to detect use after scope bugs.
|
||||
// MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
|
||||
// HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
|
||||
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
|
||||
}
|
||||
|
||||
pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
|
||||
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
|
||||
.iter()
|
||||
.any(|kind| attr.has_name(*kind))
|
||||
}
|
||||
|
||||
pub fn contains_name(&self, attrs: &[Attribute], name: Symbol) -> bool {
|
||||
attrs.iter().any(|item| item.has_name(name))
|
||||
}
|
||||
|
||||
pub fn find_by_name<'a>(
|
||||
&'a self,
|
||||
attrs: &'a [Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<&'a Attribute> {
|
||||
attrs.iter().find(|attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn filter_by_name<'a>(
|
||||
&'a self,
|
||||
attrs: &'a [Attribute],
|
||||
name: Symbol,
|
||||
) -> impl Iterator<Item = &'a Attribute> {
|
||||
attrs.iter().filter(move |attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn first_attr_value_str_by_name(
|
||||
&self,
|
||||
attrs: &[Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<Symbol> {
|
||||
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
|
||||
}
|
||||
}
|
||||
|
||||
// JUSTIFICATION: defn of the suggested wrapper fns
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::bad_opt_access))]
|
||||
impl Session {
|
||||
pub fn verbose(&self) -> bool {
|
||||
self.opts.unstable_opts.verbose
|
||||
}
|
||||
|
||||
pub fn instrument_mcount(&self) -> bool {
|
||||
self.opts.unstable_opts.instrument_mcount
|
||||
}
|
||||
|
||||
pub fn time_llvm_passes(&self) -> bool {
|
||||
self.opts.unstable_opts.time_llvm_passes
|
||||
}
|
||||
|
||||
pub fn meta_stats(&self) -> bool {
|
||||
self.opts.unstable_opts.meta_stats
|
||||
}
|
||||
|
||||
pub fn asm_comments(&self) -> bool {
|
||||
self.opts.unstable_opts.asm_comments
|
||||
}
|
||||
|
||||
pub fn verify_llvm_ir(&self) -> bool {
|
||||
self.opts.unstable_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
|
||||
}
|
||||
|
||||
pub fn print_llvm_passes(&self) -> bool {
|
||||
self.opts.unstable_opts.print_llvm_passes
|
||||
}
|
||||
|
||||
pub fn binary_dep_depinfo(&self) -> bool {
|
||||
self.opts.unstable_opts.binary_dep_depinfo
|
||||
}
|
||||
|
||||
pub fn mir_opt_level(&self) -> usize {
|
||||
self.opts
|
||||
.unstable_opts
|
||||
.mir_opt_level
|
||||
.unwrap_or_else(|| if self.opts.optimize != OptLevel::No { 2 } else { 1 })
|
||||
}
|
||||
|
||||
/// Calculates the flavor of LTO to use for this compilation.
|
||||
pub fn lto(&self) -> config::Lto {
|
||||
// If our target has codegen requirements ignore the command line
|
||||
if self.target.requires_lto {
|
||||
return config::Lto::Fat;
|
||||
}
|
||||
|
||||
// If the user specified something, return that. If they only said `-C
|
||||
// lto` and we've for whatever reason forced off ThinLTO via the CLI,
|
||||
// then ensure we can't use a ThinLTO.
|
||||
match self.opts.cg.lto {
|
||||
config::LtoCli::Unspecified => {
|
||||
// The compiler was invoked without the `-Clto` flag. Fall
|
||||
// through to the default handling
|
||||
}
|
||||
config::LtoCli::No => {
|
||||
// The user explicitly opted out of any kind of LTO
|
||||
return config::Lto::No;
|
||||
}
|
||||
config::LtoCli::Yes | config::LtoCli::Fat | config::LtoCli::NoParam => {
|
||||
// All of these mean fat LTO
|
||||
return config::Lto::Fat;
|
||||
}
|
||||
config::LtoCli::Thin => {
|
||||
return if self.opts.cli_forced_thinlto_off {
|
||||
config::Lto::Fat
|
||||
} else {
|
||||
config::Lto::Thin
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Ok at this point the target doesn't require anything and the user
|
||||
// hasn't asked for anything. Our next decision is whether or not
|
||||
// we enable "auto" ThinLTO where we use multiple codegen units and
|
||||
// then do ThinLTO over those codegen units. The logic below will
|
||||
// either return `No` or `ThinLocal`.
|
||||
|
||||
// If processing command line options determined that we're incompatible
|
||||
// with ThinLTO (e.g., `-C lto --emit llvm-ir`) then return that option.
|
||||
if self.opts.cli_forced_thinlto_off {
|
||||
return config::Lto::No;
|
||||
}
|
||||
|
||||
// If `-Z thinlto` specified process that, but note that this is mostly
|
||||
// a deprecated option now that `-C lto=thin` exists.
|
||||
if let Some(enabled) = self.opts.unstable_opts.thinlto {
|
||||
if enabled {
|
||||
return config::Lto::ThinLocal;
|
||||
} else {
|
||||
return config::Lto::No;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's only one codegen unit and LTO isn't enabled then there's
|
||||
// no need for ThinLTO so just return false.
|
||||
if self.codegen_units() == 1 {
|
||||
return config::Lto::No;
|
||||
}
|
||||
|
||||
// Now we're in "defaults" territory. By default we enable ThinLTO for
|
||||
// optimized compiles (anything greater than O0).
|
||||
match self.opts.optimize {
|
||||
config::OptLevel::No => config::Lto::No,
|
||||
_ => config::Lto::ThinLocal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the panic strategy for this compile session. If the user explicitly selected one
|
||||
/// using '-C panic', use that, otherwise use the panic strategy defined by the target.
|
||||
pub fn panic_strategy(&self) -> PanicStrategy {
|
||||
self.opts.cg.panic.unwrap_or(self.target.panic_strategy)
|
||||
}
|
||||
|
||||
pub fn fewer_names(&self) -> bool {
|
||||
if let Some(fewer_names) = self.opts.unstable_opts.fewer_names {
|
||||
fewer_names
|
||||
} else {
|
||||
let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
|
||||
|| self.opts.output_types.contains_key(&OutputType::Bitcode)
|
||||
// AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
|
||||
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
|
||||
!more_names
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unstable_options(&self) -> bool {
|
||||
self.opts.unstable_opts.unstable_options
|
||||
}
|
||||
|
||||
pub fn is_nightly_build(&self) -> bool {
|
||||
self.opts.unstable_features.is_nightly_build()
|
||||
}
|
||||
|
||||
pub fn overflow_checks(&self) -> bool {
|
||||
self.opts.cg.overflow_checks.unwrap_or(self.opts.debug_assertions)
|
||||
}
|
||||
|
||||
pub fn relocation_model(&self) -> RelocModel {
|
||||
self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
|
||||
}
|
||||
|
||||
pub fn code_model(&self) -> Option<CodeModel> {
|
||||
self.opts.cg.code_model.or(self.target.code_model)
|
||||
}
|
||||
|
||||
pub fn tls_model(&self) -> TlsModel {
|
||||
self.opts.unstable_opts.tls_model.unwrap_or(self.target.tls_model)
|
||||
}
|
||||
|
||||
pub fn split_debuginfo(&self) -> SplitDebuginfo {
|
||||
self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo)
|
||||
}
|
||||
|
||||
pub fn stack_protector(&self) -> StackProtector {
|
||||
if self.target.options.supports_stack_protector {
|
||||
self.opts.unstable_opts.stack_protector
|
||||
} else {
|
||||
StackProtector::None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn must_emit_unwind_tables(&self) -> bool {
|
||||
// This is used to control the emission of the `uwtable` attribute on
|
||||
// LLVM functions.
|
||||
//
|
||||
// Unwind tables are needed when compiling with `-C panic=unwind`, but
|
||||
// LLVM won't omit unwind tables unless the function is also marked as
|
||||
// `nounwind`, so users are allowed to disable `uwtable` emission.
|
||||
// Historically rustc always emits `uwtable` attributes by default, so
|
||||
// even they can be disabled, they're still emitted by default.
|
||||
//
|
||||
// On some targets (including windows), however, exceptions include
|
||||
// other events such as illegal instructions, segfaults, etc. This means
|
||||
// that on Windows we end up still needing unwind tables even if the `-C
|
||||
// panic=abort` flag is passed.
|
||||
//
|
||||
// You can also find more info on why Windows needs unwind tables in:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
|
||||
//
|
||||
// If a target requires unwind tables, then they must be emitted.
|
||||
// Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>`
|
||||
// value, if it is provided, or disable them, if not.
|
||||
self.target.requires_uwtable
|
||||
|| self.opts.cg.force_unwind_tables.unwrap_or(
|
||||
self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the number of query threads that should be used for this
|
||||
/// compilation
|
||||
pub fn threads(&self) -> usize {
|
||||
|
@ -1048,109 +1164,17 @@ impl Session {
|
|||
self.opts.unstable_opts.teach && self.diagnostic().must_teach(code)
|
||||
}
|
||||
|
||||
pub fn rust_2015(&self) -> bool {
|
||||
self.opts.edition == Edition::Edition2015
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 edition?
|
||||
pub fn rust_2018(&self) -> bool {
|
||||
self.opts.edition >= Edition::Edition2018
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2021 edition?
|
||||
pub fn rust_2021(&self) -> bool {
|
||||
self.opts.edition >= Edition::Edition2021
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2024 edition?
|
||||
pub fn rust_2024(&self) -> bool {
|
||||
self.opts.edition >= Edition::Edition2024
|
||||
}
|
||||
|
||||
pub fn edition(&self) -> Edition {
|
||||
self.opts.edition
|
||||
}
|
||||
|
||||
/// Returns `true` if we cannot skip the PLT for shared library calls.
|
||||
pub fn needs_plt(&self) -> bool {
|
||||
// Check if the current target usually needs PLT to be enabled.
|
||||
// The user can use the command line flag to override it.
|
||||
let needs_plt = self.target.needs_plt;
|
||||
|
||||
let dbg_opts = &self.opts.unstable_opts;
|
||||
|
||||
let relro_level = dbg_opts.relro_level.unwrap_or(self.target.relro_level);
|
||||
|
||||
// Only enable this optimization by default if full relro is also enabled.
|
||||
// In this case, lazy binding was already unavailable, so nothing is lost.
|
||||
// This also ensures `-Wl,-z,now` is supported by the linker.
|
||||
let full_relro = RelroLevel::Full == relro_level;
|
||||
|
||||
// If user didn't explicitly forced us to use / skip the PLT,
|
||||
// then try to skip it where possible.
|
||||
dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
|
||||
}
|
||||
|
||||
/// Checks if LLVM lifetime markers should be emitted.
|
||||
pub fn emit_lifetime_markers(&self) -> bool {
|
||||
self.opts.optimize != config::OptLevel::No
|
||||
// AddressSanitizer uses lifetimes to detect use after scope bugs.
|
||||
// MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
|
||||
// HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
|
||||
|| self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
|
||||
}
|
||||
|
||||
pub fn link_dead_code(&self) -> bool {
|
||||
self.opts.cg.link_dead_code.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn instrument_coverage(&self) -> bool {
|
||||
self.opts.instrument_coverage()
|
||||
}
|
||||
|
||||
pub fn instrument_coverage_except_unused_generics(&self) -> bool {
|
||||
self.opts.instrument_coverage_except_unused_generics()
|
||||
}
|
||||
|
||||
pub fn instrument_coverage_except_unused_functions(&self) -> bool {
|
||||
self.opts.instrument_coverage_except_unused_functions()
|
||||
}
|
||||
|
||||
pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
|
||||
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
|
||||
.iter()
|
||||
.any(|kind| attr.has_name(*kind))
|
||||
}
|
||||
|
||||
pub fn contains_name(&self, attrs: &[Attribute], name: Symbol) -> bool {
|
||||
attrs.iter().any(|item| item.has_name(name))
|
||||
}
|
||||
|
||||
pub fn find_by_name<'a>(
|
||||
&'a self,
|
||||
attrs: &'a [Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<&'a Attribute> {
|
||||
attrs.iter().find(|attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn filter_by_name<'a>(
|
||||
&'a self,
|
||||
attrs: &'a [Attribute],
|
||||
name: Symbol,
|
||||
) -> impl Iterator<Item = &'a Attribute> {
|
||||
attrs.iter().filter(move |attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn first_attr_value_str_by_name(
|
||||
&self,
|
||||
attrs: &[Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<Symbol> {
|
||||
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
|
||||
}
|
||||
}
|
||||
|
||||
// JUSTIFICATION: part of session construction
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::bad_opt_access))]
|
||||
fn default_emitter(
|
||||
sopts: &config::Options,
|
||||
registry: rustc_errors::registry::Registry,
|
||||
|
@ -1235,6 +1259,8 @@ pub enum DiagnosticOutput {
|
|||
Raw(Box<dyn Write + Send>),
|
||||
}
|
||||
|
||||
// JUSTIFICATION: literally session construction
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::bad_opt_access))]
|
||||
pub fn build_session(
|
||||
sopts: config::Options,
|
||||
local_crate_source_file: Option<PathBuf>,
|
||||
|
@ -1356,11 +1382,8 @@ pub fn build_session(
|
|||
CguReuseTracker::new_disabled()
|
||||
};
|
||||
|
||||
let prof = SelfProfilerRef::new(
|
||||
self_profiler,
|
||||
sopts.unstable_opts.time_passes || sopts.unstable_opts.time,
|
||||
sopts.unstable_opts.time_passes,
|
||||
);
|
||||
let prof =
|
||||
SelfProfilerRef::new(self_profiler, sopts.time_passes(), sopts.unstable_opts.time_passes);
|
||||
|
||||
let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") {
|
||||
Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate,
|
||||
|
@ -1409,8 +1432,12 @@ pub fn build_session(
|
|||
sess
|
||||
}
|
||||
|
||||
// If it is useful to have a Session available already for validating a
|
||||
// commandline argument, you can do so here.
|
||||
/// Validate command line arguments with a `Session`.
|
||||
///
|
||||
/// If it is useful to have a Session available already for validating a commandline argument, you
|
||||
/// can do so here.
|
||||
// JUSTIFICATION: needs to access args to validate them
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::bad_opt_access))]
|
||||
fn validate_commandline_args_with_session_available(sess: &Session) {
|
||||
// Since we don't know if code in an rlib will be linked to statically or
|
||||
// dynamically downstream, rustc generates `__imp_` symbols that help linkers
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue