use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::config::{OptLevel, SanitizerSet};
+use rustc_session::config::OptLevel;
use rustc_session::Session;
-use rustc_target::spec::StackProbeType;
+use rustc_target::spec::{SanitizerSet, StackProbeType};
use crate::attributes;
use crate::llvm::AttributePlace::Function;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath};
+use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath};
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::InnerSpan;
-use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo};
+use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo};
use tracing::debug;
use libc::{c_char, c_int, c_uint, c_void, size_t};
use rustc_middle::middle::exported_symbols;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{DebugInfo, SanitizerSet};
+use rustc_session::config::DebugInfo;
use rustc_span::symbol::Symbol;
+use rustc_target::spec::SanitizerSet;
use std::ffi::CString;
use std::time::Instant;
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
-use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
+use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
use rustc_span::symbol::Symbol;
use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
-use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target};
+use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
use super::archive::ArchiveBuilder;
use super::command::Command;
.map(|channel| format!("-{}", channel))
.unwrap_or_default();
- match sess.opts.target_triple.triple() {
- "aarch64-apple-darwin" | "x86_64-apple-darwin" => {
- // On Apple platforms, the sanitizer is always built as a dylib, and
- // LLVM will link to `@rpath/*.dylib`, so we need to specify an
- // rpath to the library as well (the rpath should be absolute, see
- // PR #41352 for details).
- let filename = format!("rustc{}_rt.{}", channel, name);
- let path = find_sanitizer_runtime(&sess, &filename);
- let rpath = path.to_str().expect("non-utf8 component in path");
- linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
- linker.link_dylib(Symbol::intern(&filename));
- }
- "aarch64-fuchsia"
- | "aarch64-unknown-linux-gnu"
- | "x86_64-fuchsia"
- | "x86_64-unknown-freebsd"
- | "x86_64-unknown-linux-gnu" => {
- let filename = format!("librustc{}_rt.{}.a", channel, name);
- let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
- linker.link_whole_rlib(&path);
- }
- _ => {}
+ if sess.target.is_like_osx {
+ // On Apple platforms, the sanitizer is always built as a dylib, and
+ // LLVM will link to `@rpath/*.dylib`, so we need to specify an
+ // rpath to the library as well (the rpath should be absolute, see
+ // PR #41352 for details).
+ let filename = format!("rustc{}_rt.{}", channel, name);
+ let path = find_sanitizer_runtime(&sess, &filename);
+ let rpath = path.to_str().expect("non-utf8 component in path");
+ linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
+ linker.link_dylib(Symbol::intern(&filename));
+ } else {
+ let filename = format!("librustc{}_rt.{}.a", channel, name);
+ let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
+ linker.link_whole_rlib(&path);
}
}
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::Instance;
use rustc_middle::ty::{SymbolName, TyCtxt};
-use rustc_session::config::{CrateType, SanitizerSet};
+use rustc_session::config::CrateType;
+use rustc_target::spec::SanitizerSet;
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
crates_export_threshold(&tcx.sess.crate_types())
use rustc_middle::ty::TyCtxt;
use rustc_session::cgu_reuse_tracker::CguReuseTracker;
use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
-use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath};
+use rustc_session::config::{Passes, SwitchWithOptPath};
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
-use rustc_target::spec::{MergeFunctions, PanicStrategy};
+use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet};
use std::any::Any;
use std::fs;
use crate::def::{CtorOf, DefKind, Res};
use crate::def_id::DefId;
use crate::hir::{self, HirId, PatKind};
+use rustc_data_structures::stable_set::FxHashSet;
use rustc_span::symbol::Ident;
use rustc_span::Span;
}
_ => true,
});
- variants.sort();
- variants.dedup();
+ // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
+ // the bounds
+ let mut duplicates = FxHashSet::default();
+ variants.retain(|def_id| duplicates.insert(*def_id));
variants
}
use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
use rustc_session::config::{
- Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel,
+ Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel,
};
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm;
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
-use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel};
+use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel};
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
use std::num::NonZeroUsize;
use crate::mir::mono::Linkage;
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
-use rustc_session::config::SanitizerSet;
use rustc_span::symbol::Symbol;
+use rustc_target::spec::SanitizerSet;
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
pub struct CodegenFnAttrs {
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};
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 {
crate mod dep_tracking {
use super::{
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
- LtoCli, OptLevel, OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm,
- SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
+ LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
+ SymbolManglingVersion, TrimmedDefPaths,
};
use crate::lint;
use crate::options::WasiExecModel;
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;
#![cfg_attr(bootstrap, feature(or_patterns))]
#![recursion_limit = "256"]
-#[macro_use]
-extern crate bitflags;
#[macro_use]
extern crate rustc_macros;
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;
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 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;
);
}
- 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));
}
}
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::apple_base::opts("macos");
base.cpu = "apple-a12".to_string();
base.max_atomic_width = Some(128);
- base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
+ base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
// Clang automatically chooses a more specific target based on
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::fuchsia_base::opts();
base.max_atomic_width = Some(128);
+ base.supported_sanitizers = SanitizerSet::ADDRESS;
Target {
llvm_target: "aarch64-fuchsia".to_string(),
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
// See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
// for target ABI requirements.
// As documented in http://developer.android.com/ndk/guides/cpu-features.html
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
base.features = "+neon,+fp-armv8".to_string();
+ base.supported_sanitizers = SanitizerSet::HWADDRESS;
Target {
llvm_target: "aarch64-linux-android".to_string(),
pointer_width: 64,
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.max_atomic_width = Some(128);
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD
+ | SanitizerSet::HWADDRESS;
Target {
llvm_target: "aarch64-unknown-linux-gnu".to_string(),
use crate::abi::Endian;
use crate::spec::abi::{lookup as lookup_abi, Abi};
use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_serialize::json::{Json, ToJson};
use rustc_span::symbol::{sym, Symbol};
use std::collections::BTreeMap;
}
}
-macro_rules! supported_targets {
- ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
- $(mod $module;)+
-
- /// List of supported targets
- pub const TARGETS: &[&str] = &[$($($triple),+),+];
-
- fn load_builtin(target: &str) -> Option<Target> {
- let mut t = match target {
- $( $($triple)|+ => $module::target(), )+
- _ => return None,
- };
- t.is_builtin = true;
- debug!("got builtin target: {:?}", t);
- Some(t)
- }
-
- #[cfg(test)]
- mod tests {
- mod tests_impl;
-
- // Cannot put this into a separate file without duplication, make an exception.
- $(
- #[test] // `#[test]`
- fn $module() {
- tests_impl::test_target(super::$module::target());
- }
- )+
- }
- };
-}
-
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum StackProbeType {
/// Don't emit any stack probes.
}
}
+bitflags::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;
+ }
+}
+
+impl SanitizerSet {
+ /// Return sanitizer's name
+ ///
+ /// Returns none if the flags is a set of sanitizers numbering not exactly one.
+ fn as_str(self) -> Option<&'static str> {
+ Some(match self {
+ SanitizerSet::ADDRESS => "address",
+ SanitizerSet::LEAK => "leak",
+ SanitizerSet::MEMORY => "memory",
+ SanitizerSet::THREAD => "thread",
+ SanitizerSet::HWADDRESS => "hwaddress",
+ _ => return None,
+ })
+ }
+}
+
+/// 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 = s.as_str().unwrap_or_else(|| 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);
+ }
+}
+
+impl ToJson for SanitizerSet {
+ fn to_json(&self) -> Json {
+ self.into_iter()
+ .map(|v| Some(v.as_str()?.to_json()))
+ .collect::<Option<Vec<_>>>()
+ .unwrap_or(Vec::new())
+ .to_json()
+ }
+}
+
+macro_rules! supported_targets {
+ ( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
+ $(mod $module;)+
+
+ /// List of supported targets
+ pub const TARGETS: &[&str] = &[$($($triple),+),+];
+
+ fn load_builtin(target: &str) -> Option<Target> {
+ let mut t = match target {
+ $( $($triple)|+ => $module::target(), )+
+ _ => return None,
+ };
+ t.is_builtin = true;
+ debug!("got builtin target: {:?}", t);
+ Some(t)
+ }
+
+ #[cfg(test)]
+ mod tests {
+ mod tests_impl;
+
+ // Cannot put this into a separate file without duplication, make an exception.
+ $(
+ #[test] // `#[test]`
+ fn $module() {
+ tests_impl::test_target(super::$module::target());
+ }
+ )+
+ }
+ };
+}
+
supported_targets! {
("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
/// How to handle split debug information, if at all. Specifying `None` has
/// target-specific meaning.
pub split_debuginfo: SplitDebuginfo,
+
+ /// The sanitizers supported by this target
+ ///
+ /// Note that the support here is at a codegen level. If the machine code with sanitizer
+ /// enabled can generated on this target, but the necessary supporting libraries are not
+ /// distributed with the target, the sanitizer should still appear in this list for the target.
+ pub supported_sanitizers: SanitizerSet,
}
impl Default for TargetOptions {
eh_frame_header: true,
has_thumb_interworking: false,
split_debuginfo: SplitDebuginfo::Off,
+ supported_sanitizers: SanitizerSet::empty(),
}
}
}
)),
}).unwrap_or(Ok(()))
} );
+ ($key_name:ident, SanitizerSet) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| {
+ for s in a {
+ base.$key_name |= match s.as_string() {
+ Some("address") => SanitizerSet::ADDRESS,
+ Some("leak") => SanitizerSet::LEAK,
+ Some("memory") => SanitizerSet::MEMORY,
+ Some("thread") => SanitizerSet::THREAD,
+ Some("hwaddress") => SanitizerSet::HWADDRESS,
+ Some(s) => return Some(Err(format!("unknown sanitizer {}", s))),
+ _ => return Some(Err(format!("not a string: {:?}", s))),
+ };
+ }
+ Some(Ok(()))
+ }).unwrap_or(Ok(()))
+ } );
+
($key_name:ident, crt_objects_fallback) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
key!(eh_frame_header, bool);
key!(has_thumb_interworking, bool);
key!(split_debuginfo, SplitDebuginfo)?;
+ key!(supported_sanitizers, SanitizerSet)?;
// NB: The old name is deprecated, but support for it is retained for
// compatibility.
target_option_val!(eh_frame_header);
target_option_val!(has_thumb_interworking);
target_option_val!(split_debuginfo);
+ target_option_val!(supported_sanitizers);
if default.unsupported_abis != self.unsupported_abis {
d.insert(
-use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::apple_base::opts("macos");
);
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
// Clang automatically chooses a more specific target based on
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
-use crate::spec::{StackProbeType, Target};
+use crate::spec::{SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::fuchsia_base::opts();
base.cpu = "x86-64".to_string();
base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
+ base.supported_sanitizers = SanitizerSet::ADDRESS;
Target {
llvm_target: "x86_64-fuchsia".to_string(),
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
base.max_atomic_width = Some(64);
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::THREAD;
Target {
llvm_target: "x86_64-unknown-freebsd".to_string(),
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.max_atomic_width = Some(64);
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
base.stack_probes = StackProbeType::InlineOrCall { min_llvm_version_for_inline: (11, 0, 1) };
+ base.supported_sanitizers =
+ SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
Target {
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
-use rustc_session::config::SanitizerSet;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use rustc_target::spec::abi;
+use rustc_target::spec::{abi, SanitizerSet};
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
use std::iter;
-Subproject commit af078ecc0b069ec594982f92d4c6c58af99efbb5
+Subproject commit 710fc18ddcb6c7677b3c96359abb35da37f2a488
// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
-// error-pattern: error: `-Zsanitizer=leak` only works with targets:
-
+// error-pattern: error: leak sanitizer is not supported for this target
#![feature(no_core)]
#![no_core]
#![no_main]
-error: `-Zsanitizer=leak` only works with targets: aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
+error: leak sanitizer is not supported for this target
error: aborting due to previous error