Commit 70d8b95f authored by Ingvar Stepanyan's avatar Ingvar Stepanyan Committed by Ryan Hunt

Disallow unknown and conflicting repr markers

parent f9b8512d
......@@ -132,7 +132,7 @@ impl Enum {
attrs: &Vec<syn::Attribute>,
mod_cfg: &Option<Cfg>,
) -> Result<Enum, String> {
let repr = Repr::load(attrs);
let repr = Repr::load(attrs)?;
if repr == Repr::RUST {
return Err("Enum not marked with a valid repr(prim) or repr(C).".to_owned());
}
......
......@@ -43,42 +43,55 @@ impl Repr {
pub const RUST: Self = Repr {
style: ReprStyle::Rust,
ty: None,
};
pub fn load(attrs: &[syn::Attribute]) -> Repr {
attrs
.iter()
.filter_map(|attr| match *attr {
syn::Attribute {
style: syn::AttrStyle::Outer,
is_sugared_doc: false,
value: syn::MetaItem::List(ref id, ref nested)
} if id == "repr" => Some(nested),
_ => None,
})
.flat_map(|nested| nested)
.filter_map(|meta| match *meta {
syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref id)) => Some(id.as_ref()),
_ => None,
})
.fold(Repr::default(), |mut acc, id| {
if id == "C" {
acc.style = ReprStyle::C;
} else {
acc.ty = Some(match id {
"u8" => ReprType::U8,
"u16" => ReprType::U16,
"u32" => ReprType::U32,
"usize" => ReprType::USize,
"i8" => ReprType::I8,
"i16" => ReprType::I16,
"i32" => ReprType::I32,
"isize" => ReprType::ISize,
_ => return acc
});
pub fn load(attrs: &[syn::Attribute]) -> Result<Repr, String> {
let ids = attrs
.iter()
.filter_map(|attr| match *attr {
syn::Attribute {
style: syn::AttrStyle::Outer,
is_sugared_doc: false,
value: syn::MetaItem::List(ref id, ref nested),
} if id == "repr" =>
{
Some(nested)
}
_ => None,
})
.flat_map(|nested| nested)
.filter_map(|meta| match *meta {
syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref id)) => Some(id.as_ref()),
_ => None,
});
let mut repr = Repr::default();
for id in ids {
let new_ty = match id {
"u8" => ReprType::U8,
"u16" => ReprType::U16,
"u32" => ReprType::U32,
"usize" => ReprType::USize,
"i8" => ReprType::I8,
"i16" => ReprType::I16,
"i32" => ReprType::I32,
"isize" => ReprType::ISize,
"C" => {
repr.style = ReprStyle::C;
continue;
}
_ => {
return Err(format!("Unsupported #[repr({})].", id));
}
};
if let Some(old_ty) = repr.ty {
return Err(format!(
"Conflicting #[repr(...)] type hints {:?} and {:?}.",
old_ty, new_ty
));
}
acc
})
repr.ty = Some(new_ty);
}
Ok(repr)
}
}
......@@ -37,7 +37,7 @@ impl Struct {
attrs: &Vec<syn::Attribute>,
mod_cfg: &Option<Cfg>,
) -> Result<Struct, String> {
if Repr::load(attrs) != Repr::C {
if Repr::load(attrs)? != Repr::C {
return Err("Struct is not marked #[repr(C)].".to_owned());
}
......
......@@ -37,7 +37,7 @@ impl Union {
attrs: &Vec<syn::Attribute>,
mod_cfg: &Option<Cfg>,
) -> Result<Union, String> {
if Repr::load(attrs) != Repr::C {
if Repr::load(attrs)? != Repr::C {
return Err("Union is not marked #[repr(C)].".to_owned());
}
......
......@@ -42,6 +42,10 @@ enum E {
};
typedef intptr_t E;
typedef struct I I;
typedef struct J J;
typedef struct Opaque Opaque;
enum F_Tag {
......@@ -115,4 +119,4 @@ typedef struct {
};
} H;
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
......@@ -36,6 +36,10 @@ enum class E : intptr_t {
e4 = 5,
};
struct I;
struct J;
struct Opaque;
union F {
......@@ -111,6 +115,6 @@ struct H {
extern "C" {
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
} // extern "C"
......@@ -66,6 +66,20 @@ enum H {
Baz
}
#[repr(C, u8, u16)]
enum I {
Foo(i16),
Bar { x: u8, y: i16 },
Baz
}
#[repr(C, u8, unknown_hint)]
enum J {
Foo(i16),
Bar { x: u8, y: i16 },
Baz
}
#[no_mangle]
pub extern "C" fn root(
o: *mut Opaque,
......@@ -76,5 +90,7 @@ pub extern "C" fn root(
e: E,
f: F,
g: G,
h: H
h: H,
i: I,
j: J
) { }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment