Process cfg_attr right before stripping cfg
Fixes #22070. Fixes #19372.
This commit is contained in:
parent
0110f5e03c
commit
5354317037
8 changed files with 113 additions and 38 deletions
|
|
@ -12,7 +12,7 @@ use attr::AttrMetaMethods;
|
|||
use diagnostic::SpanHandler;
|
||||
use fold::Folder;
|
||||
use {ast, fold, attr};
|
||||
use codemap::Spanned;
|
||||
use codemap::{Spanned, respan};
|
||||
use ptr::P;
|
||||
|
||||
use util::small_vector::SmallVector;
|
||||
|
|
@ -26,6 +26,7 @@ struct Context<F> where F: FnMut(&[ast::Attribute]) -> bool {
|
|||
// Support conditional compilation by transforming the AST, stripping out
|
||||
// any items that do not belong in the current configuration
|
||||
pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
|
||||
let krate = process_cfg_attr(diagnostic, krate);
|
||||
let config = krate.config.clone();
|
||||
strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs))
|
||||
}
|
||||
|
|
@ -281,3 +282,49 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attr
|
|||
attr::cfg_matches(diagnostic, cfg, &*mis[0])
|
||||
})
|
||||
}
|
||||
|
||||
struct CfgAttrFolder<'a> {
|
||||
diag: &'a SpanHandler,
|
||||
config: ast::CrateConfig,
|
||||
}
|
||||
|
||||
// Process `#[cfg_attr]`.
|
||||
fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
|
||||
let mut fld = CfgAttrFolder {
|
||||
diag: diagnostic,
|
||||
config: krate.config.clone(),
|
||||
};
|
||||
fld.fold_crate(krate)
|
||||
}
|
||||
|
||||
impl<'a> fold::Folder for CfgAttrFolder<'a> {
|
||||
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
|
||||
if !attr.check_name("cfg_attr") {
|
||||
return fold::noop_fold_attribute(attr, self);
|
||||
}
|
||||
|
||||
let (cfg, mi) = match attr.meta_item_list() {
|
||||
Some([ref cfg, ref mi]) => (cfg, mi),
|
||||
_ => {
|
||||
self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
if attr::cfg_matches(self.diag, &self.config[], &cfg) {
|
||||
Some(respan(mi.span, ast::Attribute_ {
|
||||
id: attr::mk_attr_id(),
|
||||
style: attr.node.style,
|
||||
value: mi.clone(),
|
||||
is_sugared_doc: false,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Need the ability to run pre-expansion.
|
||||
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
||||
fold::noop_fold_mac(mac, self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -528,8 +528,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
|
|||
syntax_expanders.insert(intern("cfg"),
|
||||
builtin_normal_expander(
|
||||
ext::cfg::expand_cfg));
|
||||
syntax_expanders.insert(intern("cfg_attr"),
|
||||
Modifier(box ext::cfg_attr::expand));
|
||||
syntax_expanders.insert(intern("trace_macros"),
|
||||
builtin_normal_expander(
|
||||
ext::trace_macros::expand_trace_macros));
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast;
|
||||
use attr;
|
||||
use codemap::Span;
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::build::AstBuilder;
|
||||
use ptr::P;
|
||||
|
||||
pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P<ast::Item>) -> P<ast::Item> {
|
||||
let (cfg, attr) = match mi.node {
|
||||
ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]),
|
||||
_ => {
|
||||
cx.span_err(sp, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
let mut out = (*it).clone();
|
||||
if attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &**cfg) {
|
||||
out.attrs.push(cx.attribute(attr.span, attr.clone()));
|
||||
}
|
||||
|
||||
P(out)
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,6 @@ pub mod ext {
|
|||
pub mod base;
|
||||
pub mod build;
|
||||
pub mod cfg;
|
||||
pub mod cfg_attr;
|
||||
pub mod concat;
|
||||
pub mod concat_idents;
|
||||
pub mod deriving;
|
||||
|
|
|
|||
18
src/test/compile-fail/cfg-attr-cfg-2.rs
Normal file
18
src/test/compile-fail/cfg-attr-cfg-2.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// error-pattern: main function not found
|
||||
// compile-flags: --cfg foo
|
||||
|
||||
// main is conditionally compiled, but the conditional compilation
|
||||
// is conditional too!
|
||||
|
||||
#[cfg_attr(foo, cfg(bar))]
|
||||
fn main() { }
|
||||
17
src/test/compile-fail/cfg-attr-crate-2.rs
Normal file
17
src/test/compile-fail/cfg-attr-crate-2.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// compile-flags: --cfg broken
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
|
||||
|
||||
#![cfg_attr(broken, no_std)] //~ ERROR no_std is experimental
|
||||
|
||||
fn main() { }
|
||||
15
src/test/run-pass/cfg-attr-cfg.rs
Normal file
15
src/test/run-pass/cfg-attr-cfg.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// main is conditionally compiled, but the conditional compilation
|
||||
// is conditional too!
|
||||
|
||||
#[cfg_attr(foo, cfg(bar))]
|
||||
fn main() { }
|
||||
15
src/test/run-pass/cfg-attr-crate.rs
Normal file
15
src/test/run-pass/cfg-attr-crate.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
|
||||
|
||||
#![cfg_attr(not_used, no_std)]
|
||||
|
||||
fn main() { }
|
||||
Loading…
Add table
Add a link
Reference in a new issue