about summary refs log tree commit diff
path: root/compiler/rustc_builtin_macros/src/cfg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros/src/cfg.rs')
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
new file mode 100644
index 00000000000..4c00162b556
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -0,0 +1,54 @@
+//! The compiler code necessary to support the cfg! extension, which expands to
+//! a literal `true` or `false` based on whether the given cfg matches the
+//! current compilation environment.
+
+use rustc_ast as ast;
+use rustc_ast::token;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_attr as attr;
+use rustc_errors::DiagnosticBuilder;
+use rustc_expand::base::{self, *};
+use rustc_span::Span;
+
+pub fn expand_cfg(
+    cx: &mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> Box<dyn base::MacResult + 'static> {
+    let sp = cx.with_def_site_ctxt(sp);
+
+    match parse_cfg(cx, sp, tts) {
+        Ok(cfg) => {
+            let matches_cfg = attr::cfg_matches(&cfg, &cx.sess.parse_sess, cx.ecfg.features);
+            MacEager::expr(cx.expr_bool(sp, matches_cfg))
+        }
+        Err(mut err) => {
+            err.emit();
+            DummyResult::any(sp)
+        }
+    }
+}
+
+fn parse_cfg<'a>(
+    cx: &mut ExtCtxt<'a>,
+    sp: Span,
+    tts: TokenStream,
+) -> Result<ast::MetaItem, DiagnosticBuilder<'a>> {
+    let mut p = cx.new_parser_from_tts(tts);
+
+    if p.token == token::Eof {
+        let mut err = cx.struct_span_err(sp, "macro requires a cfg-pattern as an argument");
+        err.span_label(sp, "cfg-pattern required");
+        return Err(err);
+    }
+
+    let cfg = p.parse_meta_item()?;
+
+    let _ = p.eat(&token::Comma);
+
+    if !p.eat(&token::Eof) {
+        return Err(cx.struct_span_err(sp, "expected 1 cfg-pattern"));
+    }
+
+    Ok(cfg)
+}