Skip to content

Commit b6facc1

Browse files
committed
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.
1 parent 2f890d8 commit b6facc1

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

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

+24-5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern crate syn;
1212
use proc_macro2::Span;
1313
use rand::Rng;
1414
use rand::SeedableRng;
15+
use std::collections::HashSet;
1516
use std::sync::atomic::{AtomicUsize, Ordering};
1617
use std::time::{SystemTime, UNIX_EPOCH};
1718
use syn::{
@@ -119,7 +120,10 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
119120
let attrs = f.attrs;
120121
let unsafety = f.unsafety;
121122
let hash = random_ident();
122-
let (statics, stmts) = extract_static_muts(f.block.stmts);
123+
let (statics, stmts) = match extract_static_muts(f.block.stmts) {
124+
Err(e) => return e.to_compile_error().into(),
125+
Ok(x) => x,
126+
};
123127

124128
let vars = statics
125129
.into_iter()
@@ -434,7 +438,10 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
434438
.into();
435439
}
436440

437-
let (statics, stmts) = extract_static_muts(stmts);
441+
let (statics, stmts) = match extract_static_muts(stmts) {
442+
Err(e) => return e.to_compile_error().into(),
443+
Ok(x) => x,
444+
};
438445

439446
let vars = statics
440447
.into_iter()
@@ -588,7 +595,10 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
588595
.into();
589596
}
590597

591-
let (statics, stmts) = extract_static_muts(stmts);
598+
let (statics, stmts) = match extract_static_muts(stmts) {
599+
Err(e) => return e.to_compile_error().into(),
600+
Ok(x) => x,
601+
};
592602

593603
let vars = statics
594604
.into_iter()
@@ -732,15 +742,24 @@ fn random_ident() -> Ident {
732742
}
733743

734744
/// Extracts `static mut` vars from the beginning of the given statements
735-
fn extract_static_muts(stmts: Vec<Stmt>) -> (Vec<ItemStatic>, Vec<Stmt>) {
745+
fn extract_static_muts(stmts: Vec<Stmt>) -> Result<(Vec<ItemStatic>, Vec<Stmt>), parse::Error> {
736746
let mut istmts = stmts.into_iter();
737747

748+
let mut seen = HashSet::new();
738749
let mut statics = vec![];
739750
let mut stmts = vec![];
740751
while let Some(stmt) = istmts.next() {
741752
match stmt {
742753
Stmt::Item(Item::Static(var)) => {
743754
if var.mutability.is_some() {
755+
if seen.contains(&var.ident) {
756+
return Err(parse::Error::new(
757+
var.ident.span(),
758+
format!("the name `{}` is defined multiple times", var.ident),
759+
));
760+
}
761+
762+
seen.insert(var.ident.clone());
744763
statics.push(var);
745764
} else {
746765
stmts.push(Stmt::Item(Item::Static(var)));
@@ -755,5 +774,5 @@ fn extract_static_muts(stmts: Vec<Stmt>) -> (Vec<ItemStatic>, Vec<Stmt>) {
755774

756775
stmts.extend(istmts);
757776

758-
(statics, stmts)
777+
Ok((statics, stmts))
759778
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
extern crate cortex_m_rt;
5+
extern crate panic_halt;
6+
7+
use cortex_m_rt::{entry, exception, interrupt};
8+
9+
enum interrupt {
10+
UART0,
11+
}
12+
13+
#[entry]
14+
fn foo() -> ! {
15+
static mut X: u32 = 0;
16+
static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times
17+
18+
loop {}
19+
}
20+
21+
#[exception]
22+
fn SVCall() {
23+
static mut X: u32 = 0;
24+
static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times
25+
}
26+
27+
#[interrupt]
28+
fn UART0() {
29+
static mut X: u32 = 0;
30+
static mut X: i32 = 0; //~ ERROR the name `X` is defined multiple times
31+
}

0 commit comments

Comments
 (0)