about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-08-26 19:23:42 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-09-09 01:07:01 +0300
commitaadbcffb7c59718834c63c20ab7ce6276aef430c (patch)
tree00d8d2a2281a3beb2ed8cbaad6f4a5baf877a15e
parentea45edf0ee39fd7f25e0ba7258023c81b53b3a0d (diff)
downloadrust-aadbcffb7c59718834c63c20ab7ce6276aef430c.tar.gz
rust-aadbcffb7c59718834c63c20ab7ce6276aef430c.zip
Issue deprecation warnings for safe accesses to extern statics
-rw-r--r--src/doc/book/ffi.md2
-rw-r--r--src/libpanic_unwind/seh.rs4
-rw-r--r--src/librustc/lint/builtin.rs9
-rw-r--r--src/librustc/middle/effect.rs40
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/test/compile-fail/auxiliary/extern-statics.rs14
-rw-r--r--src/test/compile-fail/linkage2.rs2
-rw-r--r--src/test/compile-fail/linkage3.rs2
-rw-r--r--src/test/compile-fail/safe-extern-statics-mut.rs28
-rw-r--r--src/test/compile-fail/safe-extern-statics.rs32
-rw-r--r--src/test/run-pass/check-static-recursion-foreign.rs2
11 files changed, 123 insertions, 16 deletions
diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md
index 1dea15311ce..8709c3f4b7b 100644
--- a/src/doc/book/ffi.md
+++ b/src/doc/book/ffi.md
@@ -471,7 +471,7 @@ extern {
 
 fn main() {
     println!("You have readline version {} installed.",
-             rl_readline_version as i32);
+             unsafe { rl_readline_version as i32 });
 }
 ```
 
diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs
index dd6e92fe9ae..58964214930 100644
--- a/src/libpanic_unwind/seh.rs
+++ b/src/libpanic_unwind/seh.rs
@@ -232,13 +232,13 @@ extern "C" {
 // Again, I'm not entirely sure what this is describing, it just seems to work.
 #[cfg_attr(not(test), lang = "msvc_try_filter")]
 static mut TYPE_DESCRIPTOR1: _TypeDescriptor = _TypeDescriptor {
-    pVFTable: &TYPE_INFO_VTABLE as *const _ as *const _,
+    pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
     spare: 0 as *mut _,
     name: imp::NAME1,
 };
 
 static mut TYPE_DESCRIPTOR2: _TypeDescriptor = _TypeDescriptor {
-    pVFTable: &TYPE_INFO_VTABLE as *const _ as *const _,
+    pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
     spare: 0 as *mut _,
     name: imp::NAME2,
 };
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index ed94e5fe377..fa77c911b46 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -192,6 +192,12 @@ declare_lint! {
     "lifetimes or labels named `'_` were erroneously allowed"
 }
 
+declare_lint! {
+    pub SAFE_EXTERN_STATICS,
+    Warn,
+    "safe access to extern statics was erroneously allowed"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -228,7 +234,8 @@ impl LintPass for HardwiredLints {
             RENAMED_AND_REMOVED_LINTS,
             SUPER_OR_SELF_IN_GLOBAL_PATH,
             HR_LIFETIME_IN_ASSOC_TYPE,
-            LIFETIME_UNDERSCORE
+            LIFETIME_UNDERSCORE,
+            SAFE_EXTERN_STATICS
         )
     }
 }
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index a7af0b50b84..082db569e18 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -15,6 +15,7 @@ use self::RootUnsafeContext::*;
 use dep_graph::DepNode;
 use ty::{self, Ty, TyCtxt};
 use ty::MethodCall;
+use lint;
 
 use syntax::ast;
 use syntax_pos::Span;
@@ -57,16 +58,25 @@ struct EffectCheckVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
-    fn require_unsafe(&mut self, span: Span, description: &str) {
+    fn require_unsafe_ext(&mut self, node_id: ast::NodeId, span: Span,
+                          description: &str, is_lint: bool) {
         if self.unsafe_context.push_unsafe_count > 0 { return; }
         match self.unsafe_context.root {
             SafeContext => {
-                // Report an error.
-                struct_span_err!(
-                    self.tcx.sess, span, E0133,
-                    "{} requires unsafe function or block", description)
-                    .span_label(span, &description)
-                    .emit();
+                if is_lint {
+                    self.tcx.sess.add_lint(lint::builtin::SAFE_EXTERN_STATICS,
+                                           node_id,
+                                           span,
+                                           format!("{} requires unsafe function or \
+                                                    block (error E0133)", description));
+                } else {
+                    // Report an error.
+                    struct_span_err!(
+                        self.tcx.sess, span, E0133,
+                        "{} requires unsafe function or block", description)
+                        .span_label(span, &description)
+                        .emit();
+                }
             }
             UnsafeBlock(block_id) => {
                 // OK, but record this.
@@ -76,6 +86,10 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
             UnsafeFn => {}
         }
     }
+
+    fn require_unsafe(&mut self, span: Span, description: &str) {
+        self.require_unsafe_ext(ast::DUMMY_NODE_ID, span, description, false)
+    }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
@@ -173,8 +187,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
             hir::ExprPath(..) => {
-                if let Def::Static(_, true) = self.tcx.expect_def(expr.id) {
-                    self.require_unsafe(expr.span, "use of mutable static");
+                if let Def::Static(def_id, mutbl) = self.tcx.expect_def(expr.id) {
+                    if mutbl {
+                        self.require_unsafe(expr.span, "use of mutable static");
+                    } else if match self.tcx.map.get_if_local(def_id) {
+                        Some(hir::map::NodeForeignItem(..)) => true,
+                        Some(..) => false,
+                        None => self.tcx.sess.cstore.is_foreign_item(def_id),
+                    } {
+                        self.require_unsafe_ext(expr.id, expr.span, "use of extern static", true);
+                    }
                 }
             }
             hir::ExprField(ref base_expr, field) => {
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index b9817cc6ff4..bc2979c806f 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -201,6 +201,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             id: LintId::of(LIFETIME_UNDERSCORE),
             reference: "RFC 1177 <https://github.com/rust-lang/rfcs/pull/1177>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(SAFE_EXTERN_STATICS),
+            reference: "issue 36247 <https://github.com/rust-lang/rust/issues/35112>",
+        },
         ]);
 
     // Register renamed and removed lints
diff --git a/src/test/compile-fail/auxiliary/extern-statics.rs b/src/test/compile-fail/auxiliary/extern-statics.rs
new file mode 100644
index 00000000000..07f70b177b3
--- /dev/null
+++ b/src/test/compile-fail/auxiliary/extern-statics.rs
@@ -0,0 +1,14 @@
+// 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 {
+    pub static XA: u8;
+    pub static mut XB: u8;
+}
diff --git a/src/test/compile-fail/linkage2.rs b/src/test/compile-fail/linkage2.rs
index 2a127d937ea..afae4a451d6 100644
--- a/src/test/compile-fail/linkage2.rs
+++ b/src/test/compile-fail/linkage2.rs
@@ -16,5 +16,5 @@ extern {
 }
 
 fn main() {
-    println!("{}", foo);
+    println!("{}", unsafe { foo });
 }
diff --git a/src/test/compile-fail/linkage3.rs b/src/test/compile-fail/linkage3.rs
index 8343f718902..c222989ed66 100644
--- a/src/test/compile-fail/linkage3.rs
+++ b/src/test/compile-fail/linkage3.rs
@@ -16,5 +16,5 @@ extern {
 }
 
 fn main() {
-    println!("{:?}", foo);
+    println!("{:?}", unsafe { foo });
 }
diff --git a/src/test/compile-fail/safe-extern-statics-mut.rs b/src/test/compile-fail/safe-extern-statics-mut.rs
new file mode 100644
index 00000000000..b5f3b4535df
--- /dev/null
+++ b/src/test/compile-fail/safe-extern-statics-mut.rs
@@ -0,0 +1,28 @@
+// 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.
+
+// aux-build:extern-statics.rs
+
+#![allow(unused)]
+#![deny(safe_extern_statics)]
+
+extern crate extern_statics;
+use extern_statics::*;
+
+extern {
+    static mut B: u8;
+}
+
+fn main() {
+    let b = B; //~ ERROR use of mutable static requires unsafe function or block
+    let rb = &B; //~ ERROR use of mutable static requires unsafe function or block
+    let xb = XB; //~ ERROR use of mutable static requires unsafe function or block
+    let xrb = &XB; //~ ERROR use of mutable static requires unsafe function or block
+}
diff --git a/src/test/compile-fail/safe-extern-statics.rs b/src/test/compile-fail/safe-extern-statics.rs
new file mode 100644
index 00000000000..7e96897ee88
--- /dev/null
+++ b/src/test/compile-fail/safe-extern-statics.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// aux-build:extern-statics.rs
+
+#![allow(unused)]
+#![deny(safe_extern_statics)]
+
+extern crate extern_statics;
+use extern_statics::*;
+
+extern {
+    static A: u8;
+}
+
+fn main() {
+    let a = A; //~ ERROR use of extern static requires unsafe function or block
+               //~^ WARN this was previously accepted by the compiler
+    let ra = &A; //~ ERROR use of extern static requires unsafe function or block
+                 //~^ WARN this was previously accepted by the compiler
+    let xa = XA; //~ ERROR use of extern static requires unsafe function or block
+                 //~^ WARN this was previously accepted by the compiler
+    let xra = &XA; //~ ERROR use of extern static requires unsafe function or block
+                   //~^ WARN this was previously accepted by the compiler
+}
diff --git a/src/test/run-pass/check-static-recursion-foreign.rs b/src/test/run-pass/check-static-recursion-foreign.rs
index 554853ade5b..8e718f328ff 100644
--- a/src/test/run-pass/check-static-recursion-foreign.rs
+++ b/src/test/run-pass/check-static-recursion-foreign.rs
@@ -27,6 +27,6 @@ extern "C" {
     static test_static: c_int;
 }
 
-static B: &'static c_int = &test_static;
+static B: &'static c_int = unsafe { &test_static };
 
 pub fn main() {}