]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #39671 - alexcrichton:change-order, r=brson
authorCorey Farwell <coreyf@rwell.org>
Thu, 9 Feb 2017 04:55:51 +0000 (23:55 -0500)
committerGitHub <noreply@github.com>
Thu, 9 Feb 2017 04:55:51 +0000 (23:55 -0500)
travis: Fix build order of dist-x86-linux

I just tried to build this container locally but it looks like connecting to
ftp.gnu.org requires SNI, so let's build curl/OpenSSL first to ensure that we've
got an SNI-capable client to download gcc/binutils with.

60 files changed:
configure
mk/cfg/aarch64-unknown-freebsd.mk [deleted file]
mk/cfg/i686-unknown-netbsd.mk [deleted file]
src/Cargo.lock
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/ci/docker/dist-x86-linux/Dockerfile
src/ci/docker/dist-x86-linux/build-headers.sh [new file with mode: 0755]
src/ci/docker/x86_64-gnu/Dockerfile
src/compiler-rt
src/doc/reference.md
src/librustc/middle/cstore.rs
src/librustc/session/config.rs
src/librustc_asan/Cargo.toml [new file with mode: 0644]
src/librustc_asan/build.rs [new file with mode: 0644]
src/librustc_asan/lib.rs [new file with mode: 0644]
src/librustc_llvm/ffi.rs
src/librustc_lsan/Cargo.toml [new file with mode: 0644]
src/librustc_lsan/build.rs [new file with mode: 0644]
src/librustc_lsan/lib.rs [new file with mode: 0644]
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_msan/Cargo.toml [new file with mode: 0644]
src/librustc_msan/build.rs [new file with mode: 0644]
src/librustc_msan/lib.rs [new file with mode: 0644]
src/librustc_trans/back/link.rs
src/librustc_trans/back/write.rs
src/librustc_trans/declare.rs
src/librustc_tsan/Cargo.toml [new file with mode: 0644]
src/librustc_tsan/build.rs [new file with mode: 0644]
src/librustc_tsan/lib.rs [new file with mode: 0644]
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/libstd/Cargo.toml
src/libstd/env.rs
src/libsyntax/feature_gate.rs
src/rustc/std_shim/Cargo.toml
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.h
src/test/compile-fail/feature-gate-sanitizer-runtime.rs [new file with mode: 0644]
src/test/compile-fail/issue-27433.rs [new file with mode: 0644]
src/test/run-make/sanitizer-address/Makefile [new file with mode: 0644]
src/test/run-make/sanitizer-address/overflow.rs [new file with mode: 0644]
src/test/run-make/sanitizer-dylib/Makefile [new file with mode: 0644]
src/test/run-make/sanitizer-dylib/hello.rs [new file with mode: 0644]
src/test/run-make/sanitizer-invalid-target/Makefile [new file with mode: 0644]
src/test/run-make/sanitizer-invalid-target/hello.rs [new file with mode: 0644]
src/test/run-make/sanitizer-leak/Makefile [new file with mode: 0644]
src/test/run-make/sanitizer-leak/leak.rs [new file with mode: 0644]
src/test/run-make/sanitizer-memory/Makefile [new file with mode: 0644]
src/test/run-make/sanitizer-memory/uninit.rs [new file with mode: 0644]
src/test/run-make/sanitizer-thread/Makefile [new file with mode: 0644]
src/test/run-make/sanitizer-thread/racy.rs [new file with mode: 0644]
src/test/rustdoc/impl-disambiguation.rs [new file with mode: 0644]
src/tools/build-manifest/src/main.rs

index 597f007633640fbb079bde04d002ba4f733e0816..c751ad9731a7db9ff5690d67105e017260a882ce 100755 (executable)
--- a/configure
+++ b/configure
@@ -649,6 +649,7 @@ opt codegen-tests 1 "run the src/test/codegen tests"
 opt option-checking 1 "complain about unrecognized options in this configure script"
 opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
 opt vendor 0 "enable usage of vendored Rust crates"
+opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)"
 
 # Optimization and debugging options. These may be overridden by the release channel, etc.
 opt_nosave optimize 1 "build optimized rust code"
diff --git a/mk/cfg/aarch64-unknown-freebsd.mk b/mk/cfg/aarch64-unknown-freebsd.mk
deleted file mode 100644 (file)
index 34aee77..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# rustbuild-only target
diff --git a/mk/cfg/i686-unknown-netbsd.mk b/mk/cfg/i686-unknown-netbsd.mk
deleted file mode 100644 (file)
index 34aee77..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# rustbuild-only target
index 53721d48d9779cb34c6590c50e768a2d6597bebd..09aefd45e94c88964ce6bdcd1515c6f9dc5b2460 100644 (file)
@@ -277,6 +277,16 @@ name = "rustc-serialize"
 version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "rustc_asan"
+version = "0.0.0"
+dependencies = [
+ "alloc_system 0.0.0",
+ "build_helper 0.1.0",
+ "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core 0.0.0",
+]
+
 [[package]]
 name = "rustc_back"
 version = "0.0.0"
@@ -410,6 +420,16 @@ dependencies = [
  "rustc_bitflags 0.0.0",
 ]
 
+[[package]]
+name = "rustc_lsan"
+version = "0.0.0"
+dependencies = [
+ "alloc_system 0.0.0",
+ "build_helper 0.1.0",
+ "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core 0.0.0",
+]
+
 [[package]]
 name = "rustc_metadata"
 version = "0.0.0"
@@ -444,6 +464,16 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustc_msan"
+version = "0.0.0"
+dependencies = [
+ "alloc_system 0.0.0",
+ "build_helper 0.1.0",
+ "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core 0.0.0",
+]
+
 [[package]]
 name = "rustc_passes"
 version = "0.0.0"
@@ -525,6 +555,16 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustc_tsan"
+version = "0.0.0"
+dependencies = [
+ "alloc_system 0.0.0",
+ "build_helper 0.1.0",
+ "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core 0.0.0",
+]
+
 [[package]]
 name = "rustc_typeck"
 version = "0.0.0"
@@ -586,6 +626,10 @@ dependencies = [
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
  "rand 0.0.0",
+ "rustc_asan 0.0.0",
+ "rustc_lsan 0.0.0",
+ "rustc_msan 0.0.0",
+ "rustc_tsan 0.0.0",
  "std_unicode 0.0.0",
  "unwind 0.0.0",
 ]
index 0ebd10551329002068d6beb736140465b7c27337..cbfbcbe4f0c6eb85ef2c4431c41553bbbcd9764a 100644 (file)
@@ -242,6 +242,10 @@ pub fn compiletest(build: &Build,
     cmd.env("RUSTC_BOOTSTRAP", "1");
     build.add_rust_test_threads(&mut cmd);
 
+    if build.config.sanitizers {
+        cmd.env("SANITIZER_SUPPORT", "1");
+    }
+
     cmd.arg("--adb-path").arg("adb");
     cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
     if target.contains("android") {
index 81dd42a1e906a04f4578adf8ba8168ad0b691911..0b1a1f39d8d42e1765950e7c0d3fcdf9871ca366 100644 (file)
@@ -51,6 +51,17 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
     if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
         features.push_str(" force_alloc_system");
     }
+
+    if compiler.stage != 0 && build.config.sanitizers {
+        // This variable is used by the sanitizer runtime crates, e.g.
+        // rustc_lsan, to build the sanitizer runtime from C code
+        // When this variable is missing, those crates won't compile the C code,
+        // so we don't set this variable during stage0 where llvm-config is
+        // missing
+        // We also only build the runtimes when --enable-sanitizers (or its
+        // config.toml equivalent) is used
+        cargo.env("LLVM_CONFIG", build.llvm_config(target));
+    }
     cargo.arg("--features").arg(features)
          .arg("--manifest-path")
          .arg(build.src.join("src/rustc/std_shim/Cargo.toml"));
index 4e67a14345b9e3af4f995560effb187b04a5e11f..604c0397d5242972a118b26b4e0bd2ced74bf9d8 100644 (file)
@@ -48,6 +48,7 @@ pub struct Config {
     pub target_config: HashMap<String, Target>,
     pub full_bootstrap: bool,
     pub extended: bool,
+    pub sanitizers: bool,
 
     // llvm codegen options
     pub llvm_assertions: bool,
@@ -149,6 +150,7 @@ struct Build {
     python: Option<String>,
     full_bootstrap: Option<bool>,
     extended: Option<bool>,
+    sanitizers: Option<bool>,
 }
 
 /// TOML representation of various global install decisions.
@@ -294,6 +296,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
         set(&mut config.vendor, build.vendor);
         set(&mut config.full_bootstrap, build.full_bootstrap);
         set(&mut config.extended, build.extended);
+        set(&mut config.sanitizers, build.sanitizers);
 
         if let Some(ref install) = toml.install {
             config.prefix = install.prefix.clone().map(PathBuf::from);
@@ -438,6 +441,7 @@ macro_rules! check {
                 ("VENDOR", self.vendor),
                 ("FULL_BOOTSTRAP", self.full_bootstrap),
                 ("EXTENDED", self.extended),
+                ("SANITIZERS", self.sanitizers),
             }
 
             match key {
index a53419ad7fd780a28b41fcf6433a5081510187bc..025fe990f91dab67e27e338e8bd9f08faa754ffb 100644 (file)
 # disabled by default.
 #extended = false
 
+# Build the sanitizer runtimes
+#sanitizers = false
+
 # =============================================================================
 # General install configuration options
 # =============================================================================
index 1c3901bf2a14349619d1fdc379fb57bfd7b33970..2da2892150b4fba53817b2bee9a7c436b03c4390 100644 (file)
@@ -515,9 +515,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
 
     let branch = match &build.config.channel[..] {
         "stable" |
-        "beta" => {
-            build.release.split(".").take(2).collect::<Vec<_>>().join(".")
-        }
+        "beta" => format!("rust-{}", build.release_num),
         _ => "master".to_string(),
     };
 
index e58dcc9fce92f5c2c6bb038c5f241d10d585460b..ba6b34343f0b35d15554fd0f5b142c71daa9c627 100644 (file)
@@ -599,7 +599,8 @@ fn prepare_tool_cmd(&self, compiler: &Compiler, cmd: &mut Command) {
     /// Get the space-separated set of activated features for the standard
     /// library.
     fn std_features(&self) -> String {
-        let mut features = "panic-unwind".to_string();
+        let mut features = "panic-unwind asan lsan msan tsan".to_string();
+
         if self.config.debug_jemalloc {
             features.push_str(" debug-jemalloc");
         }
index d5bb8ea77e32baa426268f87a03fb6c4ff04f089..12e24ff1af6a2fc505c67887491c9a9fedd6a737 100644 (file)
@@ -63,6 +63,11 @@ RUN ./build-git.sh
 COPY build-cmake.sh /tmp/
 RUN ./build-cmake.sh
 
+# for sanitizers, we need kernel headers files newer than the ones CentOS ships
+# with so we install newer ones here
+COPY build-headers.sh /tmp/
+RUN ./build-headers.sh
+
 RUN curl -Lo /rustroot/dumb-init \
       https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \
       chmod +x /rustroot/dumb-init
@@ -76,5 +81,5 @@ RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST |
 ENV HOSTS=i686-unknown-linux-gnu
 ENV HOSTS=$HOSTS,x86_64-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended --enable-sanitizers
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-x86-linux/build-headers.sh b/src/ci/docker/dist-x86-linux/build-headers.sh
new file mode 100755 (executable)
index 0000000..4ce38fd
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -ex
+source shared.sh
+
+curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x
+
+cd linux-3.2.84
+hide_output make mrproper
+hide_output make INSTALL_HDR_PATH=dest headers_install
+
+find dest/include \( -name .install -o -name ..install.cmd \) -delete
+yes | cp -fr dest/include/* /usr/include
+
+cd ..
+rm -rf linux-3.2.84
index 6919487e17c3e6f1a78fa3da13e48a522979e53f..e903b6ddc64cd0ef54c761321cbe154b68a49cae 100644 (file)
@@ -22,5 +22,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
     rm dumb-init_*.deb
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers
 ENV SCRIPT python2.7 ../x.py test && python2.7 ../x.py dist
index a8fc4c169fac43a5dc204d4fd56ddb1739f8c178..d30da544a8afc5d78391dee270bdf40e74a215d3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
+Subproject commit d30da544a8afc5d78391dee270bdf40e74a215d3
index f9013490418f3da598ef9bfe112411d5b0a2e9d6..8aefabe61fdf68b17294ea63662240d7b17908e1 100644 (file)
@@ -1291,15 +1291,18 @@ guaranteed to refer to the same memory address.
 
 Constant values must not have destructors, and otherwise permit most forms of
 data. Constants may refer to the address of other constants, in which case the
-address will have the `static` lifetime. The compiler is, however, still at
-liberty to translate the constant many times, so the address referred to may not
-be stable.
+address will have elided lifetimes where applicable, otherwise â€“ in most cases â€“
+defaulting to the `static` lifetime. (See below on [static lifetime elision].)
+The compiler is, however, still at liberty to translate the constant many times,
+so the address referred to may not be stable.
+
+[static lifetime elision]: #static-lifetime-elision
 
 Constants must be explicitly typed. The type may be `bool`, `char`, a number, or
 a type derived from those primitive types. The derived types are references with
 the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs.
 
-```
+```rust
 const BIT1: u32 = 1 << 0;
 const BIT2: u32 = 1 << 1;
 
@@ -1317,6 +1320,8 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
 };
 ```
 
+
+
 ### Static items
 
 A *static item* is similar to a *constant*, except that it represents a precise
@@ -1351,7 +1356,7 @@ running in the same process.
 Mutable statics are still very useful, however. They can be used with C
 libraries and can also be bound from C libraries (in an `extern` block).
 
-```
+```rust
 # fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 }
 
 static mut LEVELS: u32 = 0;
@@ -1375,6 +1380,53 @@ unsafe fn bump_levels_unsafe2() -> u32 {
 Mutable statics have the same restrictions as normal statics, except that the
 type of the value is not required to ascribe to `Sync`.
 
+#### `'static` lifetime elision
+
+[Unstable] Both constant and static declarations of reference types have
+*implicit* `'static` lifetimes unless an explicit lifetime is specified. As
+such, the constant declarations involving `'static` above may be written
+without the lifetimes. Returning to our previous example:
+
+```rust
+# #![feature(static_in_const)]
+const BIT1: u32 = 1 << 0;
+const BIT2: u32 = 1 << 1;
+
+const BITS: [u32; 2] = [BIT1, BIT2];
+const STRING: &str = "bitstring";
+
+struct BitsNStrings<'a> {
+    mybits: [u32; 2],
+    mystring: &'a str,
+}
+
+const BITS_N_STRINGS: BitsNStrings = BitsNStrings {
+    mybits: BITS,
+    mystring: STRING,
+};
+```
+
+Note that if the `static` or `const` items include function or closure
+references, which themselves include references, the compiler will first try the
+standard elision rules ([see discussion in the nomicon][elision-nomicon]). If it
+is unable to resolve the lifetimes by its usual rules, it will default to using
+the `'static` lifetime. By way of example:
+
+[elision-nomicon]: https://doc.rust-lang.org/nomicon/lifetime-elision.html
+
+```rust,ignore
+// Resolved as `fn<'a>(&'a str) -> &'a str`.
+const RESOLVED_SINGLE: fn(&str) -> &str = ..
+
+// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
+const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = ..
+
+// There is insufficient information to bound the return reference lifetime
+// relative to the argument lifetimes, so the signature is resolved as
+// `Fn(&'static Foo, &'static Bar) -> &'static Baz`.
+const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = ..
+```
+
 ### Traits
 
 A _trait_ describes an abstract interface that types can
@@ -2072,7 +2124,9 @@ macro scope.
 
 ### Miscellaneous attributes
 
-- `deprecated` - mark the item as deprecated; the full attribute is `#[deprecated(since = "crate version", note = "...")`, where both arguments are optional.
+- `deprecated` - mark the item as deprecated; the full attribute is 
+  `#[deprecated(since = "crate version", note = "...")`, where both arguments 
+  are optional.
 - `export_name` - on statics and functions, this determines the name of the
   exported symbol.
 - `link_section` - on statics and functions, this specifies the section of the
@@ -2489,9 +2543,6 @@ The currently implemented features of the reference compiler are:
             into a Rust program. This capability, especially the signature for the
             annotated function, is subject to change.
 
-* `static_in_const` - Enables lifetime elision with a `'static` default for
-                      `const` and `static` item declarations.
-
 * `thread_local` - The usage of the `#[thread_local]` attribute is experimental
                    and should be seen as unstable. This attribute is used to
                    declare a `static` as being unique per-thread leveraging
index 6537cc1adce001fa3c88522278c89c7524790da1..2d80fc32c469dc111f37eb8487811ea9940c24ba 100644 (file)
@@ -229,6 +229,7 @@ fn dylib_dependency_formats(&self, cnum: CrateNum)
     fn is_allocator(&self, cnum: CrateNum) -> bool;
     fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
     fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
+    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
     fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
     fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
     /// The name of the crate as it is referred to in source code of the current
@@ -390,6 +391,7 @@ fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
     fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
     fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
     fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
+    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
     fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
         bug!("panic_strategy")
     }
index d41c2ba93b93533a524e45f3be5b4028d5f29925..24615f2fa699213346c07cb91034d79e4a60161b 100644 (file)
@@ -51,6 +51,14 @@ pub struct Config {
     pub uint_type: UintTy,
 }
 
+#[derive(Clone)]
+pub enum Sanitizer {
+    Address,
+    Leak,
+    Memory,
+    Thread,
+}
+
 #[derive(Clone, Copy, PartialEq, Hash)]
 pub enum OptLevel {
     No, // -O0
@@ -626,11 +634,13 @@ mod $mod_desc {
             Some("a number");
         pub const parse_panic_strategy: Option<&'static str> =
             Some("either `panic` or `abort`");
+        pub const parse_sanitizer: Option<&'static str> =
+            Some("one of: `address`, `leak`, `memory` or `thread`");
     }
 
     #[allow(dead_code)]
     mod $mod_set {
-        use super::{$struct_name, Passes, SomePasses, AllPasses};
+        use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
         use rustc_back::PanicStrategy;
 
         $(
@@ -751,6 +761,17 @@ fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bo
             }
             true
         }
+
+        fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
+            match v {
+                Some("address") => *slote = Some(Sanitizer::Address),
+                Some("leak") => *slote = Some(Sanitizer::Leak),
+                Some("memory") => *slote = Some(Sanitizer::Memory),
+                Some("thread") => *slote = Some(Sanitizer::Thread),
+                _ => return false,
+            }
+            true
+        }
     }
 ) }
 
@@ -949,6 +970,8 @@ fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bo
           "encode MIR of all functions into the crate metadata"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
           "pass `-install_name @rpath/...` to the OSX linker"),
+    sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [UNTRACKED],
+                                   "Use a sanitizer"),
 }
 
 pub fn default_lib_output() -> CrateType {
diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml
new file mode 100644 (file)
index 0000000..2d4872b
--- /dev/null
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+build = "build.rs"
+name = "rustc_asan"
+version = "0.0.0"
+
+[lib]
+name = "rustc_asan"
+path = "lib.rs"
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
new file mode 100644 (file)
index 0000000..015be14
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate build_helper;
+extern crate cmake;
+
+use std::path::PathBuf;
+use std::env;
+
+use cmake::Config;
+
+fn main() {
+    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
+        let dst = Config::new("../compiler-rt")
+            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
+            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
+            .define("COMPILER_RT_BUILD_XRAY", "OFF")
+            .define("LLVM_CONFIG_PATH", llvm_config)
+            .build_target("asan")
+            .build();
+
+        println!("cargo:rustc-link-search=native={}",
+                 dst.join("build/lib/linux").display());
+        println!("cargo:rustc-link-lib=static=clang_rt.asan-x86_64");
+
+        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
+                .unwrap())
+            .join("../compiler-rt"));
+    }
+
+    println!("cargo:rerun-if-changed=build.rs");
+}
diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs
new file mode 100644 (file)
index 0000000..71a166b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(not(stage0), feature(sanitizer_runtime))]
+#![cfg_attr(not(stage0), sanitizer_runtime)]
+#![feature(alloc_system)]
+#![feature(staged_api)]
+#![no_std]
+#![unstable(feature = "sanitizer_runtime_lib",
+            reason = "internal implementation detail of sanitizers",
+            issue = "0")]
+
+extern crate alloc_system;
index 07d36448ab0f8dcd4a4403b0525a4106e012569e..949e949f673a2b39dd084162d20d8c4606bb3d56 100644 (file)
@@ -126,6 +126,9 @@ pub enum Attribute {
     UWTable         = 17,
     ZExt            = 18,
     InReg           = 19,
+    SanitizeThread  = 20,
+    SanitizeAddress = 21,
+    SanitizeMemory  = 22,
 }
 
 /// LLVMIntPredicate
diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml
new file mode 100644 (file)
index 0000000..bc1f2ea
--- /dev/null
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+build = "build.rs"
+name = "rustc_lsan"
+version = "0.0.0"
+
+[lib]
+name = "rustc_lsan"
+path = "lib.rs"
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
new file mode 100644 (file)
index 0000000..5773777
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate build_helper;
+extern crate cmake;
+
+use std::path::PathBuf;
+use std::env;
+
+use cmake::Config;
+
+fn main() {
+    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
+        let dst = Config::new("../compiler-rt")
+            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
+            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
+            .define("COMPILER_RT_BUILD_XRAY", "OFF")
+            .define("LLVM_CONFIG_PATH", llvm_config)
+            .build_target("lsan")
+            .build();
+
+        println!("cargo:rustc-link-search=native={}",
+                 dst.join("build/lib/linux").display());
+        println!("cargo:rustc-link-lib=static=clang_rt.lsan-x86_64");
+
+        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
+                .unwrap())
+            .join("../compiler-rt"));
+    }
+
+    println!("cargo:rerun-if-changed=build.rs");
+}
diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs
new file mode 100644 (file)
index 0000000..71a166b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(not(stage0), feature(sanitizer_runtime))]
+#![cfg_attr(not(stage0), sanitizer_runtime)]
+#![feature(alloc_system)]
+#![feature(staged_api)]
+#![no_std]
+#![unstable(feature = "sanitizer_runtime_lib",
+            reason = "internal implementation detail of sanitizers",
+            issue = "0")]
+
+extern crate alloc_system;
index 81a4f7c93b6e91abe2eec44da15ef705b8dbccb9..55dc5aa2876f6bab0002341acdaae62c6a48fdd4 100644 (file)
@@ -17,7 +17,8 @@
 use rustc::hir::def_id::{CrateNum, DefIndex};
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::DepKind;
-use rustc::session::{config, Session};
+use rustc::session::Session;
+use rustc::session::config::{Sanitizer, self};
 use rustc_back::PanicStrategy;
 use rustc::session::search_paths::PathKind;
 use rustc::middle;
@@ -786,6 +787,64 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
                                   &|data| data.needs_panic_runtime());
     }
 
+    fn inject_sanitizer_runtime(&mut self) {
+        if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
+            // Sanitizers can only be used with x86_64 Linux executables linked
+            // to `std`
+            if self.sess.target.target.llvm_target != "x86_64-unknown-linux-gnu" {
+                self.sess.err(&format!("Sanitizers only work with the \
+                                        `x86_64-unknown-linux-gnu` target."));
+                return
+            }
+
+            if !self.sess.crate_types.borrow().iter().all(|ct| {
+                match *ct {
+                    // Link the runtime
+                    config::CrateTypeExecutable => true,
+                    // This crate will be compiled with the required
+                    // instrumentation pass
+                    config::CrateTypeRlib => false,
+                    _ => {
+                        self.sess.err(&format!("Only executables and rlibs can be \
+                                                compiled with `-Z sanitizer`"));
+                        false
+                    }
+                }
+            }) {
+                return
+            }
+
+            let mut uses_std = false;
+            self.cstore.iter_crate_data(|_, data| {
+                if data.name == "std" {
+                    uses_std = true;
+                }
+            });
+
+            if uses_std {
+                let name = match *sanitizer {
+                    Sanitizer::Address => "rustc_asan",
+                    Sanitizer::Leak => "rustc_lsan",
+                    Sanitizer::Memory => "rustc_msan",
+                    Sanitizer::Thread => "rustc_tsan",
+                };
+                info!("loading sanitizer: {}", name);
+
+                let symbol = Symbol::intern(name);
+                let dep_kind = DepKind::Implicit;
+                let (_, data) =
+                    self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
+                                       PathKind::Crate, dep_kind);
+
+                // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
+                if !data.is_sanitizer_runtime() {
+                    self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
+                                           name));
+                }
+            }
+        }
+    }
+
     fn inject_allocator_crate(&mut self) {
         // Make sure that we actually need an allocator, if none of our
         // dependencies need one then we definitely don't!
@@ -982,6 +1041,9 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod,
 
 impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
     fn postprocess(&mut self, krate: &ast::Crate) {
+        // inject the sanitizer runtime before the allocator runtime because all
+        // sanitizers force the use of the `alloc_system` allocator
+        self.inject_sanitizer_runtime();
         self.inject_allocator_crate();
         self.inject_panic_runtime(krate);
 
index beba5faf3d03407c67f3c8558317a6b7188b1d97..4709ca6101c7908f11e8ce5ef7e9cd5a96d090ec 100644 (file)
@@ -297,6 +297,11 @@ pub fn is_compiler_builtins(&self) -> bool {
         attr::contains_name(&attrs, "compiler_builtins")
     }
 
+    pub fn is_sanitizer_runtime(&self) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+        attr::contains_name(&attrs, "sanitizer_runtime")
+    }
+
     pub fn is_no_builtins(&self) -> bool {
         let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
         attr::contains_name(&attrs, "no_builtins")
index 39581a46960887069faecd871888335f49a89c95..7b0177bfd23ed966a2b4fef4a5e6195770e7edb5 100644 (file)
@@ -297,6 +297,10 @@ fn is_compiler_builtins(&self, cnum: CrateNum) -> bool {
         self.get_crate_data(cnum).is_compiler_builtins()
     }
 
+    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool {
+        self.get_crate_data(cnum).is_sanitizer_runtime()
+    }
+
     fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
         self.get_crate_data(cnum).panic_strategy()
     }
diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml
new file mode 100644 (file)
index 0000000..45cc6b9
--- /dev/null
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+build = "build.rs"
+name = "rustc_msan"
+version = "0.0.0"
+
+[lib]
+name = "rustc_msan"
+path = "lib.rs"
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
new file mode 100644 (file)
index 0000000..7a4c8f7
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate build_helper;
+extern crate cmake;
+
+use std::path::PathBuf;
+use std::env;
+
+use cmake::Config;
+
+fn main() {
+    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
+        let dst = Config::new("../compiler-rt")
+            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
+            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
+            .define("COMPILER_RT_BUILD_XRAY", "OFF")
+            .define("LLVM_CONFIG_PATH", llvm_config)
+            .build_target("msan")
+            .build();
+
+        println!("cargo:rustc-link-search=native={}",
+                 dst.join("build/lib/linux").display());
+        println!("cargo:rustc-link-lib=static=clang_rt.msan-x86_64");
+
+        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
+                .unwrap())
+            .join("../compiler-rt"));
+    }
+
+    println!("cargo:rerun-if-changed=build.rs");
+}
diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs
new file mode 100644 (file)
index 0000000..71a166b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(not(stage0), feature(sanitizer_runtime))]
+#![cfg_attr(not(stage0), sanitizer_runtime)]
+#![feature(alloc_system)]
+#![feature(staged_api)]
+#![no_std]
+#![unstable(feature = "sanitizer_runtime_lib",
+            reason = "internal implementation detail of sanitizers",
+            issue = "0")]
+
+extern crate alloc_system;
index 4ddf8a883bc488781efd48a31d5758eefb7460b0..1cbfa26b705ac8190d6ba15e49477116d767c337 100644 (file)
@@ -1031,6 +1031,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
         // symbols from the dylib.
         let src = sess.cstore.used_crate_source(cnum);
         match data[cnum.as_usize() - 1] {
+            _ if sess.cstore.is_sanitizer_runtime(cnum) => {
+                link_sanitizer_runtime(cmd, sess, tmpdir, cnum);
+            }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
             _ if sess.cstore.is_compiler_builtins(cnum) => {
@@ -1048,6 +1051,8 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
         }
     }
 
+    // compiler-builtins are always placed last to ensure that they're
+    // linked correctly.
     // We must always link the `compiler_builtins` crate statically. Even if it
     // was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic`
     // is used)
@@ -1064,6 +1069,34 @@ fn unlib<'a>(config: &config::Config, stem: &'a str) -> &'a str {
         }
     }
 
+    // We must link the sanitizer runtime using -Wl,--whole-archive but since
+    // it's packed in a .rlib, it contains stuff that are not objects that will
+    // make the linker error. So we must remove those bits from the .rlib before
+    // linking it.
+    fn link_sanitizer_runtime(cmd: &mut Linker,
+                              sess: &Session,
+                              tmpdir: &Path,
+                              cnum: CrateNum) {
+        let src = sess.cstore.used_crate_source(cnum);
+        let cratepath = &src.rlib.unwrap().0;
+        let dst = tmpdir.join(cratepath.file_name().unwrap());
+        let cfg = archive_config(sess, &dst, Some(cratepath));
+        let mut archive = ArchiveBuilder::new(cfg);
+        archive.update_symbols();
+
+        for f in archive.src_files() {
+            if f.ends_with("bytecode.deflate") ||
+                f == sess.cstore.metadata_filename() {
+                    archive.remove_file(&f);
+                    continue
+                }
+        }
+
+        archive.build();
+
+        cmd.link_whole_rlib(&dst);
+    }
+
     // Adds the static "rlib" versions of all crates to the command line.
     // There's a bit of magic which happens here specifically related to LTO and
     // dynamic libraries. Specifically:
index 9a761e17e75e89ff344efb230cc1c5b28d298ebd..5c4a5a9a4423d3abdf4bd9a96b90cb1884d5417f 100644 (file)
@@ -12,7 +12,7 @@
 use back::link::{get_linker, remove};
 use back::symbol_export::ExportedSymbols;
 use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
-use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses};
+use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses, Sanitizer};
 use session::Session;
 use session::config::{self, OutputType};
 use llvm;
@@ -679,6 +679,22 @@ pub fn run_passes(sess: &Session,
     let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone());
     let mut metadata_config = ModuleConfig::new(tm, vec![]);
 
+    if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
+        match *sanitizer {
+            Sanitizer::Address => {
+                modules_config.passes.push("asan".to_owned());
+                modules_config.passes.push("asan-module".to_owned());
+            }
+            Sanitizer::Memory => {
+                modules_config.passes.push("msan".to_owned())
+            }
+            Sanitizer::Thread => {
+                modules_config.passes.push("tsan".to_owned())
+            }
+            _ => {}
+        }
+    }
+
     modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
     modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));
 
index bf7a02eb0f196c7fdc6306f6a8a2c35fd3014afd..7ac482459ee39f5846a3dd4ec807bbde27cb8405 100644 (file)
@@ -23,6 +23,7 @@
 use llvm::{self, ValueRef};
 use llvm::AttributePlace::Function;
 use rustc::ty;
+use rustc::session::config::Sanitizer;
 use abi::{Abi, FnType};
 use attributes;
 use context::CrateContext;
@@ -72,6 +73,21 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
         llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
     }
 
+    if let Some(ref sanitizer) = ccx.tcx().sess.opts.debugging_opts.sanitizer {
+        match *sanitizer {
+            Sanitizer::Address => {
+                llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
+            },
+            Sanitizer::Memory => {
+                llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
+            },
+            Sanitizer::Thread => {
+                llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
+            },
+            _ => {}
+        }
+    }
+
     // If we're compiling the compiler-builtins crate, e.g. the equivalent of
     // compiler-rt, then we want to implicitly compile everything with hidden
     // visibility as we're going to link this object all over the place but
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
new file mode 100644 (file)
index 0000000..66d6236
--- /dev/null
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+build = "build.rs"
+name = "rustc_tsan"
+version = "0.0.0"
+
+[lib]
+name = "rustc_tsan"
+path = "lib.rs"
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+cmake = "0.1.18"
+
+[dependencies]
+alloc_system = { path = "../liballoc_system" }
+core = { path = "../libcore" }
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
new file mode 100644 (file)
index 0000000..84326ae
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate build_helper;
+extern crate cmake;
+
+use std::path::PathBuf;
+use std::env;
+
+use cmake::Config;
+
+fn main() {
+    if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
+        let dst = Config::new("../compiler-rt")
+            .define("COMPILER_RT_BUILD_SANITIZERS", "ON")
+            .define("COMPILER_RT_BUILD_BUILTINS", "OFF")
+            .define("COMPILER_RT_BUILD_XRAY", "OFF")
+            .define("LLVM_CONFIG_PATH", llvm_config)
+            .build_target("tsan")
+            .build();
+
+        println!("cargo:rustc-link-search=native={}",
+                 dst.join("build/lib/linux").display());
+        println!("cargo:rustc-link-lib=static=clang_rt.tsan-x86_64");
+
+        build_helper::rerun_if_changed_anything_in_dir(&PathBuf::from(env::var("CARGO_MANIFEST_DIR")
+                .unwrap())
+            .join("../compiler-rt"));
+    }
+
+    println!("cargo:rerun-if-changed=build.rs");
+}
diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs
new file mode 100644 (file)
index 0000000..71a166b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(not(stage0), feature(sanitizer_runtime))]
+#![cfg_attr(not(stage0), sanitizer_runtime)]
+#![feature(alloc_system)]
+#![feature(staged_api)]
+#![no_std]
+#![unstable(feature = "sanitizer_runtime_lib",
+            reason = "internal implementation detail of sanitizers",
+            issue = "0")]
+
+extern crate alloc_system;
index 60dae19d876c98a765d9b9e1cfa6a5d94f8c2af4..c591c09bf20e2701b221f806ad659249bf899d3b 100644 (file)
@@ -671,9 +671,11 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
                 }
                 _ => {
                     if f.alternate() {
-                        write!(f, "&{}{}{:#}", lt, m, **ty)
+                        write!(f, "&{}{}", lt, m)?;
+                        fmt_type(&ty, f, use_absolute)
                     } else {
-                        write!(f, "&amp;{}{}{}", lt, m, **ty)
+                        write!(f, "&amp;{}{}", lt, m)?;
+                        fmt_type(&ty, f, use_absolute)
                     }
                 }
             }
index 40eb7e5ab78c3df024e83346641c41979913fc76..6234d89024441b946e3d3aba0ba0503b6d9d2385 100644 (file)
@@ -2132,10 +2132,23 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
         <ul class='item-list' id='implementors-list'>
     ")?;
     if let Some(implementors) = cache.implementors.get(&it.def_id) {
-        let mut implementor_count: FxHashMap<&str, usize> = FxHashMap();
+        // The DefId is for the first Type found with that name. The bool is
+        // if any Types with the same name but different DefId have been found.
+        let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
         for implementor in implementors {
-            if let clean::Type::ResolvedPath {ref path, ..} = implementor.impl_.for_ {
-                *implementor_count.entry(path.last_name()).or_insert(0) += 1;
+            match implementor.impl_.for_ {
+                clean::ResolvedPath { ref path, did, is_generic: false, .. } |
+                clean::BorrowedRef {
+                    type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
+                    ..
+                } => {
+                    let &mut (prev_did, ref mut has_duplicates) =
+                        implementor_dups.entry(path.last_name()).or_insert((did, false));
+                    if prev_did != did {
+                        *has_duplicates = true;
+                    }
+                }
+                _ => {}
             }
         }
 
@@ -2143,12 +2156,13 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
             write!(w, "<li><code>")?;
             // If there's already another implementor that has the same abbridged name, use the
             // full path, for example in `std::iter::ExactSizeIterator`
-            let use_absolute = if let clean::Type::ResolvedPath {
-                ref path, ..
-            } = implementor.impl_.for_ {
-                implementor_count[path.last_name()] > 1
-            } else {
-                false
+            let use_absolute = match implementor.impl_.for_ {
+                clean::ResolvedPath { ref path, is_generic: false, .. } |
+                clean::BorrowedRef {
+                    type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
+                    ..
+                } => implementor_dups[path.last_name()].1,
+                _ => false,
             };
             fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
             writeln!(w, "</code></li>")?;
index 8146e7fb1edaf4a5b0a413d781a06dbd7d7b943b..2ba7517d3d2023761a0cc24838d184fe2c95d2f4 100644 (file)
@@ -23,13 +23,23 @@ compiler_builtins = { path = "../libcompiler_builtins" }
 std_unicode = { path = "../libstd_unicode" }
 unwind = { path = "../libunwind" }
 
+[target.x86_64-unknown-linux-gnu.dependencies]
+rustc_asan = { path = "../librustc_asan", optional = true }
+rustc_lsan = { path = "../librustc_lsan", optional = true }
+rustc_msan = { path = "../librustc_msan", optional = true }
+rustc_tsan = { path = "../librustc_tsan", optional = true }
+
 [build-dependencies]
 build_helper = { path = "../build_helper" }
 gcc = "0.3.27"
 
 [features]
+asan = ["rustc_asan"]
 backtrace = []
 debug-jemalloc = ["alloc_jemalloc/debug"]
 jemalloc = ["alloc_jemalloc"]
 force_alloc_system = []
+lsan = ["rustc_lsan"]
+msan = ["rustc_msan"]
 panic-unwind = ["panic_unwind"]
+tsan = ["rustc_tsan"]
index e26415392949175499c870fd6d2143c7e91b2415..1ef2cb4ed153c2e5d4e78eba2531e86031ecc29d 100644 (file)
@@ -400,15 +400,19 @@ pub struct JoinPathsError {
     inner: os_imp::JoinPathsError
 }
 
-/// Joins a collection of `Path`s appropriately for the `PATH`
+/// Joins a collection of [`Path`]s appropriately for the `PATH`
 /// environment variable.
 ///
-/// Returns an `OsString` on success.
+/// Returns an [`OsString`] on success.
 ///
-/// Returns an `Err` (containing an error message) if one of the input
-/// `Path`s contains an invalid character for constructing the `PATH`
+/// Returns an [`Err`][err] (containing an error message) if one of the input
+/// [`Path`]s contains an invalid character for constructing the `PATH`
 /// variable (a double quote on Windows or a colon on Unix).
 ///
+/// [`Path`]: ../../std/path/struct.Path.html
+/// [`OsString`]: ../../std/ffi/struct.OsString.html
+/// [err]: ../../std/result/enum.Result.html#variant.Err
+///
 /// # Examples
 ///
 /// ```
index a78c192a120df22bd5496b48eaa44d5d03d718bb..cc0a67b3d2e94b64c46ac60f29deffc5a9deebb0 100644 (file)
@@ -328,6 +328,10 @@ pub fn new() -> Features {
 
     // `extern "msp430-interrupt" fn()`
     (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
+
+    // Used to identify crates that contain sanitizer runtimes
+    // rustc internal
+    (active, sanitizer_runtime, "1.17.0", None),
 );
 
 declare_features! (
@@ -647,6 +651,12 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                               contains compiler-rt intrinsics and will never be \
                                               stable",
                                           cfg_fn!(compiler_builtins))),
+    ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
+                                             "sanitizer_runtime",
+                                             "the `#[sanitizer_runtime]` attribute is used to \
+                                              identify crates that contain the runtime of a \
+                                              sanitizer and will never be stable",
+                                             cfg_fn!(sanitizer_runtime))),
 
     ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
                                               "allow_internal_unstable",
index 14c9c5544b188561d41302d3a22ac5a6dcbc32ee..db96079d3e916e1fb789fe88bdab6a39a90de3cb 100644 (file)
@@ -35,8 +35,12 @@ core = { path = "../../libcore" }
 
 # Reexport features from std
 [features]
+asan = ["std/asan"]
 backtrace = ["std/backtrace"]
 debug-jemalloc = ["std/debug-jemalloc"]
 jemalloc = ["std/jemalloc"]
 force_alloc_system = ["std/force_alloc_system"]
+lsan = ["std/lsan"]
+msan = ["std/msan"]
 panic-unwind = ["std/panic-unwind"]
+tsan = ["std/tsan"]
index 4e201c254e39f4f9bc9bb17e029368b468f580ea..f3b52b71b99c12655dfcdbc9fa86294e7af5551e 100644 (file)
@@ -148,6 +148,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
     return Attribute::ZExt;
   case InReg:
     return Attribute::InReg;
+  case SanitizeThread:
+    return Attribute::SanitizeThread;
+  case SanitizeAddress:
+    return Attribute::SanitizeAddress;
+  case SanitizeMemory:
+    return Attribute::SanitizeMemory;
   }
   llvm_unreachable("bad AttributeKind");
 }
index a30fa3133e2825b1403d0afa0dda7343846f9acc..0baf5528e9356574397864719da3747f44ed98a8 100644 (file)
@@ -98,6 +98,9 @@ enum LLVMRustAttribute {
   UWTable = 17,
   ZExt = 18,
   InReg = 19,
+  SanitizeThread = 20,
+  SanitizeAddress = 21,
+  SanitizeMemory = 22,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
diff --git a/src/test/compile-fail/feature-gate-sanitizer-runtime.rs b/src/test/compile-fail/feature-gate-sanitizer-runtime.rs
new file mode 100644 (file)
index 0000000..a18641d
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-27433.rs b/src/test/compile-fail/issue-27433.rs
new file mode 100644 (file)
index 0000000..78d9639
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let foo = 42u32;
+    const FOO : u32 = foo;
+                   //~^ ERROR attempt to use a non-constant value in a constant
+}
diff --git a/src/test/run-make/sanitizer-address/Makefile b/src/test/run-make/sanitizer-address/Makefile
new file mode 100644 (file)
index 0000000..5931145
--- /dev/null
@@ -0,0 +1,11 @@
+-include ../tools.mk
+
+# NOTE the address sanitizer only supports x86_64 linux
+ifdef SANITIZER_SUPPORT
+all:
+       $(RUSTC) -g -Z sanitizer=address -Z print-link-args overflow.rs | grep -q librustc_asan
+       $(TMPDIR)/overflow 2>&1 | grep -q stack-buffer-overflow
+else
+all:
+
+endif
diff --git a/src/test/run-make/sanitizer-address/overflow.rs b/src/test/run-make/sanitizer-address/overflow.rs
new file mode 100644 (file)
index 0000000..e35c387
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let xs = [0, 1, 2, 3];
+    let y = unsafe { *xs.as_ptr().offset(4) };
+}
diff --git a/src/test/run-make/sanitizer-dylib/Makefile b/src/test/run-make/sanitizer-dylib/Makefile
new file mode 100644 (file)
index 0000000..835d5b0
--- /dev/null
@@ -0,0 +1,8 @@
+-include ../tools.mk
+
+ifeq ($(TARGET),x86_64-unknown-linux-gnu)
+all:
+       $(RUSTC) -Z sanitizer=leak --crate-type dylib --target $(TARGET) hello.rs 2>&1 | grep -q 'Only executables and rlibs can be compiled with `-Z sanitizer`'
+else
+all:
+endif
diff --git a/src/test/run-make/sanitizer-dylib/hello.rs b/src/test/run-make/sanitizer-dylib/hello.rs
new file mode 100644 (file)
index 0000000..4178285
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/run-make/sanitizer-invalid-target/Makefile b/src/test/run-make/sanitizer-invalid-target/Makefile
new file mode 100644 (file)
index 0000000..6a1ce8b
--- /dev/null
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | grep -q 'Sanitizers only work with the `x86_64-unknown-linux-gnu` target'
diff --git a/src/test/run-make/sanitizer-invalid-target/hello.rs b/src/test/run-make/sanitizer-invalid-target/hello.rs
new file mode 100644 (file)
index 0000000..e9e46b7
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
diff --git a/src/test/run-make/sanitizer-leak/Makefile b/src/test/run-make/sanitizer-leak/Makefile
new file mode 100644 (file)
index 0000000..f02d948
--- /dev/null
@@ -0,0 +1,10 @@
+-include ../tools.mk
+
+ifdef SANITIZER_SUPPORT
+all:
+       $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | grep -q librustc_lsan
+       $(TMPDIR)/leak 2>&1 | grep -q 'detected memory leaks'
+else
+all:
+
+endif
diff --git a/src/test/run-make/sanitizer-leak/leak.rs b/src/test/run-make/sanitizer-leak/leak.rs
new file mode 100644 (file)
index 0000000..279da6a
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::mem;
+
+fn main() {
+    let xs = vec![1, 2, 3, 4];
+    mem::forget(xs);
+}
diff --git a/src/test/run-make/sanitizer-memory/Makefile b/src/test/run-make/sanitizer-memory/Makefile
new file mode 100644 (file)
index 0000000..08682e5
--- /dev/null
@@ -0,0 +1,10 @@
+-include ../tools.mk
+
+ifdef SANITIZER_SUPPORT
+all:
+       $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | grep -q librustc_msan
+       $(TMPDIR)/uninit 2>&1 | grep -q use-of-uninitialized-value
+else
+all:
+
+endif
diff --git a/src/test/run-make/sanitizer-memory/uninit.rs b/src/test/run-make/sanitizer-memory/uninit.rs
new file mode 100644 (file)
index 0000000..8350c7d
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::mem;
+
+fn main() {
+    let xs: [u8; 4] = unsafe { mem::uninitialized() };
+    let y = xs[0] + xs[1];
+}
diff --git a/src/test/run-make/sanitizer-thread/Makefile b/src/test/run-make/sanitizer-thread/Makefile
new file mode 100644 (file)
index 0000000..8bb89a2
--- /dev/null
@@ -0,0 +1,10 @@
+-include ../tools.mk
+
+ifdef SANITIZER_SUPPORT
+all:
+       $(RUSTC) -g -Z sanitizer=thread -Z print-link-args racy.rs | grep -q librustc_tsan
+       $(TMPDIR)/racy 2>&1 | grep -q 'data race'
+else
+all:
+
+endif
diff --git a/src/test/run-make/sanitizer-thread/racy.rs b/src/test/run-make/sanitizer-thread/racy.rs
new file mode 100644 (file)
index 0000000..dc929e0
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::thread;
+
+static mut ANSWER: i32 = 0;
+
+fn main() {
+    let t1 = thread::spawn(|| unsafe { ANSWER = 42 });
+    unsafe {
+        ANSWER = 24;
+    }
+    t1.join().ok();
+}
diff --git a/src/test/rustdoc/impl-disambiguation.rs b/src/test/rustdoc/impl-disambiguation.rs
new file mode 100644 (file)
index 0000000..afe1daf
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+pub trait Foo {}
+
+pub struct Bar<T> { field: T }
+
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+//     "impl Foo for Bar<u8>"
+impl Foo for Bar<u8> {}
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+//     "impl Foo for Bar<u16>"
+impl Foo for Bar<u16> {}
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+//     "impl<'a> Foo for &'a Bar<u8>"
+impl<'a> Foo for &'a Bar<u8> {}
+
+pub mod mod1 {
+    pub struct Baz {}
+}
+
+pub mod mod2 {
+    pub enum Baz {}
+}
+
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+//     "impl Foo for foo::mod1::Baz"
+impl Foo for mod1::Baz {}
+// @has foo/trait.Foo.html '//*[@class="item-list"]//code' \
+//     "impl<'a> Foo for &'a foo::mod2::Baz"
+impl<'a> Foo for &'a mod2::Baz {}
index 548a11439f5ccf44e645ba089f3050447a9cec40..0aefe703c9ca7de3e540801f1ded23012dab2987 100644 (file)
@@ -326,6 +326,8 @@ fn url(&self, component: &str, target: &str) -> String {
     fn filename(&self, component: &str, target: &str) -> String {
         if component == "rust-src" {
             format!("rust-src-{}.tar.gz", self.channel)
+        } else if component == "cargo" {
+            format!("cargo-nightly-{}.tar.gz", target)
         } else {
             format!("{}-{}-{}.tar.gz", component, self.channel, target)
         }