Merge remote-tracking branch 'upstream/master' into impl-16351-nightly
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
commit
f9d390d14a
4238 changed files with 96221 additions and 81870 deletions
|
@ -10,7 +10,6 @@ use crate::{early_error, early_warn, Session};
|
|||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::impl_stable_hash_via_hash;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
||||
use rustc_target::abi::{Align, TargetDataLayout};
|
||||
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
|
||||
|
@ -19,7 +18,7 @@ use rustc_serialize::json;
|
|||
|
||||
use crate::parse::CrateConfig;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST};
|
||||
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
|
||||
use rustc_span::source_map::{FileName, FilePathMapping};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::SourceFileHashAlgorithm;
|
||||
|
@ -36,66 +35,6 @@ use std::iter::{self, FromIterator};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::str::{self, FromStr};
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default, Encodable, Decodable)]
|
||||
pub struct SanitizerSet: u8 {
|
||||
const ADDRESS = 1 << 0;
|
||||
const LEAK = 1 << 1;
|
||||
const MEMORY = 1 << 2;
|
||||
const THREAD = 1 << 3;
|
||||
const HWADDRESS = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats a sanitizer set as a comma separated list of sanitizers' names.
|
||||
impl fmt::Display for SanitizerSet {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut first = true;
|
||||
for s in *self {
|
||||
let name = match s {
|
||||
SanitizerSet::ADDRESS => "address",
|
||||
SanitizerSet::LEAK => "leak",
|
||||
SanitizerSet::MEMORY => "memory",
|
||||
SanitizerSet::THREAD => "thread",
|
||||
SanitizerSet::HWADDRESS => "hwaddress",
|
||||
_ => panic!("unrecognized sanitizer {:?}", s),
|
||||
};
|
||||
if !first {
|
||||
f.write_str(",")?;
|
||||
}
|
||||
f.write_str(name)?;
|
||||
first = false;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for SanitizerSet {
|
||||
type Item = SanitizerSet;
|
||||
type IntoIter = std::vec::IntoIter<SanitizerSet>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
[
|
||||
SanitizerSet::ADDRESS,
|
||||
SanitizerSet::LEAK,
|
||||
SanitizerSet::MEMORY,
|
||||
SanitizerSet::THREAD,
|
||||
SanitizerSet::HWADDRESS,
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|&s| self.contains(s))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for SanitizerSet {
|
||||
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
||||
self.bits().hash_stable(ctx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
/// The different settings that the `-Z strip` flag can have.
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum Strip {
|
||||
|
@ -136,19 +75,21 @@ impl_stable_hash_via_hash!(OptLevel);
|
|||
|
||||
/// This is what the `LtoCli` values get mapped to after resolving defaults and
|
||||
/// and taking other command line options into account.
|
||||
///
|
||||
/// Note that linker plugin-based LTO is a different mechanism entirely.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Lto {
|
||||
/// Don't do any LTO whatsoever
|
||||
/// Don't do any LTO whatsoever.
|
||||
No,
|
||||
|
||||
/// Do a full crate graph LTO with ThinLTO
|
||||
/// Do a full-crate-graph (inter-crate) LTO with ThinLTO.
|
||||
Thin,
|
||||
|
||||
/// Do a local graph LTO with ThinLTO (only relevant for multiple codegen
|
||||
/// units).
|
||||
/// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is
|
||||
/// only relevant if multiple CGUs are used.
|
||||
ThinLocal,
|
||||
|
||||
/// Do a full crate graph LTO with "fat" LTO
|
||||
/// Do a full-crate-graph (inter-crate) LTO with "fat" LTO.
|
||||
Fat,
|
||||
}
|
||||
|
||||
|
@ -184,6 +125,37 @@ pub enum MirSpanview {
|
|||
Block,
|
||||
}
|
||||
|
||||
/// The different settings that the `-Z instrument-coverage` flag can have.
|
||||
///
|
||||
/// Coverage instrumentation now supports combining `-Z instrument-coverage`
|
||||
/// with compiler and linker optimization (enabled with `-O` or `-C opt-level=1`
|
||||
/// and higher). Nevertheless, there are many variables, depending on options
|
||||
/// selected, code structure, and enabled attributes. If errors are encountered,
|
||||
/// either while compiling or when generating `llvm-cov show` reports, consider
|
||||
/// lowering the optimization level, including or excluding `-C link-dead-code`,
|
||||
/// or using `-Z instrument-coverage=except-unused-functions` or `-Z
|
||||
/// instrument-coverage=except-unused-generics`.
|
||||
///
|
||||
/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the
|
||||
/// coverage map, it will not attempt to generate synthetic functions for unused
|
||||
/// (and not code-generated) functions (whether they are generic or not). As a
|
||||
/// result, non-codegenned functions will not be included in the coverage map,
|
||||
/// and will not appear, as covered or uncovered, in coverage reports.
|
||||
///
|
||||
/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map,
|
||||
/// unless the function has type parameters.
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum InstrumentCoverage {
|
||||
/// Default `-Z instrument-coverage` or `-Z instrument-coverage=statement`
|
||||
All,
|
||||
/// `-Z instrument-coverage=except-unused-generics`
|
||||
ExceptUnusedGenerics,
|
||||
/// `-Z instrument-coverage=except-unused-functions`
|
||||
ExceptUnusedFunctions,
|
||||
/// `-Z instrument-coverage=off` (or `no`, etc.)
|
||||
Off,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
pub enum LinkerPluginLto {
|
||||
LinkerPlugin(PathBuf),
|
||||
|
@ -474,6 +446,7 @@ impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec {
|
|||
}
|
||||
|
||||
impl Externs {
|
||||
/// Used for testing.
|
||||
pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
|
||||
Externs(data)
|
||||
}
|
||||
|
@ -485,6 +458,10 @@ impl Externs {
|
|||
pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExternEntry {
|
||||
|
@ -573,13 +550,6 @@ impl Input {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_input(&mut self) -> Option<&mut String> {
|
||||
match *self {
|
||||
Input::File(_) => None,
|
||||
Input::Str { ref mut input, .. } => Some(input),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source_name(&self) -> FileName {
|
||||
match *self {
|
||||
Input::File(ref ifile) => ifile.clone().into(),
|
||||
|
@ -734,6 +704,7 @@ impl Default for Options {
|
|||
remap_path_prefix: Vec::new(),
|
||||
edition: DEFAULT_EDITION,
|
||||
json_artifact_notifications: false,
|
||||
json_unused_externs: false,
|
||||
pretty: None,
|
||||
}
|
||||
}
|
||||
|
@ -747,12 +718,6 @@ impl Options {
|
|||
|| self.debugging_opts.query_dep_graph
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn enable_dep_node_debug_strs(&self) -> bool {
|
||||
cfg!(debug_assertions)
|
||||
&& (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info)
|
||||
}
|
||||
|
||||
pub fn file_path_mapping(&self) -> FilePathMapping {
|
||||
FilePathMapping::new(self.remap_path_prefix.clone())
|
||||
}
|
||||
|
@ -832,7 +797,7 @@ pub const fn default_lib_output() -> CrateType {
|
|||
CrateType::Rlib
|
||||
}
|
||||
|
||||
pub fn default_configuration(sess: &Session) -> CrateConfig {
|
||||
fn default_configuration(sess: &Session) -> CrateConfig {
|
||||
let end = &sess.target.endian;
|
||||
let arch = &sess.target.arch;
|
||||
let wordsz = sess.target.pointer_width.to_string();
|
||||
|
@ -927,7 +892,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
|
|||
user_cfg
|
||||
}
|
||||
|
||||
pub fn build_target_config(
|
||||
pub(super) fn build_target_config(
|
||||
opts: &Options,
|
||||
target_override: Option<Target>,
|
||||
sysroot: &PathBuf,
|
||||
|
@ -939,7 +904,7 @@ pub fn build_target_config(
|
|||
opts.error_format,
|
||||
&format!(
|
||||
"Error loading target specification: {}. \
|
||||
Use `--print target-list` for a list of built-in targets",
|
||||
Run `rustc --print target-list` for a list of built-in targets",
|
||||
e
|
||||
),
|
||||
)
|
||||
|
@ -1034,9 +999,6 @@ mod opt {
|
|||
pub fn flag_s(a: S, b: S, c: S) -> R {
|
||||
stable(longer(a, b), move |opts| opts.optflag(a, b, c))
|
||||
}
|
||||
pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R {
|
||||
stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
|
||||
}
|
||||
pub fn flagmulti_s(a: S, b: S, c: S) -> R {
|
||||
stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
|
||||
}
|
||||
|
@ -1047,15 +1009,6 @@ mod opt {
|
|||
pub fn multi(a: S, b: S, c: S, d: S) -> R {
|
||||
unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
|
||||
}
|
||||
pub fn flag(a: S, b: S, c: S) -> R {
|
||||
unstable(longer(a, b), move |opts| opts.optflag(a, b, c))
|
||||
}
|
||||
pub fn flagopt(a: S, b: S, c: S, d: S) -> R {
|
||||
unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
|
||||
}
|
||||
pub fn flagmulti(a: S, b: S, c: S) -> R {
|
||||
unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the "short" subset of the rustc command line options,
|
||||
|
@ -1255,15 +1208,23 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// Possible json config files
|
||||
pub struct JsonConfig {
|
||||
pub json_rendered: HumanReadableErrorType,
|
||||
pub json_artifact_notifications: bool,
|
||||
pub json_unused_externs: bool,
|
||||
}
|
||||
|
||||
/// Parse the `--json` flag.
|
||||
///
|
||||
/// The first value returned is how to render JSON diagnostics, and the second
|
||||
/// is whether or not artifact notifications are enabled.
|
||||
pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) {
|
||||
pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
|
||||
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
|
||||
HumanReadableErrorType::Default;
|
||||
let mut json_color = ColorConfig::Never;
|
||||
let mut json_artifact_notifications = false;
|
||||
let mut json_unused_externs = false;
|
||||
for option in matches.opt_strs("json") {
|
||||
// For now conservatively forbid `--color` with `--json` since `--json`
|
||||
// won't actually be emitting any colors and anything colorized is
|
||||
|
@ -1280,6 +1241,7 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool)
|
|||
"diagnostic-short" => json_rendered = HumanReadableErrorType::Short,
|
||||
"diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
|
||||
"artifacts" => json_artifact_notifications = true,
|
||||
"unused-externs" => json_unused_externs = true,
|
||||
s => early_error(
|
||||
ErrorOutputType::default(),
|
||||
&format!("unknown `--json` option `{}`", s),
|
||||
|
@ -1287,7 +1249,12 @@ pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool)
|
|||
}
|
||||
}
|
||||
}
|
||||
(json_rendered(json_color), json_artifact_notifications)
|
||||
|
||||
JsonConfig {
|
||||
json_rendered: json_rendered(json_color),
|
||||
json_artifact_notifications,
|
||||
json_unused_externs,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the `--error-format` flag.
|
||||
|
@ -1360,13 +1327,16 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
|
|||
};
|
||||
|
||||
if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
|
||||
early_error(
|
||||
ErrorOutputType::default(),
|
||||
&format!(
|
||||
"edition {} is unstable and only available with -Z unstable-options.",
|
||||
edition,
|
||||
),
|
||||
)
|
||||
let is_nightly = nightly_options::match_is_nightly_build(matches);
|
||||
let msg = if !is_nightly {
|
||||
format!(
|
||||
"the crate requires edition {}, but the latest edition supported by this Rust version is {}",
|
||||
edition, LATEST_STABLE_EDITION
|
||||
)
|
||||
} else {
|
||||
format!("edition {} is unstable and only available with -Z unstable-options", edition)
|
||||
};
|
||||
early_error(ErrorOutputType::default(), &msg)
|
||||
}
|
||||
|
||||
edition
|
||||
|
@ -1865,7 +1835,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
|
||||
let edition = parse_crate_edition(matches);
|
||||
|
||||
let (json_rendered, json_artifact_notifications) = parse_json(matches);
|
||||
let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } =
|
||||
parse_json(matches);
|
||||
|
||||
let error_format = parse_error_format(matches, color, json_rendered);
|
||||
|
||||
|
@ -1878,6 +1849,14 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
let mut debugging_opts = build_debugging_options(matches, error_format);
|
||||
check_debug_option_stability(&debugging_opts, error_format, json_rendered);
|
||||
|
||||
if !debugging_opts.unstable_options && json_unused_externs {
|
||||
early_error(
|
||||
error_format,
|
||||
"the `-Z unstable-options` flag must also be passed to enable \
|
||||
the flag `--json=unused-externs`",
|
||||
);
|
||||
}
|
||||
|
||||
let output_types = parse_output_types(&debugging_opts, matches, error_format);
|
||||
|
||||
let mut cg = build_codegen_options(matches, error_format);
|
||||
|
@ -1916,7 +1895,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
);
|
||||
}
|
||||
|
||||
if debugging_opts.instrument_coverage {
|
||||
if debugging_opts.instrument_coverage.is_some()
|
||||
&& debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off)
|
||||
{
|
||||
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
|
||||
early_error(
|
||||
error_format,
|
||||
|
@ -1942,23 +1923,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
}
|
||||
Some(SymbolManglingVersion::V0) => {}
|
||||
}
|
||||
|
||||
if debugging_opts.mir_opt_level > 1 {
|
||||
// Functions inlined during MIR transform can, at best, make it impossible to
|
||||
// effectively cover inlined functions, and, at worst, break coverage map generation
|
||||
// during LLVM codegen. For example, function counter IDs are only unique within a
|
||||
// function. Inlining after these counters are injected can produce duplicate counters,
|
||||
// resulting in an invalid coverage map (and ICE); so this option combination is not
|
||||
// allowed.
|
||||
early_warn(
|
||||
error_format,
|
||||
&format!(
|
||||
"`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
|
||||
is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
|
||||
debugging_opts.mir_opt_level,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
|
||||
|
@ -2053,6 +2017,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
remap_path_prefix,
|
||||
edition,
|
||||
json_artifact_notifications,
|
||||
json_unused_externs,
|
||||
pretty,
|
||||
}
|
||||
}
|
||||
|
@ -2077,6 +2042,7 @@ fn parse_pretty(
|
|||
("hir,identified", true) => Hir(PpHirMode::Identified),
|
||||
("hir,typed", true) => Hir(PpHirMode::Typed),
|
||||
("hir-tree", true) => HirTree,
|
||||
("thir-tree", true) => ThirTree,
|
||||
("mir", true) => Mir,
|
||||
("mir-cfg", true) => MirCFG,
|
||||
_ => {
|
||||
|
@ -2268,6 +2234,8 @@ pub enum PpMode {
|
|||
Hir(PpHirMode),
|
||||
/// `-Zunpretty=hir-tree`
|
||||
HirTree,
|
||||
/// `-Zunpretty=thir-tree`
|
||||
ThirTree,
|
||||
/// `-Zunpretty=mir`
|
||||
Mir,
|
||||
/// `-Zunpretty=mir-cfg`
|
||||
|
@ -2285,6 +2253,7 @@ impl PpMode {
|
|||
| AstTree(PpAstTreeMode::Expanded)
|
||||
| Hir(_)
|
||||
| HirTree
|
||||
| ThirTree
|
||||
| Mir
|
||||
| MirCFG => true,
|
||||
}
|
||||
|
@ -2292,7 +2261,7 @@ impl PpMode {
|
|||
|
||||
pub fn needs_analysis(&self) -> bool {
|
||||
use PpMode::*;
|
||||
matches!(*self, Mir | MirCFG)
|
||||
matches!(*self, Mir | MirCFG | ThirTree)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2316,8 +2285,8 @@ impl PpMode {
|
|||
/// how the hash should be calculated when adding a new command-line argument.
|
||||
crate mod dep_tracking {
|
||||
use super::{
|
||||
CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel,
|
||||
OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath,
|
||||
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
|
||||
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
|
||||
SymbolManglingVersion, TrimmedDefPaths,
|
||||
};
|
||||
use crate::lint;
|
||||
|
@ -2326,7 +2295,7 @@ crate mod dep_tracking {
|
|||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
|
||||
use rustc_target::spec::{RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
|
||||
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, TargetTriple, TlsModel};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::BTreeMap;
|
||||
use std::hash::Hash;
|
||||
|
@ -2370,6 +2339,7 @@ crate mod dep_tracking {
|
|||
impl_dep_tracking_hash_via_hash!(PathBuf);
|
||||
impl_dep_tracking_hash_via_hash!(lint::Level);
|
||||
impl_dep_tracking_hash_via_hash!(Option<bool>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<u32>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<usize>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<NonZeroUsize>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<String>);
|
||||
|
@ -2382,6 +2352,7 @@ crate mod dep_tracking {
|
|||
impl_dep_tracking_hash_via_hash!(Option<WasiExecModel>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<InstrumentCoverage>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
|
||||
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
|
||||
impl_dep_tracking_hash_via_hash!(CrateType);
|
||||
|
@ -2443,7 +2414,7 @@ crate mod dep_tracking {
|
|||
}
|
||||
|
||||
// This is a stable hash because BTreeMap is a sorted container
|
||||
pub fn stable_hash(
|
||||
crate fn stable_hash(
|
||||
sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
|
||||
hasher: &mut DefaultHasher,
|
||||
error_format: ErrorOutputType,
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(or_patterns)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::lint;
|
|||
use crate::search_paths::SearchPath;
|
||||
use crate::utils::NativeLibKind;
|
||||
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
|
||||
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
|
||||
|
||||
use rustc_feature::UnstableFeatures;
|
||||
|
@ -147,6 +147,9 @@ top_level_options!(
|
|||
// by the compiler.
|
||||
json_artifact_notifications: bool [TRACKED],
|
||||
|
||||
// `true` if we're emitting a JSON blob containing the unused externs
|
||||
json_unused_externs: bool [UNTRACKED],
|
||||
|
||||
pretty: Option<PpMode> [UNTRACKED],
|
||||
}
|
||||
);
|
||||
|
@ -248,9 +251,9 @@ macro_rules! options {
|
|||
pub const parse_list: &str = "a space-separated list of strings";
|
||||
pub const parse_opt_list: &str = parse_list;
|
||||
pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
|
||||
pub const parse_uint: &str = "a number";
|
||||
pub const parse_opt_uint: &str = parse_uint;
|
||||
pub const parse_threads: &str = parse_uint;
|
||||
pub const parse_number: &str = "a number";
|
||||
pub const parse_opt_number: &str = parse_number;
|
||||
pub const parse_threads: &str = parse_number;
|
||||
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
|
||||
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
|
||||
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
|
||||
|
@ -262,6 +265,7 @@ macro_rules! options {
|
|||
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
|
||||
pub const parse_optimization_fuel: &str = "crate=integer";
|
||||
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
|
||||
pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
|
||||
pub const parse_unpretty: &str = "`string` or `string=string`";
|
||||
pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0";
|
||||
pub const parse_lto: &str =
|
||||
|
@ -413,16 +417,16 @@ macro_rules! options {
|
|||
}
|
||||
}
|
||||
|
||||
/// Use this for any uint option that has a static default.
|
||||
fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool {
|
||||
/// Use this for any numeric option that has a static default.
|
||||
fn parse_number<T: Copy + FromStr>(slot: &mut T, v: Option<&str>) -> bool {
|
||||
match v.and_then(|s| s.parse().ok()) {
|
||||
Some(i) => { *slot = i; true },
|
||||
None => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Use this for any uint option that lacks a static default.
|
||||
fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool {
|
||||
/// Use this for any numeric option that lacks a static default.
|
||||
fn parse_opt_number<T: Copy + FromStr>(slot: &mut Option<T>, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some(s) => { *slot = s.parse().ok(); slot.is_some() }
|
||||
None => false
|
||||
|
@ -592,6 +596,41 @@ macro_rules! options {
|
|||
true
|
||||
}
|
||||
|
||||
fn parse_instrument_coverage(slot: &mut Option<InstrumentCoverage>, v: Option<&str>) -> bool {
|
||||
if v.is_some() {
|
||||
let mut bool_arg = None;
|
||||
if parse_opt_bool(&mut bool_arg, v) {
|
||||
*slot = if bool_arg.unwrap() {
|
||||
Some(InstrumentCoverage::All)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
let v = match v {
|
||||
None => {
|
||||
*slot = Some(InstrumentCoverage::All);
|
||||
return true;
|
||||
}
|
||||
Some(v) => v,
|
||||
};
|
||||
|
||||
*slot = Some(match v {
|
||||
"all" => InstrumentCoverage::All,
|
||||
"except-unused-generics" | "except_unused_generics" => {
|
||||
InstrumentCoverage::ExceptUnusedGenerics
|
||||
}
|
||||
"except-unused-functions" | "except_unused_functions" => {
|
||||
InstrumentCoverage::ExceptUnusedFunctions
|
||||
}
|
||||
"off" | "no" | "n" | "false" | "0" => InstrumentCoverage::Off,
|
||||
_ => return false,
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_treat_err_as_bug(slot: &mut Option<NonZeroUsize>, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some(s) => { *slot = s.parse().ok(); slot.is_some() }
|
||||
|
@ -748,13 +787,13 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
|||
"this option is deprecated and does nothing"),
|
||||
code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
|
||||
"choose the code model to use (`rustc --print code-models` for details)"),
|
||||
codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
|
||||
codegen_units: Option<usize> = (None, parse_opt_number, [UNTRACKED],
|
||||
"divide crate into N units to optimize in parallel"),
|
||||
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
|
||||
"use Windows Control Flow Guard (default: no)"),
|
||||
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"explicitly enable the `cfg(debug_assertions)` directive"),
|
||||
debuginfo: usize = (0, parse_uint, [TRACKED],
|
||||
debuginfo: usize = (0, parse_number, [TRACKED],
|
||||
"debug info emission level (0 = no debug info, 1 = line tables only, \
|
||||
2 = full debug info with variable and type information; default: 0)"),
|
||||
default_linker_libraries: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -769,13 +808,13 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
|||
"force use of unwind tables"),
|
||||
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||
"enable incremental compilation"),
|
||||
inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
|
||||
inline_threshold: Option<u32> = (None, parse_opt_number, [TRACKED],
|
||||
"set the threshold for inlining a function"),
|
||||
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
|
||||
"a single extra argument to append to the linker invocation (can be used several times)"),
|
||||
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
|
||||
"extra arguments to append to the linker invocation (space separated)"),
|
||||
link_dead_code: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
|
||||
link_dead_code: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"keep dead code at link time (useful for code coverage) (default: no)"),
|
||||
link_self_contained: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
|
||||
"control whether to link Rust provided C objects/libraries or rely
|
||||
|
@ -870,8 +909,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
(default: no)"),
|
||||
borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED],
|
||||
"select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"),
|
||||
borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||
"gather borrowck statistics (default: no)"),
|
||||
cgu_partitioning_strategy: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||
"the codegen unit partitioning strategy to use"),
|
||||
chalk: bool = (false, parse_bool, [TRACKED],
|
||||
|
@ -959,24 +996,22 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"verify incr. comp. hashes of green query instances (default: no)"),
|
||||
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"enable MIR inlining (default: no)"),
|
||||
inline_mir_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
|
||||
inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
"a default MIR inlining threshold (default: 50)"),
|
||||
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
|
||||
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
"inlining threshold for functions with inline hint (default: 100)"),
|
||||
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"control whether `#[inline]` functions are in all CGUs"),
|
||||
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||
"gather statistics about the input (default: no)"),
|
||||
insert_sideeffect: bool = (false, parse_bool, [TRACKED],
|
||||
"fix undefined behavior when a thread doesn't eventually make progress \
|
||||
(such as entering an empty infinite loop) by inserting llvm.sideeffect \
|
||||
(default: no)"),
|
||||
instrument_coverage: bool = (false, parse_bool, [TRACKED],
|
||||
instrument_coverage: Option<InstrumentCoverage> = (None, parse_instrument_coverage, [TRACKED],
|
||||
"instrument the generated code to support LLVM source-based code coverage \
|
||||
reports (note, the compiler build config must include `profiler = true`, \
|
||||
and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \
|
||||
implies `-Z symbol-mangling-version=v0`; disables/overrides some Rust \
|
||||
optimizations (default: no)"),
|
||||
optimizations. Optional values are: `=all` (default coverage), \
|
||||
`=except-unused-generics`, `=except-unused-functions`, or `=off` \
|
||||
(default: instrument-coverage=off)"),
|
||||
instrument_mcount: bool = (false, parse_bool, [TRACKED],
|
||||
"insert function instrument code for mcount-based tracing (default: no)"),
|
||||
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -999,10 +1034,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
|
||||
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
|
||||
(default: no)"),
|
||||
mir_opt_level: usize = (1, parse_uint, [TRACKED],
|
||||
"MIR optimization level (0-3; default: 1)"),
|
||||
mutable_noalias: bool = (false, parse_bool, [TRACKED],
|
||||
"emit noalias metadata for mutable references (default: no)"),
|
||||
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
|
||||
mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
|
||||
new_llvm_pass_manager: bool = (false, parse_bool, [TRACKED],
|
||||
"use new LLVM pass manager (default: no)"),
|
||||
nll_facts: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -1120,7 +1155,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
|
||||
teach: bool = (false, parse_bool, [TRACKED],
|
||||
"show extended diagnostic help (default: no)"),
|
||||
terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
|
||||
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
|
||||
"set the current terminal width"),
|
||||
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||
"select processor to schedule for (`rustc --print target-cpus` for details)"),
|
||||
|
|
|
@ -13,7 +13,6 @@ use rustc_span::hygiene::ExpnId;
|
|||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
use rustc_span::{MultiSpan, Span, Symbol};
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::str;
|
||||
|
||||
/// The set of keys (and, optionally, values) that define the compilation
|
||||
|
@ -122,8 +121,6 @@ pub struct ParseSess {
|
|||
pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
|
||||
/// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
|
||||
pub raw_identifier_spans: Lock<Vec<Span>>,
|
||||
/// Used to determine and report recursive module inclusions.
|
||||
pub included_mod_stack: Lock<Vec<PathBuf>>,
|
||||
source_map: Lrc<SourceMap>,
|
||||
pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
|
||||
/// Contains the spans of block expressions that could have been incomplete based on the
|
||||
|
@ -143,6 +140,7 @@ pub struct ParseSess {
|
|||
}
|
||||
|
||||
impl ParseSess {
|
||||
/// Used for testing.
|
||||
pub fn new(file_path_mapping: FilePathMapping) -> Self {
|
||||
let sm = Lrc::new(SourceMap::new(file_path_mapping));
|
||||
let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone()));
|
||||
|
@ -157,7 +155,6 @@ impl ParseSess {
|
|||
edition: ExpnId::root().expn_data().edition,
|
||||
missing_fragment_specifiers: Default::default(),
|
||||
raw_identifier_spans: Lock::new(Vec::new()),
|
||||
included_mod_stack: Lock::new(vec![]),
|
||||
source_map,
|
||||
buffered_lints: Lock::new(vec![]),
|
||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
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, PrintRequest, SanitizerSet, SwitchWithOptPath};
|
||||
use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
|
||||
use crate::filesearch;
|
||||
use crate::lint::{self, LintId};
|
||||
use crate::parse::ParseSess;
|
||||
use crate::search_paths::{PathKind, SearchPath};
|
||||
|
||||
pub use rustc_ast::attr::MarkedAttrs;
|
||||
pub use rustc_ast::crate_disambiguator::CrateDisambiguator;
|
||||
pub use rustc_ast::Attribute;
|
||||
use rustc_data_structures::flock;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
|
@ -21,14 +20,15 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
|
|||
use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
|
||||
use rustc_errors::json::JsonEmitter;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
|
||||
use rustc_lint_defs::FutureBreakage;
|
||||
pub use rustc_span::crate_disambiguator::CrateDisambiguator;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
|
||||
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
|
||||
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel};
|
||||
use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel};
|
||||
|
||||
use std::cell::{self, RefCell};
|
||||
use std::env;
|
||||
|
@ -241,8 +241,7 @@ pub struct PerfStats {
|
|||
enum DiagnosticBuilderMethod {
|
||||
Note,
|
||||
SpanNote,
|
||||
SpanSuggestion(String), // suggestion
|
||||
// Add more variants as needed to support one-time diagnostics.
|
||||
// Add more variants as needed to support one-time diagnostics.
|
||||
}
|
||||
|
||||
/// Trait implemented by error types. This should not be implemented manually. Instead, use
|
||||
|
@ -551,15 +550,6 @@ impl Session {
|
|||
let span = span_maybe.expect("`span_note` needs a span");
|
||||
diag_builder.span_note(span, message);
|
||||
}
|
||||
DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
|
||||
let span = span_maybe.expect("`span_suggestion_*` needs a span");
|
||||
diag_builder.span_suggestion(
|
||||
span,
|
||||
message,
|
||||
suggestion,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -589,23 +579,6 @@ impl Session {
|
|||
self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None);
|
||||
}
|
||||
|
||||
pub fn diag_span_suggestion_once<'a, 'b>(
|
||||
&'a self,
|
||||
diag_builder: &'b mut DiagnosticBuilder<'a>,
|
||||
msg_id: DiagnosticMessageId,
|
||||
span: Span,
|
||||
message: &str,
|
||||
suggestion: String,
|
||||
) {
|
||||
self.diag_once(
|
||||
diag_builder,
|
||||
DiagnosticBuilderMethod::SpanSuggestion(suggestion),
|
||||
msg_id,
|
||||
message,
|
||||
Some(span),
|
||||
);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn source_map(&self) -> &SourceMap {
|
||||
self.parse_sess.source_map()
|
||||
|
@ -631,15 +604,18 @@ impl Session {
|
|||
pub fn verify_llvm_ir(&self) -> bool {
|
||||
self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
|
||||
}
|
||||
pub fn borrowck_stats(&self) -> bool {
|
||||
self.opts.debugging_opts.borrowck_stats
|
||||
}
|
||||
pub fn print_llvm_passes(&self) -> bool {
|
||||
self.opts.debugging_opts.print_llvm_passes
|
||||
}
|
||||
pub fn binary_dep_depinfo(&self) -> bool {
|
||||
self.opts.debugging_opts.binary_dep_depinfo
|
||||
}
|
||||
pub fn mir_opt_level(&self) -> usize {
|
||||
self.opts
|
||||
.debugging_opts
|
||||
.mir_opt_level
|
||||
.unwrap_or_else(|| if self.opts.optimize != config::OptLevel::No { 2 } else { 1 })
|
||||
}
|
||||
|
||||
/// Gets the features enabled for the current compilation session.
|
||||
/// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents
|
||||
|
@ -831,8 +807,11 @@ impl Session {
|
|||
// This is used to control the emission of the `uwtable` attribute on
|
||||
// LLVM functions.
|
||||
//
|
||||
// At the very least, unwind tables are needed when compiling with
|
||||
// `-C panic=unwind`.
|
||||
// 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
|
||||
|
@ -845,13 +824,10 @@ impl Session {
|
|||
// 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.
|
||||
if self.panic_strategy() == PanicStrategy::Unwind {
|
||||
true
|
||||
} else if self.target.requires_uwtable {
|
||||
true
|
||||
} else {
|
||||
self.opts.cg.force_unwind_tables.unwrap_or(false)
|
||||
}
|
||||
self.target.requires_uwtable
|
||||
|| self.opts.cg.force_unwind_tables.unwrap_or(
|
||||
self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the symbol name for the registrar function,
|
||||
|
@ -884,22 +860,6 @@ impl Session {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn set_incr_session_load_dep_graph(&self, load: bool) {
|
||||
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
|
||||
|
||||
if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session {
|
||||
*load_dep_graph = load;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn incr_session_load_dep_graph(&self) -> bool {
|
||||
let incr_comp_session = self.incr_comp_session.borrow();
|
||||
match *incr_comp_session {
|
||||
IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_incr_comp_session(
|
||||
&self,
|
||||
session_dir: PathBuf,
|
||||
|
@ -1137,6 +1097,21 @@ impl Session {
|
|||
self.opts.cg.link_dead_code.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn instrument_coverage(&self) -> bool {
|
||||
self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
|
||||
!= config::InstrumentCoverage::Off
|
||||
}
|
||||
|
||||
pub fn instrument_coverage_except_unused_generics(&self) -> bool {
|
||||
self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
|
||||
== config::InstrumentCoverage::ExceptUnusedGenerics
|
||||
}
|
||||
|
||||
pub fn instrument_coverage_except_unused_functions(&self) -> bool {
|
||||
self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
|
||||
== config::InstrumentCoverage::ExceptUnusedFunctions
|
||||
}
|
||||
|
||||
pub fn mark_attr_known(&self, attr: &Attribute) {
|
||||
self.known_attrs.lock().mark(attr)
|
||||
}
|
||||
|
@ -1509,13 +1484,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
|||
|
||||
// Unwind tables cannot be disabled if the target requires them.
|
||||
if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
|
||||
if sess.panic_strategy() == PanicStrategy::Unwind && !include_uwtables {
|
||||
sess.err(
|
||||
"panic=unwind requires unwind tables, they cannot be disabled \
|
||||
with `-C force-unwind-tables=no`.",
|
||||
);
|
||||
}
|
||||
|
||||
if sess.target.requires_uwtable && !include_uwtables {
|
||||
sess.err(
|
||||
"target requires unwind tables, they cannot be disabled with \
|
||||
|
@ -1543,59 +1511,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
|||
);
|
||||
}
|
||||
|
||||
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
|
||||
"aarch64-apple-darwin",
|
||||
"aarch64-fuchsia",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-fuchsia",
|
||||
"x86_64-unknown-freebsd",
|
||||
"x86_64-unknown-linux-gnu",
|
||||
];
|
||||
const LSAN_SUPPORTED_TARGETS: &[&str] = &[
|
||||
"aarch64-apple-darwin",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-unknown-linux-gnu",
|
||||
];
|
||||
const MSAN_SUPPORTED_TARGETS: &[&str] =
|
||||
&["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
|
||||
const TSAN_SUPPORTED_TARGETS: &[&str] = &[
|
||||
"aarch64-apple-darwin",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-unknown-freebsd",
|
||||
"x86_64-unknown-linux-gnu",
|
||||
];
|
||||
const HWASAN_SUPPORTED_TARGETS: &[&str] =
|
||||
&["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
|
||||
|
||||
// Sanitizers can only be used on some tested platforms.
|
||||
for s in sess.opts.debugging_opts.sanitizer {
|
||||
let supported_targets = match s {
|
||||
SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS,
|
||||
SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS,
|
||||
SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS,
|
||||
SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS,
|
||||
SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS,
|
||||
_ => panic!("unrecognized sanitizer {}", s),
|
||||
};
|
||||
if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
|
||||
sess.err(&format!(
|
||||
"`-Zsanitizer={}` only works with targets: {}",
|
||||
s,
|
||||
supported_targets.join(", ")
|
||||
));
|
||||
}
|
||||
let conflicting = sess.opts.debugging_opts.sanitizer - s;
|
||||
if !conflicting.is_empty() {
|
||||
sess.err(&format!(
|
||||
"`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`",
|
||||
s, conflicting,
|
||||
));
|
||||
// Don't report additional errors.
|
||||
break;
|
||||
}
|
||||
// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
|
||||
let supported_sanitizers = sess.target.options.supported_sanitizers;
|
||||
let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
|
||||
match unsupported_sanitizers.into_iter().count() {
|
||||
0 => {}
|
||||
1 => sess
|
||||
.err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
|
||||
_ => sess.err(&format!(
|
||||
"{} sanitizers are not supported for this target",
|
||||
unsupported_sanitizers
|
||||
)),
|
||||
}
|
||||
// Cannot mix and match sanitizers.
|
||||
let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
|
||||
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
|
||||
sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
use crate::parse::ParseSess;
|
||||
use crate::session::Session;
|
||||
use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
|
||||
use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream;
|
||||
|
||||
impl Session {
|
||||
pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
|
||||
self.prof.verbose_generic_activity(what)
|
||||
|
@ -53,3 +59,52 @@ impl CanonicalizedPath {
|
|||
&self.original
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Find a better spot for this - it needs to be accessible from `rustc_ast_lowering`,
|
||||
// and needs to access `ParseSess
|
||||
pub struct FlattenNonterminals<'a> {
|
||||
pub parse_sess: &'a ParseSess,
|
||||
pub synthesize_tokens: CanSynthesizeMissingTokens,
|
||||
pub nt_to_tokenstream: NtToTokenstream,
|
||||
}
|
||||
|
||||
impl<'a> FlattenNonterminals<'a> {
|
||||
pub fn process_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
|
||||
fn can_skip(stream: &TokenStream) -> bool {
|
||||
stream.trees().all(|tree| match tree {
|
||||
TokenTree::Token(token) => !matches!(token.kind, token::Interpolated(_)),
|
||||
TokenTree::Delimited(_, _, inner) => can_skip(&inner),
|
||||
})
|
||||
}
|
||||
|
||||
if can_skip(&tokens) {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
tokens.into_trees().flat_map(|tree| self.process_token_tree(tree).into_trees()).collect()
|
||||
}
|
||||
|
||||
pub fn process_token_tree(&mut self, tree: TokenTree) -> TokenStream {
|
||||
match tree {
|
||||
TokenTree::Token(token) => self.process_token(token),
|
||||
TokenTree::Delimited(span, delim, tts) => {
|
||||
TokenTree::Delimited(span, delim, self.process_token_stream(tts)).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_token(&mut self, token: Token) -> TokenStream {
|
||||
match token.kind {
|
||||
token::Interpolated(nt) => {
|
||||
let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens);
|
||||
TokenTree::Delimited(
|
||||
DelimSpan::from_single(token.span),
|
||||
DelimToken::NoDelim,
|
||||
self.process_token_stream(tts),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
_ => TokenTree::Token(token).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue