about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorHavvy (Ryan Scheel) <ryan.havvy@gmail.com>2018-10-04 04:55:47 -0700
committerHavvy (Ryan Scheel) <ryan.havvy@gmail.com>2018-10-07 02:08:24 -0700
commit35e6c65628a537ad92a38b562a6f9e2de1887b5b (patch)
tree6ed810ae66c532fd72490e98594fb39c09f2445a /src/libsyntax
parent1a867dc346a0b9ea5abd8a8504f1908f42ff2dd2 (diff)
downloadrust-35e6c65628a537ad92a38b562a6f9e2de1887b5b.tar.gz
rust-35e6c65628a537ad92a38b562a6f9e2de1887b5b.zip
cfg_attr_multi: Feature gate
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/config.rs36
-rw-r--r--src/libsyntax/feature_gate.rs3
2 files changed, 38 insertions, 1 deletions
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 7a85f628536..e611eb86dc1 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -9,7 +9,14 @@
 // except according to those terms.
 
 use attr::HasAttrs;
-use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue};
+use feature_gate::{
+    feature_err,
+    EXPLAIN_STMT_ATTR_SYNTAX,
+    Features,
+    get_features,
+    GateIssue,
+    emit_feature_err,
+};
 use {fold, attr};
 use ast;
 use source_map::Spanned;
@@ -97,6 +104,13 @@ impl<'a> StripUnconfigured<'a> {
             return vec![attr];
         }
 
+        let gate_cfg_attr_multi = if let Some(ref features) = self.features {
+            !features.cfg_attr_multi
+        } else {
+            false
+        };
+        let cfg_attr_span = attr.span;
+
         let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| {
             parser.expect(&token::OpenDelim(token::Paren))?;
 
@@ -123,6 +137,26 @@ impl<'a> StripUnconfigured<'a> {
             }
         };
 
+        // Check feature gate and lint on zero attributes in source. Even if the feature is gated,
+        // we still compute as if it wasn't, since the emitted error will stop compilation futher
+        // along the compilation.
+        match (expanded_attrs.len(), gate_cfg_attr_multi) {
+            (0, false) => {
+                // FIXME: Emit unused attribute lint here.
+            },
+            (1, _) => {},
+            (_, true) => {
+                emit_feature_err(
+                    self.sess,
+                    "cfg_attr_multi",
+                    cfg_attr_span,
+                    GateIssue::Language,
+                    "cfg_attr with zero or more than one attributes is experimental",
+                );
+            },
+            (_, false) => {}
+        }
+
         if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
             // We call `process_cfg_attr` recursively in case there's a
             // `cfg_attr` inside of another `cfg_attr`. E.g.
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index adbe2f9d439..7707bbaa8b0 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -515,6 +515,9 @@ declare_features! (
 
     // Allows `impl Trait` in bindings (`let`, `const`, `static`)
     (active, impl_trait_in_bindings, "1.30.0", Some(34511), None),
+
+    // #[cfg_attr(predicate, multiple, attributes, here)]
+    (active, cfg_attr_multi, "1.31.0", Some(555666), None),
 );
 
 declare_features! (