Disallow unknown and conflicting repr markers
This commit is contained in:
committed by
Ryan Hunt
parent
f9b8512dc2
commit
70d8b95f78
@@ -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());
|
||||
}
|
||||
|
||||
+47
-34
@@ -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"
|
||||
|
||||
+17
-1
@@ -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
|
||||
) { }
|
||||
|
||||
Reference in New Issue
Block a user