Skip to content

Commit 0cabf09

Browse files
bors[bot]japaric
andcommitted
Merge #159
159: static mut transform: forward `#[cfg]` r=therealprof a=japaric as reported in japaric/cortex-m-rtfm#110 the following code fails to compile ``` rust #[entry] fn main() -> ! { #[cfg(something)] static mut FOO: u32 = 0; //~ ERROR cannot find value `FOO` in this scope } ``` the issue is that the expansion of the static looks like this: ``` rust let FOO = unsafe { #[cfg(never)] static mut FOO: u32 = 0; &mut FOO }; ``` so when the `#[cfg]` evals to false the static is gone but the `let FOO` is not removed. this PR forwards `#[cfg]` attributes to the `let` expression and fixes the error ``` rust #[cfg(never)] // <- added let FOO = unsafe { #[cfg(never)] static mut FOO: u32 = 0; &mut FOO }; ``` Co-authored-by: Jorge Aparicio <[email protected]>
2 parents c7e6e5f + c69ff66 commit 0cabf09

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

cortex-m-rt/examples/cfg-static.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! using `#[cfg]` on `static` shouldn't cause compile errors
2+
3+
#![deny(unsafe_code)]
4+
#![deny(warnings)]
5+
#![no_main]
6+
#![no_std]
7+
8+
extern crate cortex_m_rt as rt;
9+
extern crate panic_halt;
10+
11+
use rt::{entry, exception};
12+
13+
#[entry]
14+
fn main() -> ! {
15+
#[cfg(never)]
16+
static mut COUNT: u32 = 0;
17+
18+
loop {}
19+
}
20+
21+
#[exception]
22+
fn SysTick() {
23+
#[cfg(never)]
24+
static mut FOO: u32 = 0;
25+
}

cortex-m-rt/macros/src/lib.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use std::collections::HashSet;
1616
use std::sync::atomic::{AtomicUsize, Ordering};
1717
use std::time::{SystemTime, UNIX_EPOCH};
1818
use syn::{
19-
parse, spanned::Spanned, FnArg, Ident, Item, ItemFn, ItemStatic, ReturnType, Stmt, Type,
20-
Visibility,
19+
parse, spanned::Spanned, AttrStyle, Attribute, FnArg, Ident, Item, ItemFn, ItemStatic,
20+
PathArguments, ReturnType, Stmt, Type, Visibility,
2121
};
2222

2323
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
@@ -128,15 +128,17 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
128128
let vars = statics
129129
.into_iter()
130130
.map(|var| {
131-
let attrs = var.attrs;
131+
let (ref cfgs, ref attrs) = extract_cfgs(var.attrs);
132132
let ident = var.ident;
133133
let ty = var.ty;
134134
let expr = var.expr;
135135

136136
quote!(
137137
#[allow(non_snake_case)]
138+
#(#cfgs)*
138139
let #ident: &'static mut #ty = unsafe {
139140
#(#attrs)*
141+
#(#cfgs)*
140142
static mut #ident: #ty = #expr;
141143

142144
&mut #ident
@@ -405,7 +407,6 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
405407

406408
// further type check of the input argument
407409
let #pat: &cortex_m_rt::ExceptionFrame = #pat;
408-
409410
#(#stmts)*
410411
}
411412
)
@@ -446,15 +447,17 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
446447
let vars = statics
447448
.into_iter()
448449
.map(|var| {
449-
let attrs = var.attrs;
450+
let (ref cfgs, ref attrs) = extract_cfgs(var.attrs);
450451
let ident = var.ident;
451452
let ty = var.ty;
452453
let expr = var.expr;
453454

454455
quote!(
455456
#[allow(non_snake_case)]
457+
#(#cfgs)*
456458
let #ident: &mut #ty = unsafe {
457459
#(#attrs)*
460+
#(#cfgs)*
458461
static mut #ident: #ty = #expr;
459462

460463
&mut #ident
@@ -603,15 +606,17 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
603606
let vars = statics
604607
.into_iter()
605608
.map(|var| {
606-
let attrs = var.attrs;
609+
let (ref cfgs, ref attrs) = extract_cfgs(var.attrs);
607610
let ident = var.ident;
608611
let ty = var.ty;
609612
let expr = var.expr;
610613

611614
quote!(
612615
#[allow(non_snake_case)]
616+
#(#cfgs)*
613617
let #ident: &mut #ty = unsafe {
614618
#(#attrs)*
619+
#(#cfgs)*
615620
static mut #ident: #ty = #expr;
616621

617622
&mut #ident
@@ -776,3 +781,27 @@ fn extract_static_muts(stmts: Vec<Stmt>) -> Result<(Vec<ItemStatic>, Vec<Stmt>),
776781

777782
Ok((statics, stmts))
778783
}
784+
785+
fn extract_cfgs(attrs: Vec<Attribute>) -> (Vec<Attribute>, Vec<Attribute>) {
786+
let mut cfgs = vec![];
787+
let mut not_cfgs = vec![];
788+
789+
for attr in attrs {
790+
if eq(&attr, "cfg") {
791+
cfgs.push(attr);
792+
} else {
793+
not_cfgs.push(attr);
794+
}
795+
}
796+
797+
(cfgs, not_cfgs)
798+
}
799+
800+
/// Returns `true` if `attr.path` matches `name`
801+
fn eq(attr: &Attribute, name: &str) -> bool {
802+
attr.style == AttrStyle::Outer && attr.path.segments.len() == 1 && {
803+
let pair = attr.path.segments.first().unwrap();
804+
let segment = pair.value();
805+
segment.arguments == PathArguments::None && segment.ident.to_string() == name
806+
}
807+
}

0 commit comments

Comments
 (0)