diff options
author | 2018-11-04 01:08:52 +0100 | |
---|---|---|
committer | 2018-11-04 01:08:52 +0100 | |
commit | b6facc16d893c2e886401cb0743bb29700388293 (patch) | |
tree | 177290bf54b326717157b43568006a42b16387d7 | |
parent | 2f890d87b1945f1f901355b94375d2531fa71f7c (diff) | |
download | cortex-m-b6facc16d893c2e886401cb0743bb29700388293.tar.gz cortex-m-b6facc16d893c2e886401cb0743bb29700388293.tar.zst cortex-m-b6facc16d893c2e886401cb0743bb29700388293.zip |
reject duplicate `static mut` variables
after #140 landed the entry, exception and interrupt attributes started
accepting code like this:
``` rust
#[entry]
fn main() -> ! {
static mut FOO: u32 = 0;
static mut FOO: i32 = 0;
}
```
because that code expands into:
``` rust
fn main() -> ! {
let FOO: &'static mut u32 = unsafe {
static mut FOO: u32 = 0;
&mut FOO
};
// shadows previous variable
let FOO: &'static mut u32 = unsafe {
static mut FOO: i32 = 0;
&mut FOO
};
}
```
this commit adds a check that rejects `static mut`s with duplicated names to
these three attributes.
-rw-r--r-- | cortex-m-rt/macros/src/lib.rs | 29 | ||||
-rw-r--r-- | cortex-m-rt/tests/compile-fail/duplicate-static.rs | 31 |
2 files changed, 55 insertions, 5 deletions
diff --git a/cortex-m-rt/macros/src/lib.rs b/cortex-m-rt/macros/src/lib.rs index 0032837..dfa936b 100644 --- a/cortex-m-rt/macros/src/lib.rs +++ b/cortex-m-rt/macros/src/lib.rs @@ -12,6 +12,7 @@ extern crate syn; use proc_macro2::Span; use rand::Rng; use rand::SeedableRng; +use std::collections::HashSet; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; use syn::{ @@ -119,7 +120,10 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { let attrs = f.attrs; let unsafety = f.unsafety; let hash = random_ident(); - let (statics, stmts) = extract_static_muts(f.block.stmts); + let (statics, stmts) = match extract_static_muts(f.block.stmts) { + Err(e) => return e.to_compile_error().into(), + Ok(x) => x, + }; let vars = statics .into_iter() @@ -434,7 +438,10 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { .into(); } - let (statics, stmts) = extract_static_muts(stmts); + let (statics, stmts) = match extract_static_muts(stmts) { + Err(e) => return e.to_compile_error().into(), + Ok(x) => x, + }; let vars = statics .into_iter() @@ -588,7 +595,10 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { .into(); } - let (statics, stmts) = extract_static_muts(stmts); + let (statics, stmts) = match extract_static_muts(stmts) { + Err(e) => return e.to_compile_error().into(), + Ok(x) => x, + }; let vars = statics .into_iter() @@ -732,15 +742,24 @@ fn random_ident() -> Ident { } /// Extracts `static mut` vars from the beginning of the given statements -fn extract_static_muts(stmts: Vec<Stmt>) -> (Vec<ItemStatic>, Vec<Stmt>) { +fn extract_static_muts(stmts: Vec<Stmt>) -> Result<(Vec<ItemStatic>, Vec<Stmt>), parse::Error> { let mut istmts = stmts.into_iter(); + let mut seen = HashSet::new(); let mut statics = vec![]; let mut stmts = vec![]; while let Some(stmt) = istmts.next() { match stmt { Stmt::Item(Item::Static(var)) => { if var.mutability.is_some() { + if seen.contains(&var.ident) { + return Err(parse::Error::new( + var.ident.span(), + format!("the name `{}` is defined multiple times", var.ident), + )); + } + + seen.insert(var.ident.clone()); statics.push(var); } else { stmts.push(Stmt::Item(Item::Static(var))); @@ -755,5 +774,5 @@ fn extract_static_muts(stmts: Vec<Stmt>) -> (Vec<ItemStatic>, Vec<Stmt>) { stmts.extend(istmts); - (statics, stmts) + Ok((statics, stmts)) } diff --git a/cortex-m-rt/tests/compile-fail/duplicate-static.rs b/cortex-m-rt/tests/compile-fail/duplicate-static.rs new file mode 100644 index 0000000..fccb65f --- /dev/null +++ b/cortex-m-rt/tests/compile-fail/duplicate-static.rs @@ -0,0 +1,31 @@ +#![no_main] +#![no_std] + +extern crate cortex_m_rt; +extern crate panic_halt; + +use cortex_m_rt::{entry, exception, interrupt}; + +enum interrupt { + UART0, +} + +#[entry] +fn foo() -> ! { + static mut X: u32 = 0; + static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times + + loop {} +} + +#[exception] +fn SVCall() { + static mut X: u32 = 0; + static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times +} + +#[interrupt] +fn UART0() { + static mut X: u32 = 0; + static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times +} |