Skip to content

Commit 6db6d99

Browse files
authored
Merge pull request #1018 from nicholasbishop/bishop-allow-union
xtask: Allow unions in uefi-raw
2 parents e25c4b8 + 9fd1cba commit 6db6d99

File tree

1 file changed

+79
-8
lines changed

1 file changed

+79
-8
lines changed

xtask/src/check_raw.rs

+79-8
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use syn::spanned::Spanned;
1616
use syn::token::Comma;
1717
use syn::{
1818
parenthesized, Abi, Attribute, Field, Fields, FieldsNamed, FieldsUnnamed, File, Item,
19-
ItemConst, ItemMacro, ItemStruct, ItemType, LitInt, ReturnType, Type, TypeArray, TypeBareFn,
20-
TypePtr, Visibility,
19+
ItemConst, ItemMacro, ItemStruct, ItemType, ItemUnion, LitInt, ReturnType, Type, TypeArray,
20+
TypeBareFn, TypePtr, Visibility,
2121
};
2222
use walkdir::WalkDir;
2323

@@ -253,26 +253,46 @@ fn check_fields(fields: &Punctuated<Field, Comma>, src: &Path) -> Result<(), Err
253253
Ok(())
254254
}
255255

256+
fn check_type_attrs(attrs: &[Attribute], spanned: &dyn Spanned, src: &Path) -> Result<(), Error> {
257+
let attrs = parse_attrs(attrs, src)?;
258+
let reprs = get_reprs(&attrs);
259+
260+
let allowed_reprs: &[&[Repr]] = &[&[Repr::C], &[Repr::C, Repr::Packed], &[Repr::Transparent]];
261+
262+
if allowed_reprs.contains(&reprs.as_slice()) {
263+
Ok(())
264+
} else {
265+
Err(Error::new(ErrorKind::ForbiddenRepr, src, spanned))
266+
}
267+
}
268+
256269
/// Validate a struct.
257270
fn check_struct(item: &ItemStruct, src: &Path) -> Result<(), Error> {
258271
if !is_pub(&item.vis) {
259272
return Err(Error::new(ErrorKind::MissingPub, src, &item.struct_token));
260273
}
261274

262-
let attrs = parse_attrs(&item.attrs, src)?;
263-
264275
match &item.fields {
265276
Fields::Named(FieldsNamed { named, .. }) => check_fields(named, src)?,
266277
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => check_fields(unnamed, src)?,
267278
Fields::Unit => {}
268279
}
269280

270-
let reprs = get_reprs(&attrs);
271-
let allowed_reprs: &[&[Repr]] = &[&[Repr::C], &[Repr::C, Repr::Packed], &[Repr::Transparent]];
272-
if !allowed_reprs.contains(&reprs.as_slice()) {
273-
return Err(Error::new(ErrorKind::ForbiddenRepr, src, item));
281+
check_type_attrs(&item.attrs, item, src)?;
282+
283+
Ok(())
284+
}
285+
286+
/// Validate a union.
287+
fn check_union(item: &ItemUnion, src: &Path) -> Result<(), Error> {
288+
if !is_pub(&item.vis) {
289+
return Err(Error::new(ErrorKind::MissingPub, src, &item.union_token));
274290
}
275291

292+
check_fields(&item.fields.named, src)?;
293+
294+
check_type_attrs(&item.attrs, item, src)?;
295+
276296
Ok(())
277297
}
278298

@@ -319,6 +339,9 @@ fn check_item(item: &Item, src: &Path) -> Result<(), Error> {
319339
Item::Struct(item) => {
320340
check_struct(item, src)?;
321341
}
342+
Item::Union(item) => {
343+
check_union(item, src)?;
344+
}
322345
Item::Macro(item) => {
323346
check_macro(item, src)?;
324347
}
@@ -555,4 +578,52 @@ mod tests {
555578
ErrorKind::ForbiddenType,
556579
);
557580
}
581+
582+
#[test]
583+
fn test_union() {
584+
// Valid union.
585+
assert!(check_union(
586+
&parse_quote! {
587+
#[repr(C)]
588+
pub union U {
589+
pub a: u32,
590+
pub b: u64,
591+
}
592+
},
593+
src(),
594+
)
595+
.is_ok());
596+
597+
// Missing `pub` on union.
598+
check_item_err(
599+
parse_quote! {
600+
#[repr(C)]
601+
struct U {
602+
pub f: u32,
603+
}
604+
},
605+
ErrorKind::MissingPub,
606+
);
607+
608+
// Missing `pub` on field.
609+
check_item_err(
610+
parse_quote! {
611+
#[repr(C)]
612+
pub struct U {
613+
f: u32,
614+
}
615+
},
616+
ErrorKind::MissingPub,
617+
);
618+
619+
// Forbidden `repr`.
620+
check_item_err(
621+
parse_quote! {
622+
pub struct S {
623+
pub f: u32,
624+
}
625+
},
626+
ErrorKind::ForbiddenRepr,
627+
);
628+
}
558629
}

0 commit comments

Comments
 (0)