aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <jorge@japaric.io> 2018-11-04 01:08:52 +0100
committerGravatar Jorge Aparicio <jorge@japaric.io> 2018-11-04 01:08:52 +0100
commitb6facc16d893c2e886401cb0743bb29700388293 (patch)
tree177290bf54b326717157b43568006a42b16387d7
parent2f890d87b1945f1f901355b94375d2531fa71f7c (diff)
downloadcortex-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.rs29
-rw-r--r--cortex-m-rt/tests/compile-fail/duplicate-static.rs31
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
+}