auto merge of #17527 : sfackler/rust/cfg-syntax, r=alexcrichton
We'll need a snapshot before we can convert the codebase over and turn on the deprecation warnings. cc #17490 This is sitting on top of #17506
This commit is contained in:
commit
7eb9337dac
@ -226,7 +226,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
// baz! should not use this definition unless foo is enabled.
|
||||
|
||||
krate = time(time_passes, "configuration 1", krate, |krate|
|
||||
syntax::config::strip_unconfigured_items(krate));
|
||||
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
|
||||
|
||||
let mut addl_plugins = Some(addl_plugins);
|
||||
let Plugins { macros, registrars }
|
||||
@ -307,7 +307,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
|
||||
// strip again, in case expansion added anything with a #[cfg].
|
||||
krate = time(time_passes, "configuration 2", krate, |krate|
|
||||
syntax::config::strip_unconfigured_items(krate));
|
||||
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
|
||||
|
||||
krate = time(time_passes, "maybe building test harness", krate, |krate|
|
||||
syntax::test::modify_for_testing(&sess.parse_sess,
|
||||
|
@ -307,6 +307,32 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::MetaItem) -> bool {
|
||||
match cfg.node {
|
||||
ast::MetaList(ref pred, ref mis) if pred.get() == "any" =>
|
||||
mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi)),
|
||||
ast::MetaList(ref pred, ref mis) if pred.get() == "all" =>
|
||||
mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi)),
|
||||
ast::MetaList(ref pred, ref mis) if pred.get() == "not" => {
|
||||
// NOTE: turn on after snapshot
|
||||
/*
|
||||
if mis.len() != 1 {
|
||||
diagnostic.span_warn(cfg.span, "the use of multiple cfgs in the same `not` \
|
||||
statement is deprecated. Change `not(a, b)` to \
|
||||
`not(all(a, b))`.");
|
||||
}
|
||||
*/
|
||||
!mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi))
|
||||
}
|
||||
ast::MetaList(ref pred, _) => {
|
||||
diagnostic.span_err(cfg.span, format!("invalid predicate `{}`", pred).as_slice());
|
||||
false
|
||||
},
|
||||
ast::MetaWord(_) | ast::MetaNameValue(..) => contains(cfgs, cfg),
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests if any `cfg(...)` meta items in `metas` match `cfg`. e.g.
|
||||
///
|
||||
/// test_cfg(`[foo="a", bar]`, `[cfg(foo), cfg(bar)]`) == true
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use attr::AttrMetaMethods;
|
||||
use diagnostic::SpanHandler;
|
||||
use fold::Folder;
|
||||
use {ast, fold, attr};
|
||||
use codemap::Spanned;
|
||||
@ -21,9 +23,9 @@ struct Context<'a> {
|
||||
|
||||
// Support conditional compilation by transforming the AST, stripping out
|
||||
// any items that do not belong in the current configuration
|
||||
pub fn strip_unconfigured_items(krate: ast::Crate) -> ast::Crate {
|
||||
pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
|
||||
let config = krate.config.clone();
|
||||
strip_items(krate, |attrs| in_cfg(config.as_slice(), attrs))
|
||||
strip_items(krate, |attrs| in_cfg(diagnostic, config.as_slice(), attrs))
|
||||
}
|
||||
|
||||
impl<'a> fold::Folder for Context<'a> {
|
||||
@ -249,7 +251,34 @@ fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
|
||||
|
||||
// Determine if an item should be translated in the current crate
|
||||
// configuration based on the item's attributes
|
||||
fn in_cfg(cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
|
||||
attr::test_cfg(cfg, attrs.iter())
|
||||
fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
|
||||
let mut in_cfg = false;
|
||||
let mut seen_cfg = false;
|
||||
for attr in attrs.iter() {
|
||||
let mis = match attr.node.value.node {
|
||||
ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis,
|
||||
_ => continue
|
||||
};
|
||||
|
||||
// NOTE: turn on after snapshot
|
||||
/*
|
||||
if mis.len() != 1 {
|
||||
diagnostic.span_warn(attr.span, "The use of multiple cfgs in the top level of \
|
||||
`#[cfg(..)]` is deprecated. Change `#[cfg(a, b)]` to \
|
||||
`#[cfg(all(a, b))]`.");
|
||||
}
|
||||
|
||||
if seen_cfg {
|
||||
diagnostic.span_warn(attr.span, "The semantics of multiple `#[cfg(..)]` attributes on \
|
||||
same item are changing from the union of the cfgs to \
|
||||
the intersection of the cfgs. Change `#[cfg(a)] \
|
||||
#[cfg(b)]` to `#[cfg(any(a, b))]`.");
|
||||
}
|
||||
*/
|
||||
|
||||
seen_cfg = true;
|
||||
in_cfg |= mis.iter().all(|mi| attr::cfg_matches(diagnostic, cfg, &**mi));
|
||||
}
|
||||
in_cfg | !seen_cfg
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ use ext::build::AstBuilder;
|
||||
use attr;
|
||||
use attr::*;
|
||||
use parse::attr::ParserAttr;
|
||||
use parse::token::InternedString;
|
||||
use parse::token;
|
||||
|
||||
|
||||
@ -39,11 +38,17 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt,
|
||||
p.expect(&token::COMMA);
|
||||
}
|
||||
|
||||
// test_cfg searches for meta items looking like `cfg(foo, ...)`
|
||||
let in_cfg = Some(cx.meta_list(sp, InternedString::new("cfg"), cfgs));
|
||||
// NOTE: turn on after snapshot
|
||||
/*
|
||||
if cfgs.len() != 1 {
|
||||
cx.span_warn(sp, "The use of multiple cfgs at the top level of `cfg!` \
|
||||
is deprecated. Change `cfg!(a, b)` to \
|
||||
`cfg!(all(a, b))`.");
|
||||
}
|
||||
*/
|
||||
|
||||
let matches_cfg = attr::test_cfg(cx.cfg().as_slice(),
|
||||
in_cfg.iter());
|
||||
let e = cx.expr_bool(sp, matches_cfg);
|
||||
MacExpr::new(e)
|
||||
let matches_cfg = cfgs.iter().all(|cfg| attr::cfg_matches(&cx.parse_sess.span_diagnostic,
|
||||
cx.cfg.as_slice(), &**cfg));
|
||||
|
||||
MacExpr::new(cx.expr_bool(sp, matches_cfg))
|
||||
}
|
||||
|
@ -25,33 +25,10 @@ pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P<ast::Item>)
|
||||
};
|
||||
|
||||
let mut out = (*it).clone();
|
||||
if cfg_matches(cx, &**cfg) {
|
||||
if attr::cfg_matches(&cx.parse_sess.span_diagnostic, cx.cfg.as_slice(), &**cfg) {
|
||||
out.attrs.push(cx.attribute(attr.span, attr.clone()));
|
||||
}
|
||||
|
||||
P(out)
|
||||
}
|
||||
|
||||
fn cfg_matches(cx: &mut ExtCtxt, cfg: &ast::MetaItem) -> bool {
|
||||
match cfg.node {
|
||||
ast::MetaList(ref pred, ref mis) if pred.get() == "any" =>
|
||||
mis.iter().any(|mi| cfg_matches(cx, &**mi)),
|
||||
ast::MetaList(ref pred, ref mis) if pred.get() == "all" =>
|
||||
mis.iter().all(|mi| cfg_matches(cx, &**mi)),
|
||||
ast::MetaList(ref pred, ref mis) if pred.get() == "not" => {
|
||||
if mis.len() != 1 {
|
||||
cx.span_err(cfg.span, format!("expected 1 value, got {}",
|
||||
mis.len()).as_slice());
|
||||
return false;
|
||||
}
|
||||
!cfg_matches(cx, &*mis[0])
|
||||
}
|
||||
ast::MetaList(ref pred, _) => {
|
||||
cx.span_err(cfg.span,
|
||||
format!("invalid predicate `{}`", pred).as_slice());
|
||||
false
|
||||
},
|
||||
ast::MetaWord(_) | ast::MetaNameValue(..) =>
|
||||
attr::contains(cx.cfg.as_slice(), cfg),
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,9 @@
|
||||
|
||||
fn foo(x: int) { println!("{}", x); }
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
target_arch = "arm"))]
|
||||
pub fn main() {
|
||||
let x: int;
|
||||
let y: int;
|
||||
@ -27,5 +26,5 @@ pub fn main() {
|
||||
foo(y);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))]
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))]
|
||||
pub fn main() {}
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "x86_64"))]
|
||||
pub fn main() {
|
||||
// assignment not dead
|
||||
let mut x: int = 0;
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
fn foo(x: int) { println!("{}", x); }
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
target_arch = "arm"))]
|
||||
pub fn main() {
|
||||
let x: int;
|
||||
x = 1; //~ NOTE prior assignment occurs here
|
||||
@ -25,5 +25,5 @@ pub fn main() {
|
||||
foo(x);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))]
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))]
|
||||
pub fn main() {}
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
fn foo(x: int) { println!("{}", x); }
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
target_arch = "arm"))]
|
||||
pub fn main() {
|
||||
let x: int;
|
||||
unsafe {
|
||||
@ -23,5 +23,5 @@ pub fn main() {
|
||||
foo(x);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))]
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))]
|
||||
pub fn main() {}
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
fn foo(x: int) { println!("{}", x); }
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
target_arch = "arm"))]
|
||||
pub fn main() {
|
||||
let x: int;
|
||||
unsafe {
|
||||
@ -23,5 +23,5 @@ pub fn main() {
|
||||
foo(x);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))]
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))]
|
||||
pub fn main() {}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// compile-flags: --cfg foo
|
||||
|
||||
#[cfg(foo, bar)] // foo AND bar
|
||||
#[cfg(all(foo, bar))] // foo AND bar
|
||||
fn foo() {}
|
||||
|
||||
fn main() {
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
#[cfg = r#"just parse this"#]
|
||||
#[cfg(foo = r#"just parse this"#)]
|
||||
extern crate r##"blah"## as blah;
|
||||
|
||||
fn main() { unsafe { asm!(r###"blah"###); } }
|
||||
|
@ -8,27 +8,27 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: --cfg foo --cfg bar(baz) --cfg qux="foo"
|
||||
// compile-flags: --cfg foo --cfg qux="foo"
|
||||
|
||||
pub fn main() {
|
||||
// check
|
||||
if ! cfg!(foo) { fail!() }
|
||||
if cfg!(not(foo)) { fail!() }
|
||||
|
||||
if ! cfg!(bar(baz)) { fail!() }
|
||||
if cfg!(not(bar(baz))) { fail!() }
|
||||
|
||||
if ! cfg!(qux="foo") { fail!() }
|
||||
if cfg!(not(qux="foo")) { fail!() }
|
||||
|
||||
if ! cfg!(foo, bar(baz), qux="foo") { fail!() }
|
||||
if cfg!(not(foo, bar(baz), qux="foo")) { fail!() }
|
||||
if ! cfg!(foo, qux="foo") { fail!() }
|
||||
if cfg!(not(foo, qux="foo")) { fail!() }
|
||||
if cfg!(all(not(foo, qux="foo"))) { fail!() }
|
||||
|
||||
if cfg!(not_a_cfg) { fail!() }
|
||||
if cfg!(not_a_cfg, foo, bar(baz), qux="foo") { fail!() }
|
||||
if cfg!(not_a_cfg, foo, qux="foo") { fail!() }
|
||||
if cfg!(all(not_a_cfg, foo, qux="foo")) { fail!() }
|
||||
if ! cfg!(any(not_a_cfg, foo)) { fail!() }
|
||||
|
||||
if ! cfg!(not(not_a_cfg)) { fail!() }
|
||||
if ! cfg!(not(not_a_cfg), foo, bar(baz), qux="foo") { fail!() }
|
||||
if ! cfg!(not(not_a_cfg), foo, qux="foo") { fail!() }
|
||||
|
||||
if cfg!(trailing_comma, ) { fail!() }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user