Skip to content

Implement cfg syntax changes #17527

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 28, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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,
Expand Down
26 changes: 26 additions & 0 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 33 additions & 4 deletions src/libsyntax/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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> {
Expand Down Expand Up @@ -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
}

19 changes: 12 additions & 7 deletions src/libsyntax/ext/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use ext::build::AstBuilder;
use attr;
use attr::*;
use parse::attr::ParserAttr;
use parse::token::InternedString;
use parse::token;


Expand All @@ -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 = cfgs.iter().all(|cfg| attr::cfg_matches(&cx.parse_sess.span_diagnostic,
cx.cfg.as_slice(), &**cfg));

let matches_cfg = attr::test_cfg(cx.cfg().as_slice(),
in_cfg.iter());
let e = cx.expr_bool(sp, matches_cfg);
MacExpr::new(e)
MacExpr::new(cx.expr_bool(sp, matches_cfg))
}
25 changes: 1 addition & 24 deletions src/libsyntax/ext/cfg_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
9 changes: 4 additions & 5 deletions src/test/compile-fail/asm-in-bad-modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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() {}
4 changes: 2 additions & 2 deletions src/test/compile-fail/asm-misplaced-option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/test/compile-fail/asm-out-assign-imm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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() {}
8 changes: 4 additions & 4 deletions src/test/compile-fail/asm-out-no-modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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() {}
8 changes: 4 additions & 4 deletions src/test/compile-fail/asm-out-read-uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/test-cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/pretty/raw-str-nonexpr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"###); } }
16 changes: 8 additions & 8 deletions src/test/run-pass/syntax-extension-cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!() }
}