From c703ff26555bc25739384b2104dfb538ec7435c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 22 Oct 2019 00:00:00 +0000 Subject: [PATCH] Conditional compilation for sanitizers Configure sanitize option when compiling with a sanitizer to make it possible to execute different code depending on whether given sanitizer is enabled or not. --- .../src/language-features/cfg-sanitize.md | 36 +++++++++++++++++++ src/librustc/session/config.rs | 15 ++++++++ src/librustc_feature/active.rs | 3 ++ src/librustc_feature/builtin_attrs.rs | 1 + src/libsyntax_pos/symbol.rs | 2 ++ .../feature-gate-cfg_sanitize.rs | 3 ++ .../feature-gate-cfg_sanitize.stderr | 12 +++++++ src/test/ui/sanitize-cfg.rs | 26 ++++++++++++++ 8 files changed, 98 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/cfg-sanitize.md create mode 100644 src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs create mode 100644 src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr create mode 100644 src/test/ui/sanitize-cfg.rs diff --git a/src/doc/unstable-book/src/language-features/cfg-sanitize.md b/src/doc/unstable-book/src/language-features/cfg-sanitize.md new file mode 100644 index 0000000000000..949f24ab9c11e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/cfg-sanitize.md @@ -0,0 +1,36 @@ +# `cfg_sanitize` + +The tracking issue for this feature is: [#39699] + +[#39699]: https://github.com/rust-lang/rust/issues/39699 + +------------------------ + +The `cfg_sanitize` feature makes it possible to execute different code +depending on whether a particular sanitizer is enabled or not. + +## Examples + +``` rust +#![feature(cfg_sanitize)] + +#[cfg(sanitize = "thread")] +fn a() { + // ... +} + +#[cfg(not(sanitize = "thread"))] +fn a() { + // ... +} + +fn b() { + if cfg!(sanitize = "leak") { + // ... + } else { + // ... + } +} + +``` + diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index fbfae721bbe91..245a4ac86cd1e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -47,6 +47,17 @@ pub enum Sanitizer { Thread, } +impl fmt::Display for Sanitizer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Sanitizer::Address => "address".fmt(f), + Sanitizer::Leak => "leak".fmt(f), + Sanitizer::Memory => "memory".fmt(f), + Sanitizer::Thread => "thread".fmt(f), + } + } +} + impl FromStr for Sanitizer { type Err = (); fn from_str(s: &str) -> Result { @@ -1582,6 +1593,10 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { } } } + if let Some(s) = &sess.opts.debugging_opts.sanitizer { + let symbol = Symbol::intern(&s.to_string()); + ret.insert((sym::sanitize, Some(symbol))); + } if sess.opts.debug_assertions { ret.insert((Symbol::intern("debug_assertions"), None)); } diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 7c0d39965fc00..16d8ada9f24c0 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -524,6 +524,9 @@ declare_features! ( /// Allows the use of `if` and `match` in constants. (active, const_if_match, "1.41.0", Some(49146), None), + /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. + (active, cfg_sanitize, "1.41.0", Some(39699), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index f72df00a8e821..fa8e3e189edef 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -25,6 +25,7 @@ const GATED_CFGS: &[GatedCfg] = &[ (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), + (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 7d43c3c8d076e..3059b05969106 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -177,6 +177,7 @@ symbols! { cfg_attr, cfg_attr_multi, cfg_doctest, + cfg_sanitize, cfg_target_feature, cfg_target_has_atomic, cfg_target_thread_local, @@ -634,6 +635,7 @@ symbols! { rust_eh_unwind_resume, rust_oom, rvalue_static_promotion, + sanitize, sanitizer_runtime, _Self, self_in_typedefs, diff --git a/src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs new file mode 100644 index 0000000000000..c3e7cc9ed8a9b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs @@ -0,0 +1,3 @@ +#[cfg(not(sanitize = "thread"))] +//~^ `cfg(sanitize)` is experimental +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr new file mode 100644 index 0000000000000..f67a0d83bdd3a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(sanitize)` is experimental and subject to change + --> $DIR/feature-gate-cfg_sanitize.rs:1:11 + | +LL | #[cfg(not(sanitize = "thread"))] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/39699 + = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/sanitize-cfg.rs b/src/test/ui/sanitize-cfg.rs new file mode 100644 index 0000000000000..9c198543a8664 --- /dev/null +++ b/src/test/ui/sanitize-cfg.rs @@ -0,0 +1,26 @@ +// Verifies that when compiling with -Zsanitizer=option, +// the `#[cfg(sanitize = "option")]` attribute is configured. + +// needs-sanitizer-support +// only-linux +// only-x86_64 +// check-pass +// revisions: address leak memory thread +//[address]compile-flags: -Zsanitizer=address --cfg address +//[leak]compile-flags: -Zsanitizer=leak --cfg leak +//[memory]compile-flags: -Zsanitizer=memory --cfg memory +//[thread]compile-flags: -Zsanitizer=thread --cfg thread + +#![feature(cfg_sanitize)] + +#[cfg(all(sanitize = "address", address))] +fn main() {} + +#[cfg(all(sanitize = "leak", leak))] +fn main() {} + +#[cfg(all(sanitize = "memory", memory))] +fn main() {} + +#[cfg(all(sanitize = "thread", thread))] +fn main() {}