about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/config.rs6
-rw-r--r--src/libsyntax/diagnostic_list.rs15
-rw-r--r--src/libsyntax/feature_gate.rs11
-rw-r--r--src/libsyntax/parse/parser.rs45
4 files changed, 53 insertions, 24 deletions
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 4e4432a3f33..2abb7e407eb 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -24,8 +24,8 @@ pub struct StripUnconfigured<'a> {
 }
 
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
-                -> (ast::Crate, Features) {
+pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition,
+                allow_features: &Option<Vec<String>>) -> (ast::Crate, Features) {
     let features;
     {
         let mut strip_unconfigured = StripUnconfigured {
@@ -43,7 +43,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
             return (krate, Features::new());
         }
 
-        features = get_features(&sess.span_diagnostic, &krate.attrs, edition);
+        features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
 
         // Avoid reconfiguring malformed `cfg_attr`s
         if err_count == sess.span_diagnostic.err_count() {
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 2c367f1f402..ac24475cab8 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -378,6 +378,21 @@ Erroneous code example:
 
 "##,
 
+E0725: r##"
+A feature attribute named a feature that was disallowed in the compiler
+command line flags.
+
+Erroneous code example:
+
+```ignore (can't specify compiler flags from doctests)
+#![feature(never_type)] // error: the feature `never_type` is not in
+                        // the list of allowed features
+```
+
+Delete the offending feature attribute, or add it to the list of allowed
+features in the `-Z allow_features` flag.
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index b2982629fe6..280b17da0be 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -2008,7 +2008,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
-                    crate_edition: Edition) -> Features {
+                    crate_edition: Edition, allow_features: &Option<Vec<String>>) -> Features {
     fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
         let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
         if let Some(reason) = reason {
@@ -2127,6 +2127,15 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
             }
 
             if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
+                if let Some(allowed) = allow_features.as_ref() {
+                    if allowed.iter().find(|f| *f == name.as_str()).is_none() {
+                        span_err!(span_handler, mi.span, E0725,
+                                  "the feature `{}` is not in the list of allowed features",
+                                  name);
+                        continue;
+                    }
+                }
+
                 set(&mut features, mi.span);
                 features.declared_lang_features.push((name, mi.span, None));
                 continue
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fe31311094b..22af7d47fd0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5116,12 +5116,8 @@ impl<'a> Parser<'a> {
 
                 let ident = self.parse_ident()?;
                 let (delim, tokens) = self.expect_delimited_token_tree()?;
-                if delim != MacDelimiter::Brace {
-                    if !self.eat(&token::Semi) {
-                        let msg = "macros that expand to items must either \
-                                   be surrounded with braces or followed by a semicolon";
-                        self.span_err(self.prev_span, msg);
-                    }
+                if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+                    self.report_invalid_macro_expansion_item();
                 }
 
                 (ident, ast::MacroDef { tokens: tokens, legacy: true })
@@ -5264,13 +5260,8 @@ impl<'a> Parser<'a> {
                 // if it has a special ident, it's definitely an item
                 //
                 // Require a semicolon or braces.
-                if style != MacStmtStyle::Braces {
-                    if !self.eat(&token::Semi) {
-                        self.span_err(self.prev_span,
-                                      "macros that expand to items must \
-                                       either be surrounded with braces or \
-                                       followed by a semicolon");
-                    }
+                if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
+                    self.report_invalid_macro_expansion_item();
                 }
                 let span = lo.to(hi);
                 Stmt {
@@ -8360,13 +8351,8 @@ impl<'a> Parser<'a> {
             };
             // eat a matched-delimiter token tree:
             let (delim, tts) = self.expect_delimited_token_tree()?;
-            if delim != MacDelimiter::Brace {
-                if !self.eat(&token::Semi) {
-                    self.span_err(self.prev_span,
-                                  "macros that expand to items must either \
-                                   be surrounded with braces or followed by \
-                                   a semicolon");
-                }
+            if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+                self.report_invalid_macro_expansion_item();
             }
 
             let hi = self.prev_span;
@@ -8597,6 +8583,25 @@ impl<'a> Parser<'a> {
             }
         }
     }
+
+    fn report_invalid_macro_expansion_item(&self) {
+        self.struct_span_err(
+            self.prev_span,
+            "macros that expand to items must be delimited with braces or followed by a semicolon",
+        ).multipart_suggestion(
+            "change the delimiters to curly braces",
+            vec![
+                (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")),
+                (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()),
+            ],
+            Applicability::MaybeIncorrect,
+        ).span_suggestion(
+            self.sess.source_map.next_point(self.prev_span),
+            "add a semicolon",
+            ';'.to_string(),
+            Applicability::MaybeIncorrect,
+        ).emit();
+    }
 }
 
 pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {