]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #54869 - GuillaumeGomez:fix-mobile-docs, r=QuietMisdreavus
authorkennytm <kennytm@gmail.com>
Fri, 12 Oct 2018 14:04:05 +0000 (22:04 +0800)
committerGitHub <noreply@github.com>
Fri, 12 Oct 2018 14:04:05 +0000 (22:04 +0800)
Fix mobile docs

Fixes #54836.

<img width="1440" alt="screen shot 2018-10-06 at 18 53 19" src="https://user-images.githubusercontent.com/3050060/46573683-1b4cd700-c999-11e8-9e6b-86a23b332e22.png">

r? @QuietMisdreavus

28 files changed:
config.toml.example
src/bootstrap/config.rs
src/etc/gdb_rust_pretty_printing.py
src/liballoc/collections/btree/node.rs
src/liballoc/lib.rs
src/liballoc/vec.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/declare.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
src/librustdoc/html/highlight.rs
src/libstd/primitive_docs.rs
src/libsyntax/parse/lexer/mod.rs
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.h
src/test/codegen/naked-functions.rs
src/test/codegen/no-plt.rs [new file with mode: 0644]
src/test/rustdoc-ui/invalid-syntax.rs [new file with mode: 0644]
src/test/rustdoc-ui/invalid-syntax.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr
src/test/ui/issues/issue-20801.nll.stderr

index 312270532affc7bbaaaa1001f0effeb1bd229055..1c851999130a0213ae5daded08d1e8eda4f637ae 100644 (file)
 # =============================================================================
 [rust]
 
-# Indicates that the build should be optimized for debugging Rust. Note that
-# this is typically not what you want as it takes an incredibly large amount of
-# time to have a debug-mode rustc compile any code (notably libstd). If this
-# value is set to `true` it will affect a number of configuration options below
-# as well, if unconfigured.
-#debug = false
-
-# Whether or not to optimize the compiler and standard library
+# Whether or not to optimize the compiler and standard library.
+#
 # Note: the slowness of the non optimized compiler compiling itself usually
 #       outweighs the time gains in not doing optimizations, therefore a
-#       full bootstrap takes much more time with optimize set to false.
+#       full bootstrap takes much more time with `optimize` set to false.
 #optimize = true
 
+# Indicates that the build should be configured for debugging Rust. A
+# `debug`-enabled compiler and standard library will be somewhat
+# slower (due to e.g. checking of debug assertions) but should remain
+# usable.
+#
+# Note: If this value is set to `true`, it will affect a number of
+#       configuration options below as well, if they have been left
+#       unconfigured in this file.
+#
+# Note: changes to the `debug` setting do *not* affect `optimize`
+#       above. In theory, a "maximally debuggable" environment would
+#       set `optimize` to `false` above to assist the introspection
+#       facilities of debuggers like lldb and gdb. To recreate such an
+#       environment, explicitly set `optimize` to `false` and `debug`
+#       to `true`. In practice, everyone leaves `optimize` set to
+#       `true`, because an unoptimized rustc with debugging
+#       enabled becomes *unusably slow* (e.g. rust-lang/rust#24840
+#       reported a 25x slowdown) and bootstrapping the supposed
+#       "maximally debuggable" environment (notably libstd) takes
+#       hours to build.
+#
+#debug = false
+
 # Number of codegen units to use for each compiler invocation. A value of 0
 # means "the number of cores on this machine", and 1+ is passed through to the
 # compiler.
index c3fbc8eeca6ba65ee428f6cff468f05283334219..a5ed096a735810b09a0304faa53686c3aa1bac33 100644 (file)
@@ -628,6 +628,9 @@ pub fn parse(args: &[String]) -> Config {
         let default = false;
         config.llvm_assertions = llvm_assertions.unwrap_or(default);
 
+        let default = true;
+        config.rust_optimize = optimize.unwrap_or(default);
+
         let default = match &config.channel[..] {
             "stable" | "beta" | "nightly" => true,
             _ => false,
@@ -640,7 +643,6 @@ pub fn parse(args: &[String]) -> Config {
         config.debug_jemalloc = debug_jemalloc.unwrap_or(default);
         config.rust_debuginfo = debuginfo.unwrap_or(default);
         config.rust_debug_assertions = debug_assertions.unwrap_or(default);
-        config.rust_optimize = optimize.unwrap_or(!default);
 
         let default = config.channel == "dev";
         config.ignore_git = ignore_git.unwrap_or(default);
index 216915dba5fe7c03116d1cf2906afd7bbafe392f..b1252f386df364dcd18708dc5bc6139fe465e0dd 100755 (executable)
@@ -322,8 +322,11 @@ class RustStdBTreeSetPrinter(object):
     def children(self):
         (length, data_ptr) = \
             rustpp.extract_length_and_ptr_from_std_btreeset(self.__val)
-        val = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3)
-        gdb_ptr = val.get_wrapped_value()
+        leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference())
+        maybe_uninit_keys = leaf_node.get_child_at_index(3)
+        manually_drop_keys = maybe_uninit_keys.get_child_at_index(1)
+        keys = manually_drop_keys.get_child_at_index(0)
+        gdb_ptr = keys.get_wrapped_value()
         for index in xrange(length):
             yield (str(index), gdb_ptr[index])
 
@@ -345,9 +348,14 @@ class RustStdBTreeMapPrinter(object):
     def children(self):
         (length, data_ptr) = \
             rustpp.extract_length_and_ptr_from_std_btreemap(self.__val)
-        keys = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3)
+        leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference())
+        maybe_uninit_keys = leaf_node.get_child_at_index(3)
+        manually_drop_keys = maybe_uninit_keys.get_child_at_index(1)
+        keys = manually_drop_keys.get_child_at_index(0)
         keys_ptr = keys.get_wrapped_value()
-        vals = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(4)
+        maybe_uninit_vals = leaf_node.get_child_at_index(4)
+        manually_drop_vals = maybe_uninit_vals.get_child_at_index(1)
+        vals = manually_drop_vals.get_child_at_index(0)
         vals_ptr = vals.get_wrapped_value()
         for index in xrange(length):
             yield (str(index), keys_ptr[index])
index 0315545262b6bc0a295953f22b4328070223356b..deca9591fbd5c499210a17f6ed67990eda11fae3 100644 (file)
@@ -42,7 +42,7 @@
 //   This implies that even an empty internal node has at least one edge.
 
 use core::marker::PhantomData;
-use core::mem;
+use core::mem::{self, MaybeUninit};
 use core::ptr::{self, Unique, NonNull};
 use core::slice;
 
@@ -58,9 +58,6 @@
 /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
 /// case.
 ///
-/// See also rust-lang/rfcs#197, which would make this structure significantly more safe by
-/// avoiding accidentally dropping unused and uninitialized keys and values.
-///
 /// We put the metadata first so that its position is the same for every `K` and `V`, in order
 /// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
 /// prevent them from being reordered.
@@ -73,7 +70,7 @@ struct LeafNode<K, V> {
     /// This node's index into the parent node's `edges` array.
     /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
     /// This is only guaranteed to be initialized when `parent` is nonnull.
-    parent_idx: u16,
+    parent_idx: MaybeUninit<u16>,
 
     /// The number of keys and values this node stores.
     ///
@@ -83,8 +80,8 @@ struct LeafNode<K, V> {
 
     /// The arrays storing the actual data of the node. Only the first `len` elements of each
     /// array are initialized and valid.
-    keys: [K; CAPACITY],
-    vals: [V; CAPACITY],
+    keys: MaybeUninit<[K; CAPACITY]>,
+    vals: MaybeUninit<[V; CAPACITY]>,
 }
 
 impl<K, V> LeafNode<K, V> {
@@ -94,10 +91,10 @@ unsafe fn new() -> Self {
         LeafNode {
             // As a general policy, we leave fields uninitialized if they can be, as this should
             // be both slightly faster and easier to track in Valgrind.
-            keys: mem::uninitialized(),
-            vals: mem::uninitialized(),
+            keys: MaybeUninit::uninitialized(),
+            vals: MaybeUninit::uninitialized(),
             parent: ptr::null(),
-            parent_idx: mem::uninitialized(),
+            parent_idx: MaybeUninit::uninitialized(),
             len: 0
         }
     }
@@ -115,10 +112,10 @@ unsafe impl Sync for LeafNode<(), ()> {}
 // ever take a pointer past the first key.
 static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
     parent: ptr::null(),
-    parent_idx: 0,
+    parent_idx: MaybeUninit::uninitialized(),
     len: 0,
-    keys: [(); CAPACITY],
-    vals: [(); CAPACITY],
+    keys: MaybeUninit::uninitialized(),
+    vals: MaybeUninit::uninitialized(),
 };
 
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
@@ -430,7 +427,7 @@ pub fn ascend(self) -> Result<
                     root: self.root,
                     _marker: PhantomData
                 },
-                idx: self.as_leaf().parent_idx as usize,
+                idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
                 _marker: PhantomData
             })
         } else {
@@ -567,7 +564,7 @@ fn into_key_slice(self) -> &'a [K] {
             // the node, which is allowed by LLVM.
             unsafe {
                 slice::from_raw_parts(
-                    self.as_leaf().keys.as_ptr(),
+                    self.as_leaf().keys.as_ptr() as *const K,
                     self.len()
                 )
             }
@@ -578,7 +575,7 @@ fn into_val_slice(self) -> &'a [V] {
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts(
-                self.as_leaf().vals.as_ptr(),
+                self.as_leaf().vals.as_ptr() as *const V,
                 self.len()
             )
         }
@@ -605,7 +602,7 @@ fn into_key_slice_mut(mut self) -> &'a mut [K] {
         } else {
             unsafe {
                 slice::from_raw_parts_mut(
-                    &mut self.as_leaf_mut().keys as *mut [K] as *mut K,
+                    self.as_leaf_mut().keys.get_mut() as *mut [K] as *mut K,
                     self.len()
                 )
             }
@@ -616,7 +613,7 @@ fn into_val_slice_mut(mut self) -> &'a mut [V] {
         debug_assert!(!self.is_shared_root());
         unsafe {
             slice::from_raw_parts_mut(
-                &mut self.as_leaf_mut().vals as *mut [V] as *mut V,
+                self.as_leaf_mut().vals.get_mut() as *mut [V] as *mut V,
                 self.len()
             )
         }
@@ -1013,7 +1010,7 @@ fn correct_parent_link(mut self) {
         let ptr = self.node.as_internal_mut() as *mut _;
         let mut child = self.descend();
         child.as_leaf_mut().parent = ptr;
-        child.as_leaf_mut().parent_idx = idx;
+        child.as_leaf_mut().parent_idx.set(idx);
     }
 
     /// Unsafely asserts to the compiler some static information about whether the underlying
@@ -1152,12 +1149,12 @@ pub fn split(mut self)
 
             ptr::copy_nonoverlapping(
                 self.node.keys().as_ptr().add(self.idx + 1),
-                new_node.keys.as_mut_ptr(),
+                new_node.keys.as_mut_ptr() as *mut K,
                 new_len
             );
             ptr::copy_nonoverlapping(
                 self.node.vals().as_ptr().add(self.idx + 1),
-                new_node.vals.as_mut_ptr(),
+                new_node.vals.as_mut_ptr() as *mut V,
                 new_len
             );
 
@@ -1210,12 +1207,12 @@ pub fn split(mut self)
 
             ptr::copy_nonoverlapping(
                 self.node.keys().as_ptr().add(self.idx + 1),
-                new_node.data.keys.as_mut_ptr(),
+                new_node.data.keys.as_mut_ptr() as *mut K,
                 new_len
             );
             ptr::copy_nonoverlapping(
                 self.node.vals().as_ptr().add(self.idx + 1),
-                new_node.data.vals.as_mut_ptr(),
+                new_node.data.vals.as_mut_ptr() as *mut V,
                 new_len
             );
             ptr::copy_nonoverlapping(
index 78d1958b8fb37a3270ae3eadff617e3282581b7a..987572e6b74a9c2dbb803b60aafb2e7f503798bd 100644 (file)
 #![feature(rustc_const_unstable)]
 #![feature(const_vec_new)]
 #![feature(slice_partition_dedup)]
+#![feature(maybe_uninit)]
 
 // Allow testing this library
 
index 2bc037e3fee126343715212911c8b62e1d28867e..f7a0bbdceafc93325359fbb83a51b413548db0da 100644 (file)
 /// assert_eq!(vec, [1, 2, 3, 4]);
 /// ```
 ///
-/// It can also initialize each element of a `Vec<T>` with a given value:
+/// It can also initialize each element of a `Vec<T>` with a given value.
+/// This may be more efficient than performing allocation and initialization
+/// in separate steps, especially when initializing a vector of zeros:
 ///
 /// ```
 /// let vec = vec![0; 5];
 /// assert_eq!(vec, [0, 0, 0, 0, 0]);
+///
+/// // The following is equivalent, but potentially slower:
+/// let mut vec1 = Vec::with_capacity(5);
+/// vec1.resize(5, 0);
 /// ```
 ///
 /// Use a `Vec<T>` as an efficient stack:
index bd58dcf4ae055fd9578608f71b87919ccbb8658b..b8d7fcffbcc0968922dc2ed3d5786a0c70efb4be 100644 (file)
@@ -2370,13 +2370,13 @@ fn mod_inv(x: usize, m: usize) -> usize {
         ///
         /// Note, that this table does not contain values where inverse does not exist (i.e. for
         /// `0⁻¹ mod 16`, `2⁻¹ mod 16`, etc.)
-        const INV_TABLE_MOD_16: [usize; 8] = [1, 11, 13, 7, 9, 3, 5, 15];
+        const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15];
         /// Modulo for which the `INV_TABLE_MOD_16` is intended.
         const INV_TABLE_MOD: usize = 16;
         /// INV_TABLE_MOD²
         const INV_TABLE_MOD_SQUARED: usize = INV_TABLE_MOD * INV_TABLE_MOD;
 
-        let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1];
+        let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1] as usize;
         if m <= INV_TABLE_MOD {
             table_inverse & (m - 1)
         } else {
@@ -2429,36 +2429,23 @@ fn mod_inv(x: usize, m: usize) -> usize {
     let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a));
     let gcd = 1usize << gcdpow;
 
-    if gcd == 1 {
-        // This branch solves for the variable $o$ in following linear congruence equation:
-        //
-        // ⎰ p + o ≡ 0 (mod a)   # $p + o$ must be aligned to specified alignment $a$
-        // ⎱     o ≡ 0 (mod s)   # offset $o$ must be a multiple of stride $s$
-        //
-        // where
+    if p as usize & (gcd - 1) == 0 {
+        // This branch solves for the following linear congruence equation:
         //
-        // * a, s are co-prime
+        // $$ p + so ≡ 0 mod a $$
         //
-        // This gives us the formula below:
+        // $p$ here is the pointer value, $s$ – stride of `T`, $o$ offset in `T`s, and $a$ – the
+        // requested alignment.
         //
-        // o = (a - (p mod a)) * (s⁻¹ mod a) * s
+        // g = gcd(a, s)
+        // o = (a - (p mod a))/g * ((s/g)⁻¹ mod a)
         //
         // The first term is “the relative alignment of p to a”, the second term is “how does
-        // incrementing p by one s change the relative alignment of p”, the third term is
-        // translating change in units of s to a byte count.
+        // incrementing p by s bytes change the relative alignment of p”. Division by `g` is
+        // necessary to make this equation well formed if $a$ and $s$ are not co-prime.
         //
         // Furthermore, the result produced by this solution is not “minimal”, so it is necessary
-        // to take the result $o mod lcm(s, a)$. Since $s$ and $a$ are co-prime (i.e. $gcd(s, a) =
-        // 1$) and $lcm(s, a) = s * a / gcd(s, a)$, we can replace $lcm(s, a)$ with just a $s * a$.
-        //
-        // (Author note: we decided later on to express the offset in "elements" rather than bytes,
-        // which drops the multiplication by `s` on both sides of the modulo.)
-        return intrinsics::unchecked_rem(a.wrapping_sub(pmoda).wrapping_mul(mod_inv(smoda, a)), a);
-    }
-
-    if p as usize & (gcd - 1) == 0 {
-        // This can be aligned, but `a` and `stride` are not co-prime, so a somewhat adapted
-        // formula is used.
+        // to take the result $o mod lcm(s, a)$. We can replace $lcm(s, a)$ with just a $a / g$.
         let j = a.wrapping_sub(pmoda) >> gcdpow;
         let k = smoda >> gcdpow;
         return intrinsics::unchecked_rem(j.wrapping_mul(mod_inv(k, a)), a >> gcdpow);
index 76dcca0257817b6f6917345345827a69cf45ba83..c9013f589edd36eb9159d62b9a3c7bae9106d69d 100644 (file)
@@ -1932,7 +1932,7 @@ fn align_to_offsets<U>(&self) -> (usize, usize) {
         fn gcd(a: usize, b: usize) -> usize {
             // iterative stein’s algorithm
             // We should still make this `const fn` (and revert to recursive algorithm if we do)
-            // because relying on llvm to consteval all this is… well, it makes me
+            // because relying on llvm to consteval all this is… well, it makes me uncomfortable.
             let (ctz_a, mut ctz_b) = unsafe {
                 if a == 0 { return b; }
                 if b == 0 { return a; }
index c532b5ee56f47d2d908cf442795842f84b0182e5..d8c36f81da32427bfb86d2775babd1dced494f60 100644 (file)
@@ -1387,6 +1387,10 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
           "output a json file with profiler results"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
           "emits a section containing stack size metadata"),
+    plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
+          "whether to use the PLT when calling into shared libraries;
+          only has effect for PIC code on systems with ELF binaries
+          (default: PLT is disabled if full relro is enabled)"),
 }
 
 pub fn default_lib_output() -> CrateType {
index 3c209a4324675a5b0681375b7f9b75869f0d2ae0..10a506da4eab44c6cffbc8da7f5405ad357afffd 100644 (file)
@@ -40,8 +40,7 @@
 use syntax_pos::{MultiSpan, Span};
 use util::profiling::SelfProfiler;
 
-use rustc_target::spec::PanicStrategy;
-use rustc_target::spec::{Target, TargetTriple};
+use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
 use rustc_data_structures::flock;
 use jobserver::Client;
 
@@ -984,6 +983,27 @@ pub fn rust_2018(&self) -> bool {
     pub fn edition(&self) -> Edition {
         self.opts.edition
     }
+
+    /// True if we cannot skip the PLT for shared library calls.
+    pub fn needs_plt(&self) -> bool {
+        // Check if the current target usually needs PLT to be enabled.
+        // The user can use the command line flag to override it.
+        let needs_plt = self.target.target.options.needs_plt;
+
+        let dbg_opts = &self.opts.debugging_opts;
+
+        let relro_level = dbg_opts.relro_level
+            .unwrap_or(self.target.target.options.relro_level);
+
+        // Only enable this optimization by default if full relro is also enabled.
+        // In this case, lazy binding was already unavailable, so nothing is lost.
+        // This also ensures `-Wl,-z,now` is supported by the linker.
+        let full_relro = RelroLevel::Full == relro_level;
+
+        // If user didn't explicitly forced us to use / skip the PLT,
+        // then try to skip it where possible.
+        dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
+    }
 }
 
 pub fn build_session(
index 0abc26d6cfbc44fc452715a465c04348e42405bb..90ba103ca4ceb2540d0173dd0c7ae8016f6746e8 100644 (file)
@@ -137,6 +137,15 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
             target_cpu.as_c_str());
 }
 
+/// Sets the `NonLazyBind` LLVM attribute on a given function,
+/// assuming the codegen options allow skipping the PLT.
+pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) {
+    // Don't generate calls through PLT if it's not necessary
+    if !sess.needs_plt() {
+        Attribute::NonLazyBind.apply_llfn(Function, llfn);
+    }
+}
+
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
 pub fn from_fn_attrs(
index 208649c143afe72f95f3b9d85d72f266ace5024b..578018c7adc8a7fa0334394c28b3fd87f81c40fa 100644 (file)
@@ -208,6 +208,13 @@ pub unsafe fn create_module(
         llvm::LLVMRustSetModulePIELevel(llmod);
     }
 
+    // If skipping the PLT is enabled, we need to add some module metadata
+    // to ensure intrinsic calls don't use it.
+    if !sess.needs_plt() {
+        let avoid_plt = "RtLibUseGOT\0".as_ptr() as *const _;
+        llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
+    }
+
     llmod
 }
 
index 7141c9ece89d7180ea0c7f85f22e1fb29afbf8e1..26969e24f0883503d9178699bd9ba32377bc351b 100644 (file)
@@ -104,6 +104,8 @@ fn declare_raw_fn(
         attributes::unwind(llfn, false);
     }
 
+    attributes::non_lazy_bind(cx.sess(), llfn);
+
     llfn
 }
 
index 8485db4210cb0b691fb2cfcbe7b6987838bf6f96..c9f51efdc50957bbb01e080c50f5165d27ae2f2c 100644 (file)
@@ -122,6 +122,7 @@ pub enum Attribute {
     SanitizeThread  = 20,
     SanitizeAddress = 21,
     SanitizeMemory  = 22,
+    NonLazyBind     = 23,
 }
 
 /// LLVMIntPredicate
index 693cfea3c95f0d4b3cbabdaa44d944abfb407c83..ea62694f8be753c7c52e6b1c71fd8127b0af5282 100644 (file)
@@ -68,6 +68,7 @@ enum GroupedMoveError<'tcx> {
 enum BorrowedContentSource {
     Arc,
     Rc,
+    DerefRawPointer,
     Other,
 }
 
@@ -76,6 +77,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             BorrowedContentSource::Arc => write!(f, "an `Arc`"),
             BorrowedContentSource::Rc => write!(f, "an `Rc`"),
+            BorrowedContentSource::DerefRawPointer => write!(f, "dereference of raw pointer"),
             BorrowedContentSource::Other => write!(f, "borrowed content"),
         }
     }
@@ -279,6 +281,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
                             self.prefixes(&original_path, PrefixSet::All)
                             .any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
                                  .is_some());
+                        debug!("report: ty={:?}", ty);
                         match ty.sty {
                             ty::Array(..) | ty::Slice(..) =>
                                 self.infcx.tcx.cannot_move_out_of_interior_noncopy(
@@ -582,6 +585,18 @@ fn borrowed_content_source(&self, place: &Place<'tcx>) -> BorrowedContentSource
             }
         }
 
+        // If we didn't find an `Arc` or an `Rc`, then check specifically for
+        // a dereference of a place that has the type of a raw pointer.
+        // We can't use `place.ty(..).to_ty(..)` here as that strips away the raw pointer.
+        if let Place::Projection(box Projection {
+            base,
+            elem: ProjectionElem::Deref,
+        }) = place {
+            if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
+                return BorrowedContentSource::DerefRawPointer;
+            }
+        }
+
         BorrowedContentSource::Other
     }
 }
index 3f1e8ee55286b6bfd682894aa3bbbc5e29c9cb13..9c0f945326d148006c8f9cd54e7412d4ea9d92eb 100644 (file)
@@ -576,6 +576,9 @@ pub struct TargetOptions {
     /// the functions in the executable are not randomized and can be used
     /// during an exploit of a vulnerability in any code.
     pub position_independent_executables: bool,
+    /// Determines if the target always requires using the PLT for indirect
+    /// library calls or not. This controls the default value of the `-Z plt` flag.
+    pub needs_plt: bool,
     /// Either partial, full, or off. Full RELRO makes the dynamic linker
     /// resolve all symbols at startup and marks the GOT read-only before
     /// starting the program, preventing overwriting the GOT.
@@ -720,6 +723,7 @@ fn default() -> TargetOptions {
             has_rpath: false,
             no_default_libraries: true,
             position_independent_executables: false,
+            needs_plt: false,
             relro_level: RelroLevel::None,
             pre_link_objects_exe: Vec::new(),
             pre_link_objects_exe_crt: Vec::new(),
@@ -1009,6 +1013,7 @@ macro_rules! key {
         key!(has_rpath, bool);
         key!(no_default_libraries, bool);
         key!(position_independent_executables, bool);
+        key!(needs_plt, bool);
         try!(key!(relro_level, RelroLevel));
         key!(archive_format);
         key!(allow_asm, bool);
@@ -1217,6 +1222,7 @@ macro_rules! target_option_val {
         target_option_val!(has_rpath);
         target_option_val!(no_default_libraries);
         target_option_val!(position_independent_executables);
+        target_option_val!(needs_plt);
         target_option_val!(relro_level);
         target_option_val!(archive_format);
         target_option_val!(allow_asm);
index 72b5bd27c7dfe3b35f1069e0fdb87362bd87eb3f..fd61067ba5168cdd575c6ef826d11ef3e34b8ad0 100644 (file)
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
     base.stack_probes = true;
     base.has_elf_tls = false;
+    // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
+    // breaks code gen. See LLVM bug 36743
+    base.needs_plt = true;
 
     Ok(Target {
         llvm_target: "x86_64-unknown-linux-gnux32".to_string(),
index 5df4862290e3c0d990e980320e3d85570a5c1495..87b4527a2a73946629e53bd4ecf5e6b1f81d702b 100644 (file)
@@ -44,9 +44,21 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>,
     }
     write_header(class, &mut out).unwrap();
 
-    let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None),
-                                         sess.source_map());
+    let lexer = match lexer::StringReader::new_without_err(&sess, fm, None, "Output from rustc:") {
+        Ok(l) => l,
+        Err(_) => {
+            let first_line = src.lines().next().unwrap_or_else(|| "");
+            let mut err = sess.span_diagnostic
+                              .struct_warn(&format!("Invalid doc comment starting with: `{}`\n\
+                                                     (Ignoring this codeblock)",
+                                                    first_line));
+            err.emit();
+            return String::new();
+        }
+    };
+    let mut classifier = Classifier::new(lexer, sess.source_map());
     if classifier.write_source(&mut out).is_err() {
+        classifier.lexer.emit_fatal_errors();
         return format!("<pre>{}</pre>", src);
     }
 
@@ -162,11 +174,10 @@ fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
         match self.lexer.try_next_token() {
             Ok(tas) => Ok(tas),
             Err(_) => {
-                self.lexer.emit_fatal_errors();
-                self.lexer.sess.span_diagnostic
-                    .struct_warn("Backing out of syntax highlighting")
-                    .note("You probably did not intend to render this as a rust code-block")
-                    .emit();
+                let mut err = self.lexer.sess.span_diagnostic
+                                  .struct_warn("Backing out of syntax highlighting");
+                err.note("You probably did not intend to render this as a rust code-block");
+                err.emit();
                 Err(io::Error::new(io::ErrorKind::Other, ""))
             }
         }
index 8d54728a75f42ff3e93918feeda1bf9c596e00c3..3b432d05132095adc8206d36e022275c51ebb321 100644 (file)
@@ -908,11 +908,36 @@ mod prim_usize { }
 /// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
 /// references with longer lifetimes can be freely coerced into references with shorter ones.
 ///
+/// Reference equality by address, instead of comparing the values pointed to, is accomplished via
+/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while
+/// [`PartialEq`] compares values.
+///
+/// [`ptr::eq`]: ptr/fn.eq.html
+/// [`PartialEq`]: cmp/trait.PartialEq.html
+///
+/// ```
+/// use std::ptr;
+///
+/// let five = 5;
+/// let other_five = 5;
+/// let five_ref = &five;
+/// let same_five_ref = &five;
+/// let other_five_ref = &other_five;
+///
+/// assert!(five_ref == same_five_ref);
+/// assert!(five_ref == other_five_ref);
+///
+/// assert!(ptr::eq(five_ref, same_five_ref));
+/// assert!(!ptr::eq(five_ref, other_five_ref));
+/// ```
+///
 /// For more information on how to use references, see [the book's section on "References and
 /// Borrowing"][book-refs].
 ///
 /// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html
 ///
+/// # Trait implementations
+///
 /// The following traits are implemented for all `&T`, regardless of the type of its referent:
 ///
 /// * [`Copy`]
index aa47d5bf669bc0eb9f6015c78739094d9cb78951..a814c88ee78216babc4db391df90667d0efabcf7 100644 (file)
@@ -238,6 +238,19 @@ pub fn new(sess: &'a ParseSess,
         sr
     }
 
+    pub fn new_without_err(sess: &'a ParseSess,
+                           source_file: Lrc<syntax_pos::SourceFile>,
+                           override_span: Option<Span>,
+                           prepend_error_text: &str) -> Result<Self, ()> {
+        let mut sr = StringReader::new_raw(sess, source_file, override_span);
+        if sr.advance_token().is_err() {
+            eprintln!("{}", prepend_error_text);
+            sr.emit_fatal_errors();
+            return Err(());
+        }
+        Ok(sr)
+    }
+
     pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
         let begin = sess.source_map().lookup_byte_offset(span.lo());
         let end = sess.source_map().lookup_byte_offset(span.hi());
index f1ab1d4ddfa476d8fb0006583f4a3b7521eac4e6..2b1bf1c0290812c228099457d3b57df54c6f8cda 100644 (file)
@@ -178,6 +178,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
     return Attribute::SanitizeAddress;
   case SanitizeMemory:
     return Attribute::SanitizeMemory;
+  case NonLazyBind:
+    return Attribute::NonLazyBind;
   }
   report_fatal_error("bad AttributeKind");
 }
index 1070068b99845f86c72e6cc839a4e0d90f2da995..b6fa9a2fa950809b5b52dd42bea14f10e1e112fa 100644 (file)
@@ -97,6 +97,7 @@ enum LLVMRustAttribute {
   SanitizeThread = 20,
   SanitizeAddress = 21,
   SanitizeMemory = 22,
+  NonLazyBind = 23,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
index aab5f1bfb4f863825d67206ef1efd378688bbe0b..2cf8ce00bfb5d7d8366a67be1584d6f8f4c24c7a 100644 (file)
@@ -15,7 +15,7 @@
 #![crate_type = "lib"]
 #![feature(naked_functions)]
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define void @naked_empty()
 #[no_mangle]
 #[naked]
@@ -24,7 +24,7 @@ pub fn naked_empty() {
     // CHECK-NEXT: ret void
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 #[no_mangle]
 #[naked]
 // CHECK-NEXT: define void @naked_with_args(i{{[0-9]+}})
@@ -35,7 +35,7 @@ pub fn naked_with_args(a: isize) {
     // CHECK: ret void
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define i{{[0-9]+}} @naked_with_return()
 #[no_mangle]
 #[naked]
@@ -45,7 +45,7 @@ pub fn naked_with_return() -> isize {
     0
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
 #[no_mangle]
 #[naked]
@@ -57,7 +57,7 @@ pub fn naked_with_args_and_return(a: isize) -> isize {
     a
 }
 
-// CHECK: Function Attrs: naked uwtable
+// CHECK: Function Attrs: naked
 // CHECK-NEXT: define void @naked_recursive()
 #[no_mangle]
 #[naked]
diff --git a/src/test/codegen/no-plt.rs b/src/test/codegen/no-plt.rs
new file mode 100644 (file)
index 0000000..8f302e5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 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.
+
+// compile-flags: -C relocation-model=pic -Z plt=no
+
+#![crate_type = "lib"]
+
+// We need a function which is normally called through the PLT.
+extern "C" {
+    // CHECK: Function Attrs: nounwind nonlazybind
+    fn getenv(name: *const u8) -> *mut u8;
+}
+
+// Ensure the function gets referenced.
+pub unsafe fn call_through_plt() -> *mut u8 {
+    getenv(b"\0".as_ptr())
+}
+
+// Ensure intrinsics also skip the PLT
+// CHECK: !"RtLibUseGOT"
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
new file mode 100644 (file)
index 0000000..8c790d7
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 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.
+
+// compile-pass
+// compile-flags: --error-format=human
+
+/// ```
+/// \__________pkt->size___________/          \_result->size_/ \__pkt->size__/
+/// ```
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
new file mode 100644 (file)
index 0000000..b566133
--- /dev/null
@@ -0,0 +1,10 @@
+Output from rustc:
+error: unknown start of token: /
+ --> <stdin>:1:1
+  |
+1 | /__________pkt->size___________/          /_result->size_/ /__pkt->size__/
+  | ^
+
+warning: Invalid doc comment starting with: `/__________pkt->size___________/          /_result->size_/ /__pkt->size__/`
+(Ignoring this codeblock)
+
index f823a6f08d789485e47546b7e9fa34f4ec5f1f34..c3a2180b9f082e062f9afab0ede465a7511ac8f3 100644 (file)
@@ -1,10 +1,10 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of dereference of raw pointer
   --> $DIR/borrowck-move-from-unsafe-ptr.rs:13:13
    |
 LL |     let y = *x; //~ ERROR cannot move out of dereference of raw pointer
    |             ^^
    |             |
-   |             cannot move out of borrowed content
+   |             cannot move out of dereference of raw pointer
    |             help: consider removing the `*`: `x`
 
 error: aborting due to previous error
index 3a6784eed67dd35d3adaaadb90b1bcd59d38ebc7..362778b26c861911d2624046c87cd15c65d575ea 100644 (file)
@@ -16,22 +16,22 @@ LL |     let b = unsafe { *imm_ref() };
    |                      cannot move out of borrowed content
    |                      help: consider removing the `*`: `imm_ref()`
 
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of dereference of raw pointer
   --> $DIR/issue-20801.rs:42:22
    |
 LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^
    |                      |
-   |                      cannot move out of borrowed content
+   |                      cannot move out of dereference of raw pointer
    |                      help: consider removing the `*`: `mut_ptr()`
 
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of dereference of raw pointer
   --> $DIR/issue-20801.rs:45:22
    |
 LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^
    |                      |
-   |                      cannot move out of borrowed content
+   |                      cannot move out of dereference of raw pointer
    |                      help: consider removing the `*`: `const_ptr()`
 
 error: aborting due to 4 previous errors