Skip to content

Commit

Permalink
Merge #149
Browse files Browse the repository at this point in the history
149: reject duplicate `static mut` variables r=therealprof a=japaric

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.

Co-authored-by: Jorge Aparicio <[email protected]>
  • Loading branch information
bors[bot] and japaric committed Nov 4, 2018
2 parents 2f890d8 + b6facc1 commit 3e0bbee
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
29 changes: 24 additions & 5 deletions cortex-m-rt/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)));
Expand All @@ -755,5 +774,5 @@ fn extract_static_muts(stmts: Vec<Stmt>) -> (Vec<ItemStatic>, Vec<Stmt>) {

stmts.extend(istmts);

(statics, stmts)
Ok((statics, stmts))
}
31 changes: 31 additions & 0 deletions cortex-m-rt/tests/compile-fail/duplicate-static.rs
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 3e0bbee

Please sign in to comment.