]> git.lizzy.rs Git - rust.git/commitdiff
Check gated attributes before and after macro expansion
authorKeegan McAllister <kmcallister@mozilla.com>
Fri, 6 Mar 2015 23:10:20 +0000 (15:10 -0800)
committerKeegan McAllister <kmcallister@mozilla.com>
Sat, 7 Mar 2015 01:15:19 +0000 (17:15 -0800)
This is important because attributes can affect expansion.

12 files changed:
src/libsyntax/feature_gate.rs
src/test/compile-fail/deprecated-phase.rs
src/test/compile-fail/feature-gate-intrinsics-and-lang-items.rs [deleted file]
src/test/compile-fail/feature-gate-intrinsics.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-lang-items.rs [new file with mode: 0644]
src/test/compile-fail/linkage1.rs
src/test/compile-fail/malformed-plugin-1.rs
src/test/compile-fail/malformed-plugin-2.rs
src/test/compile-fail/malformed-plugin-3.rs
src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs
src/test/compile-fail/reserved-attr-on-macro.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/macro-crate.rs

index c6a94b26a0a51fd32ba3b52ac6ca12c68c2140bd..eff86757fd0b24d482d1a834ce343bffa7195fbb 100644 (file)
@@ -196,6 +196,7 @@ enum Status {
     ("no_mangle", Normal),
     ("no_link", Normal),
     ("derive", Normal),
+    ("deriving", Normal), // deprecation err in expansion
     ("should_fail", Normal),
     ("should_panic", Normal),
     ("ignore", Normal),
@@ -235,6 +236,9 @@ enum Status {
                                    "the `#[rustc_move_fragments]` attribute \
                                     is an experimental feature")),
 
+    ("allow_internal_unstable", Gated("allow_internal_unstable",
+                                      EXPLAIN_ALLOW_INTERNAL_UNSTABLE)),
+
     // FIXME: #14408 whitelist docs since rustdoc looks at them
     ("doc", Whitelisted),
 
@@ -369,6 +373,33 @@ fn warn_feature(&self, feature: &str, span: Span, explain: &str) {
     fn has_feature(&self, feature: &str) -> bool {
         self.features.iter().any(|&n| n == feature)
     }
+
+    fn check_attribute(&self, attr: &ast::Attribute) {
+        debug!("check_attribute(attr = {:?})", attr);
+        let name = &*attr.name();
+        for &(n, ty) in KNOWN_ATTRIBUTES {
+            if n == name {
+                if let Gated(gate, desc) = ty {
+                    self.gate_feature(gate, attr.span, desc);
+                }
+                debug!("check_attribute: {:?} is known, {:?}", name, ty);
+                return;
+            }
+        }
+        if name.starts_with("rustc_") {
+            self.gate_feature("rustc_attrs", attr.span,
+                              "unless otherwise specified, attributes \
+                               with the prefix `rustc_` \
+                               are reserved for internal compiler diagnostics");
+        } else {
+            self.gate_feature("custom_attribute", attr.span,
+                       format!("The attribute `{}` is currently \
+                                unknown to the the compiler and \
+                                may have meaning \
+                                added to it in the future",
+                                name).as_slice());
+        }
+    }
 }
 
 pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
@@ -436,10 +467,7 @@ fn visit_mac(&mut self, mac: &ast::Mac) {
     }
 
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
-        if attr.name() == "allow_internal_unstable" {
-            self.context.gate_feature("allow_internal_unstable", attr.span,
-                                      EXPLAIN_ALLOW_INTERNAL_UNSTABLE)
-        }
+        self.context.check_attribute(attr);
     }
 }
 
@@ -456,6 +484,12 @@ fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
 }
 
 impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
+    fn visit_attribute(&mut self, attr: &ast::Attribute) {
+        if !self.context.cm.span_allows_unstable(attr.span) {
+            self.context.check_attribute(attr);
+        }
+    }
+
     fn visit_name(&mut self, sp: Span, name: ast::Name) {
         if !token::get_name(name).is_ascii() {
             self.gate_feature("non_ascii_idents", sp,
@@ -556,12 +590,6 @@ fn visit_item(&mut self, i: &ast::Item) {
     }
 
     fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
-        if attr::contains_name(&i.attrs, "linkage") {
-            self.gate_feature("linkage", i.span,
-                              "the `linkage` attribute is experimental \
-                               and not portable across platforms")
-        }
-
         let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs,
                                                                      "link_name") {
             Some(val) => val.starts_with("llvm."),
@@ -636,33 +664,6 @@ fn visit_expr(&mut self, e: &ast::Expr) {
         visit::walk_expr(self, e);
     }
 
-    fn visit_attribute(&mut self, attr: &ast::Attribute) {
-        debug!("visit_attribute(attr = {:?})", attr);
-        let name = &*attr.name();
-        for &(n, ty) in KNOWN_ATTRIBUTES {
-            if n == name {
-                if let Gated(gate, desc) = ty {
-                    self.gate_feature(gate, attr.span, desc);
-                }
-                debug!("visit_attribute: {:?} is known, {:?}", name, ty);
-                return;
-            }
-        }
-        if name.starts_with("rustc_") {
-            self.gate_feature("rustc_attrs", attr.span,
-                              "unless otherwise specified, attributes \
-                               with the prefix `rustc_` \
-                               are reserved for internal compiler diagnostics");
-        } else {
-            self.gate_feature("custom_attribute", attr.span,
-                       format!("The attribute `{}` is currently \
-                                unknown to the the compiler and \
-                                may have meaning \
-                                added to it in the future",
-                                name).as_slice());
-        }
-    }
-
     fn visit_pat(&mut self, pattern: &ast::Pat) {
         match pattern.node {
             ast::PatVec(_, Some(_), ref last) if !last.is_empty() => {
index 1401494d987a28af300ad026f11f02a1c5b7afa8..22fc4a94cd25ab87254b9d754aeadc724ae59f61 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(custom_attribute)]
+
 #[phase(blah)]
 //~^ ERROR #[phase] is deprecated
 extern crate foo;
diff --git a/src/test/compile-fail/feature-gate-intrinsics-and-lang-items.rs b/src/test/compile-fail/feature-gate-intrinsics-and-lang-items.rs
deleted file mode 100644 (file)
index 986d52b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 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.
-
-#[lang="foo"]   //~ ERROR language items are subject to change
-trait Foo {}
-
-extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
-    fn bar();
-}
-
-extern "rust-intrinsic" fn baz() {  //~ ERROR intrinsics are subject to change
-}
-
-fn main() {
-}
-
diff --git a/src/test/compile-fail/feature-gate-intrinsics.rs b/src/test/compile-fail/feature-gate-intrinsics.rs
new file mode 100644 (file)
index 0000000..a4c09b2
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2014 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 "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
+    fn bar();
+}
+
+extern "rust-intrinsic" fn baz() {  //~ ERROR intrinsics are subject to change
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/feature-gate-lang-items.rs b/src/test/compile-fail/feature-gate-lang-items.rs
new file mode 100644 (file)
index 0000000..0435ff4
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 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.
+
+#[lang="foo"]   //~ ERROR language items are subject to change
+trait Foo {}
+
+fn main() {
+}
index 35f93c13fb5e23792d071df8a27293f168a4fb5d..555cc2b9a7aad95c8c43b10932550e08154b65c8 100644 (file)
@@ -11,5 +11,4 @@
 extern {
     #[linkage = "extern_weak"] static foo: isize;
     //~^ ERROR: the `linkage` attribute is experimental and not portable
-    //~^^ ERROR: the `linkage` attribute is experimental and not portable
 }
index 254a797ef1cd0a54462062b634db348fcf9d0e2b..214a5e5e3eb115c4878422d3d978bd5b803059ea 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(plugin)]
 #![plugin] //~ ERROR malformed plugin attribute
 
 fn main() {}
index 884087b7bc534204f97f9c0513fc1102077962f6..1b112608beeb2003fc00091222574b4a2c55f305 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(plugin)]
 #![plugin="bleh"] //~ ERROR malformed plugin attribute
 
 fn main() {}
index 4885bb901df681fd68abd6daeb35db9aea4b5642..0c948831de217a6ce30c9af993fe7b7dc6c19820 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(plugin)]
 #![plugin(foo="bleh")] //~ ERROR malformed plugin attribute
 
 fn main() {}
index ccda5cbdceba6b2e156dcf775ba51a2641026a46..efa352e386d4d679806231a779fe891bd5610990 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(plugin)]
+
 #[plugin]  //~ ERROR #[plugin] on `extern crate` is deprecated
 //~^ HELP use a crate attribute instead, i.e. #![plugin(std)]
 extern crate std;
diff --git a/src/test/compile-fail/reserved-attr-on-macro.rs b/src/test/compile-fail/reserved-attr-on-macro.rs
new file mode 100644 (file)
index 0000000..db8f82a
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+#[rustc_attribute_should_be_reserved] //~ ERROR attributes with the prefix `rustc_` are reserved
+macro_rules! foo {
+    () => (());
+}
+
+fn main() {
+    foo!();
+}
index 58ccd79b7121dbe9afe8201db76283556de8a170..7a2846c31b66331815ce76613619a2a83386a51a 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
-#![feature(plugin)]
+#![feature(plugin, custom_attribute)]
 #![plugin(macro_crate_test)]
 
 #[macro_use] #[no_link]