diff --git a/src/clang.rs b/src/clang.rs index 4a46b694e3..f6566724a6 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1059,7 +1059,7 @@ impl Drop for Index { } /// A token emitted by clang's lexer. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Token { /// The kind of token this is. pub kind: CXTokenKind, diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs index 06dadab0c9..f111d98fe0 100644 --- a/src/codegen/helpers.rs +++ b/src/codegen/helpers.rs @@ -26,6 +26,14 @@ pub mod attributes { aster::AstBuilder::new().attr().word("inline") } + pub fn cold() -> ast::Attribute { + aster::AstBuilder::new().attr().word("cold") + } + + pub fn deprecated(_: Option<&str>) -> ast::Attribute { + aster::AstBuilder::new().attr().word("deprecated") + } + pub fn doc(comment: &str) -> ast::Attribute { aster::AstBuilder::new().attr().doc(comment) } @@ -33,6 +41,10 @@ pub mod attributes { pub fn link_name(name: &str) -> ast::Attribute { aster::AstBuilder::new().attr().name_value("link_name").str(name) } + + pub fn allow(rules: Vec<&str>) -> ast::Attribute { + aster::AstBuilder::new().attr().allow(rules) + } } /// Generates a proper type for a field or type with a given `Layout`, that is, @@ -75,12 +87,15 @@ impl BlobTyBuilder { } pub mod ast_ty { + use std::str; use aster; use ir::context::BindgenContext; use ir::function::FunctionSig; use ir::ty::FloatKind; + use ir::attr; use syntax::ast; use syntax::ptr::P; + use super::attributes; pub fn raw_type(ctx: &BindgenContext, name: &str) -> P { let ident = ctx.rust_ident_raw(&name); @@ -187,4 +202,32 @@ pub mod ast_ty { }) .collect::>() } + + pub fn attribute_to_rust(attribute: &attr::Attribute) -> ast::Attribute { + match *attribute { + attr::Attribute::Deprecated(ref text) => attributes::deprecated(text.as_ref().map(|s| s.as_str())), + attr::Attribute::Unused => attributes::allow(vec!["dead_code"]), + attr::Attribute::Used => attributes::doc("#[doc = \"__attribute__(unused)\"]"), + attr::Attribute::Cold => attributes::cold(), + attr::Attribute::Const => attributes::doc("#[doc = \"__attribute__(const)\"]"), + attr::Attribute::Constructor(_) => attributes::doc("#[doc = \"__attribute__(constructor)\"]"), + attr::Attribute::Destructor(_) => attributes::doc("#[doc = \"__attribute__(destructor)\"]"), + attr::Attribute::Aligned(ref tokens) => { + let s = tokens.iter() + .map(|ref token| unsafe { str::from_utf8_unchecked(&token.raw) }) + .fold(String::new(), |acc, ref s| { acc + &s }); + let t = format!("#[doc = \"__attribute__(aligned{})\"]", s.as_str()); + + attributes::doc(&t) + } + attr::Attribute::Unexposed(ref name, ref tokens) => { + let s = tokens.iter() + .map(|ref token| unsafe { str::from_utf8_unchecked(&token.raw) }) + .fold(String::new(), |acc, ref s| { acc + &s }); + let t = format!("#[doc = \"__attribute__({}{})\"]", name, s); + + attributes::doc(&t) + } + } + } } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 3b0882afcb..941bc57855 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -426,11 +426,19 @@ impl CodeGenerator for Var { result.saw_var(&canonical_name); let ty = self.ty().to_rust_ty(ctx); + let mut attrs = vec![]; + + if ctx.options().generate_comments { + for attr in self.attributes() { + attrs.push(helpers::ast_ty::attribute_to_rust(attr)); + } + } if let Some(val) = self.val() { let const_item = aster::AstBuilder::new() .item() .pub_() + .with_attrs(attrs) .const_(canonical_name) .expr(); let item = match *val { @@ -474,7 +482,6 @@ impl CodeGenerator for Var { result.push(item); } else { - let mut attrs = vec![]; if let Some(mangled) = self.mangled_name() { attrs.push(attributes::link_name(mangled)); } else if canonical_name != self.name() { @@ -877,6 +884,9 @@ impl CodeGenerator for CompInfo { if let Some(comment) = item.comment() { attributes.push(attributes::doc(comment)); } + for attr in self.attributes() { + attributes.push(helpers::ast_ty::attribute_to_rust(attr)); + } } if self.packed() { attributes.push(attributes::repr_list(&["C", "packed"])); @@ -1091,6 +1101,9 @@ impl CodeGenerator for CompInfo { if let Some(comment) = field.comment() { attrs.push(attributes::doc(comment)); } + for attr in field.attributes() { + attrs.push(helpers::ast_ty::attribute_to_rust(attr)); + } } let field_name = match field.name() { Some(name) => ctx.rust_mangle(name).into_owned(), @@ -1791,6 +1804,9 @@ impl CodeGenerator for Enum { if let Some(comment) = item.comment() { builder = builder.with_attr(attributes::doc(comment)); } + for attr in self.attributes() { + builder = builder.with_attr(helpers::ast_ty::attribute_to_rust(attr)); + } } if !is_constified_enum { @@ -2217,6 +2233,9 @@ impl CodeGenerator for Function { if let Some(comment) = item.comment() { attributes.push(attributes::doc(comment)); } + for attr in self.attributes() { + attributes.push(helpers::ast_ty::attribute_to_rust(attr)); + } } if let Some(mangled) = mangled_name { diff --git a/src/ir/attr.rs b/src/ir/attr.rs new file mode 100644 index 0000000000..33a148ab6b --- /dev/null +++ b/src/ir/attr.rs @@ -0,0 +1,153 @@ +//! Intermediate representation for attributes. +use std::str; + +use clang::Cursor; +use clang_sys::{CXCursor_UnexposedAttr, CXChildVisit_Continue}; +use cexpr::token::{Token, Kind}; + +use super::context::BindgenContext; + +/// The special attribute +#[derive(Clone, Debug)] +pub enum Attribute { + /// This attribute results in a warning if the type is used anywhere in the source file. + Deprecated(Option), + /// This attribute means that variables of that type are meant to appear possibly unused. + Unused, + /// This attribute attached to a function, means that code must be emitted for the function + /// even if it appears that the function is not referenced. + Used, + /// This attribute on functions is used to inform the compiler that the function is unlikely to be executed. + Cold, + /// Many functions do not examine any values except their arguments, + /// and have no effects except the return value. + Const, + /// This attribute causes the function to be called automatically before execution enters main (). + Constructor(Option), + /// This attribute causes the function to be called automatically after main () completes or exit () is called. + Destructor(Option), + /// This attribute specifies a minimum alignment (in bytes) + Aligned(Vec), + /// An attribute whose specific kind is not exposed via this interface. + Unexposed(String, Vec) +} + +impl Attribute { + /// Construct a new `Attribute`. + pub fn new(tokens: Vec) -> Self { + // https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax + assert!(!tokens.is_empty()); + + let (token, args) = tokens.split_first().unwrap(); + + assert_eq!(token.kind, Kind::Identifier); + + let name = unsafe { str::from_utf8_unchecked(&token.raw) }; + + debug!("__attribute__(({}({:?})))", name, args); + + match name { + "deprecated" => { + let text = if args.len() == 3 && + args[0].kind == Kind::Punctuation && args[0].raw.as_ref() == b"(" && + args[1].kind == Kind::Literal && + args[2].kind == Kind::Punctuation && args[2].raw.as_ref() == b")" { + str::from_utf8(args[1].raw.as_ref()).ok().map(String::from) + } else { + None + }; + + Attribute::Deprecated(text) + } + "unused" => Attribute::Unused, + "used" => Attribute::Used, + "cold" => Attribute::Cold, + "const" => Attribute::Const, + "constructor" => { + let priority = if args.len() == 3 && + args[0].kind == Kind::Punctuation && args[0].raw.as_ref() == b"(" && + args[1].kind == Kind::Literal && + args[2].kind == Kind::Punctuation && args[2].raw.as_ref() == b")" { + str::from_utf8(args[1].raw.as_ref()).ok().and_then(|s| s.parse::().ok()) + } else { + None + }; + + Attribute::Constructor(priority) + } + "destructor" => { + let priority = if args.len() == 3 && + args[0].kind == Kind::Punctuation && args[0].raw.as_ref() == b"(" && + args[1].kind == Kind::Literal && + args[2].kind == Kind::Punctuation && args[2].raw.as_ref() == b")" { + str::from_utf8(args[1].raw.as_ref()).ok().and_then(|s| s.parse::().ok()) + } else { + None + }; + + Attribute::Destructor(priority) + } + "aligned" => Attribute::Aligned(Vec::from(args)), + _ => Attribute::Unexposed(String::from(name), Vec::from(args)), + } + } + + /// Parse a `Cursor` for `Vec`. + pub fn parse(cur: &Cursor, ctx: &BindgenContext) -> Vec { + let mut attributes = vec![]; + + if let Some(tokens) = ctx.translation_unit().cexpr_tokens(&cur) { + let mut c = 0; + let mut iter = tokens.iter(); + + while c >= 0 { + let tokens = iter.by_ref().take_while(|ref token| { + if token.kind == Kind::Punctuation { + c += match token.raw.as_ref() { + b"(" => 1, + b")" => -1, + b"," if c == 0 => return false, + _ => 0, + } + } + + c >= 0 + }).map(|token| token.clone()).collect::>(); + + if tokens.is_empty() { + break + } else { + attributes.push(Attribute::new(tokens)); + } + } + } + + attributes + } + + /// Extract `Vec` from cursor's children. + pub fn extract(cur: &Cursor, ctx: &BindgenContext) -> Vec { + let mut attributes = vec![]; + + cur.visit(|cur| { + match cur.kind() { + CXCursor_UnexposedAttr => { + attributes.append(&mut Attribute::parse(&cur, ctx)) + } + _ => {} + } + CXChildVisit_Continue + }); + + attributes + } + + /// Whether this attribute whose specific kind is not exposed. + pub fn is_unexposed(&self) -> bool { + match *self { + Attribute::Unexposed(..) | + Attribute::Aligned(..) => true, + _ => false, + } + } +} \ No newline at end of file diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 34bd7a541c..5727cac839 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1,6 +1,7 @@ //! Compound types (unions and structs) in our intermediate representation. use super::annotations::Annotations; +use super::attr::Attribute; use super::context::{BindgenContext, ItemId}; use super::derive::{CanDeriveCopy, CanDeriveDebug}; use super::item::Item; @@ -102,6 +103,8 @@ pub struct Field { bitfield: Option, /// If the C++ field is marked as `mutable` mutable: bool, + /// The special attributes of field + attributes: Vec, } impl Field { @@ -111,7 +114,8 @@ impl Field { comment: Option, annotations: Option, bitfield: Option, - mutable: bool) + mutable: bool, + attributes: Vec) -> Field { Field { name: name, @@ -120,6 +124,7 @@ impl Field { annotations: annotations.unwrap_or_default(), bitfield: bitfield, mutable: mutable, + attributes: attributes, } } @@ -152,6 +157,11 @@ impl Field { pub fn annotations(&self) -> &Annotations { &self.annotations } + + /// The special attributes of field + pub fn attributes(&self) -> &[Attribute] { + &self.attributes + } } impl CanDeriveDebug for Field { @@ -275,13 +285,8 @@ pub struct CompInfo { /// Whether this struct is anonymous. is_anonymous: bool, - /// Used to know if we've found an opaque attribute that could cause us to - /// generate a type with invalid layout. This is explicitly used to avoid us - /// generating bad alignments when parsing types like max_align_t. - /// - /// It's not clear what the behavior should be here, if generating the item - /// and pray, or behave as an opaque type. - found_unknown_attr: bool, + /// The special attributes of types + attributes: Vec, /// Used to detect if we've run in a can_derive_debug cycle while cycling /// around the template arguments. @@ -315,7 +320,7 @@ impl CompInfo { has_non_type_template_params: false, packed: false, is_anonymous: false, - found_unknown_attr: false, + attributes: vec![], detect_derive_debug_cycle: Cell::new(false), detect_has_destructor_cycle: Cell::new(false), is_forward_declaration: false, @@ -530,7 +535,8 @@ impl CompInfo { cursor.visit(|cur| { if cur.kind() != CXCursor_FieldDecl { if let Some((ty, _)) = maybe_anonymous_struct_field { - let field = Field::new(None, ty, None, None, None, false); + let field = + Field::new(None, ty, None, None, None, false, vec![]); ci.fields.push(field); } maybe_anonymous_struct_field = None; @@ -553,7 +559,8 @@ impl CompInfo { None, None, None, - false); + false, + vec![]); ci.fields.push(field); } } @@ -578,25 +585,22 @@ impl CompInfo { let name = if name.is_empty() { None } else { Some(name) }; + // No we look for things like attributes and stuff. + + let attributes = Attribute::extract(&cur, ctx); + let field = Field::new(name, field_type, comment, annotations, bit_width, - is_mutable); - ci.fields.push(field); - - // No we look for things like attributes and stuff. - cur.visit(|cur| { - if cur.kind() == CXCursor_UnexposedAttr { - ci.found_unknown_attr = true; - } - CXChildVisit_Continue - }); + is_mutable, + attributes); + ci.fields.push(field); } CXCursor_UnexposedAttr => { - ci.found_unknown_attr = true; + ci.attributes.append(&mut Attribute::parse(&cur, ctx)); } CXCursor_EnumDecl | CXCursor_TypeAliasDecl | @@ -749,7 +753,7 @@ impl CompInfo { }); if let Some((ty, _)) = maybe_anonymous_struct_field { - let field = Field::new(None, ty, None, None, None, false); + let field = Field::new(None, ty, None, None, None, false, vec![]); ci.fields.push(field); } @@ -811,7 +815,15 @@ impl CompInfo { /// Have we found a field with an opaque type that could potentially mess up /// the layout of this compound type? pub fn found_unknown_attr(&self) -> bool { - self.found_unknown_attr + self.attributes.iter().any(|attr| attr.is_unexposed()) || + self.fields.iter().any(|field| { + field.attributes().iter().any(|attr| attr.is_unexposed()) + }) + } + + /// The special attributes of this compound type + pub fn attributes(&self) -> &[Attribute] { + &self.attributes } /// Is this compound type packed? diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs index 8ea7a8dcbc..507414421b 100644 --- a/src/ir/enum_ty.rs +++ b/src/ir/enum_ty.rs @@ -1,5 +1,6 @@ //! Intermediate representation for C/C++ enumerations. +use super::attr::Attribute; use super::context::{BindgenContext, ItemId}; use super::item::Item; use super::ty::TypeKind; @@ -28,14 +29,21 @@ pub struct Enum { /// The different variants, with explicit values. variants: Vec, + + /// The special attributes of enumeration. + attributes: Vec, } impl Enum { /// Construct a new `Enum` with the given representation and variants. - pub fn new(repr: Option, variants: Vec) -> Self { + pub fn new(repr: Option, + variants: Vec, + attributes: Vec) + -> Self { Enum { repr: repr, variants: variants, + attributes: attributes, } } @@ -49,6 +57,11 @@ impl Enum { &self.variants } + /// The special attributes of enumeration + pub fn attributes(&self) -> &[Attribute] { + &self.attributes + } + /// Construct an enumeration from the given Clang type. pub fn from_ty(ty: &clang::Type, ctx: &mut BindgenContext) @@ -108,15 +121,21 @@ impl Enum { }); let comment = cursor.raw_comment(); + + let attributes = Attribute::extract(&cursor, ctx); variants.push(EnumVariant::new(name, comment, val, - custom_behavior)); + custom_behavior, + attributes)); } } CXChildVisit_Continue }); - Ok(Enum::new(repr, variants)) + + let attributes = Attribute::extract(&declaration, ctx); + + Ok(Enum::new(repr, variants, attributes)) } } @@ -134,6 +153,9 @@ pub struct EnumVariant { /// The custom behavior this variant may have, if any. custom_behavior: Option, + + /// The special attributes of variable + attributes: Vec, } /// A constant value assigned to an enumeration variant. @@ -151,13 +173,15 @@ impl EnumVariant { pub fn new(name: String, comment: Option, val: EnumVariantValue, - custom_behavior: Option) + custom_behavior: Option, + attributes: Vec) -> Self { EnumVariant { name: name, comment: comment, val: val, custom_behavior: custom_behavior, + attributes: attributes, } } @@ -171,6 +195,11 @@ impl EnumVariant { self.val } + /// The special attributes of enumeration variant + pub fn attributes(&self) -> &[Attribute] { + &self.attributes + } + /// Returns whether this variant should be enforced to be a constant by code /// generation. pub fn force_constification(&self) -> bool { diff --git a/src/ir/function.rs b/src/ir/function.rs index 9ef9c3a73c..038c6e458f 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -2,6 +2,7 @@ use super::context::{BindgenContext, ItemId}; use super::item::Item; +use super::attr::Attribute; use super::ty::TypeKind; use super::type_collector::{ItemSet, TypeCollector}; use clang; @@ -26,6 +27,9 @@ pub struct Function { /// The doc comment on the function, if any. comment: Option, + + /// The special attributes of the function. + attributes: Vec, } impl Function { @@ -33,13 +37,15 @@ impl Function { pub fn new(name: String, mangled_name: Option, sig: ItemId, - comment: Option) + comment: Option, + attributes: Vec) -> Self { Function { name: name, mangled_name: mangled_name, signature: sig, comment: comment, + attributes: attributes, } } @@ -57,6 +63,11 @@ impl Function { pub fn signature(&self) -> ItemId { self.signature } + + /// The special attributes of this function. + pub fn attributes(&self) -> &[Attribute] { + &self.attributes + } } /// A function signature. @@ -310,7 +321,9 @@ impl ClangSubItemParser for Function { let comment = cursor.raw_comment(); - let function = Self::new(name, mangled_name, sig, comment); + let attributes = Attribute::extract(&cursor, context); + + let function = Self::new(name, mangled_name, sig, comment, attributes); Ok(ParseResult::New(function, Some(cursor))) } } diff --git a/src/ir/mod.rs b/src/ir/mod.rs index d424fcdfaa..e3060a749d 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -18,3 +18,4 @@ pub mod ty; pub mod type_collector; pub mod var; pub mod objc; +pub mod attr; diff --git a/src/ir/var.rs b/src/ir/var.rs index 6cfcdae735..a07c012b0e 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -4,6 +4,7 @@ use super::context::{BindgenContext, ItemId}; use super::function::cursor_mangling; use super::int::IntKind; use super::item::Item; +use super::attr::Attribute; use super::ty::{FloatKind, TypeKind}; use cexpr; use clang; @@ -38,6 +39,8 @@ pub struct Var { val: Option, /// Whether this variable is const. is_const: bool, + /// The special attributes of variable. + attributes: Vec, } impl Var { @@ -46,7 +49,8 @@ impl Var { mangled: Option, ty: ItemId, val: Option, - is_const: bool) + is_const: bool, + attributes: Vec) -> Var { assert!(!name.is_empty()); Var { @@ -55,6 +59,7 @@ impl Var { ty: ty, val: val, is_const: is_const, + attributes: attributes, } } @@ -82,6 +87,11 @@ impl Var { pub fn mangled_name(&self) -> Option<&str> { self.mangled_name.as_ref().map(|n| &**n) } + + /// The special attributes of variable. + pub fn attributes(&self) -> &[Attribute] { + &self.attributes + } } impl ClangSubItemParser for Var { @@ -168,8 +178,9 @@ impl ClangSubItemParser for Var { }; let ty = Item::builtin_type(type_kind, true, ctx); + let attributes = Attribute::extract(&cursor, ctx); - Ok(ParseResult::New(Var::new(name, None, ty, Some(val), true), + Ok(ParseResult::New(Var::new(name, None, ty, Some(val), true, attributes), Some(cursor))) } CXCursor_VarDecl => { @@ -239,7 +250,8 @@ impl ClangSubItemParser for Var { }; let mangling = cursor_mangling(&cursor); - let var = Var::new(name, mangling, ty, value, is_const); + let attributes = Attribute::extract(&cursor, ctx); + let var = Var::new(name, mangling, ty, value, is_const, attributes); Ok(ParseResult::New(var, Some(cursor))) } diff --git a/tests/expectations/tests/16-byte-alignment.rs b/tests/expectations/tests/16-byte-alignment.rs index b28c0537e6..e56a84817f 100644 --- a/tests/expectations/tests/16-byte-alignment.rs +++ b/tests/expectations/tests/16-byte-alignment.rs @@ -124,6 +124,7 @@ fn bindgen_test_layout_rte_ipv6_tuple() { impl Clone for rte_ipv6_tuple { fn clone(&self) -> Self { *self } } +#[doc = "__attribute__(aligned(16))"] #[repr(C)] #[derive(Copy)] pub struct rte_thash_tuple { diff --git a/tests/expectations/tests/attributes.rs b/tests/expectations/tests/attributes.rs new file mode 100644 index 0000000000..0620d620b9 --- /dev/null +++ b/tests/expectations/tests/attributes.rs @@ -0,0 +1,91 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const RTE_CACHE_LINE_SIZE: ::std::os::raw::c_uint = 64; +#[doc = "__attribute__(aligned(16))"] +pub const x: ::std::os::raw::c_int = 0; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + #[deprecated] + #[doc = "__attribute__(aligned(8))"] + #[allow(dead_code)] + pub x: [::std::os::raw::c_int; 2usize], +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} +extern "C" { + #[deprecated] + #[link_name = "old_var"] + pub static mut old_var: ::std::os::raw::c_int; +} +#[repr(u32)] +#[allow(dead_code)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum E { oldval = 0, newval = 1, } +extern "C" { + #[link_name = "foo"] + pub static mut foo: [::std::os::raw::c_int; 4usize]; +} +extern "C" { + #[cold] + #[deprecated] + #[link_name = "_Z6old_fnv"] + pub fn old_fn() -> ::std::os::raw::c_int; +} +extern "C" { + #[doc = "__attribute__(format(printf,2,3))"] + #[link_name = "_Z9my_printfPvPKcz"] + pub fn my_printf(my_object: *mut ::std::os::raw::c_void, + my_format: *const ::std::os::raw::c_char, ...) + -> ::std::os::raw::c_int; +} +extern "C" { + #[link_name = "_Z5fatalv"] + pub fn fatal(); +} +/** + * The generic rte_mbuf, containing a packet mbuf. + */ +#[doc = "__attribute__(__aligned__(a))"] +#[repr(C)] +#[derive(Debug, Copy)] +pub struct rte_mbuf { + /** Timesync flags for use with IEEE1588. */ + pub timesync: u16, +} +impl Clone for rte_mbuf { + fn clone(&self) -> Self { *self } +} +/** + * Physical memory segment descriptor. + */ +#[repr(C, packed)] +#[derive(Debug, Copy)] +pub struct rte_memseg { + /**< Number of channels. */ + pub nchannel: u32, + /**< Number of ranks. */ + pub nrank: u32, +} +#[test] +fn bindgen_test_layout_rte_memseg() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for rte_memseg { + fn clone(&self) -> Self { *self } +} +#[doc = "__attribute__(aligned(2*sizeof(longlong)))"] +#[repr(C)] +#[derive(Debug, Copy)] +pub struct align { + pub foo: ::std::os::raw::c_int, +} +impl Clone for align { + fn clone(&self) -> Self { *self } +} diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs index 530fdb22c5..c67d09dad0 100644 --- a/tests/expectations/tests/jsval_layout_opaque.rs +++ b/tests/expectations/tests/jsval_layout_opaque.rs @@ -95,6 +95,7 @@ pub enum JSWhyMagic { JS_GENERIC_MAGIC = 17, JS_WHY_MAGIC_COUNT = 18, } +#[doc = "__attribute__(aligned(8))"] #[repr(C)] #[derive(Debug, Copy)] pub struct jsval_layout { diff --git a/tests/expectations/tests/unknown_attr.rs b/tests/expectations/tests/unknown_attr.rs index fd9cce4593..5a4596d78b 100644 --- a/tests/expectations/tests/unknown_attr.rs +++ b/tests/expectations/tests/unknown_attr.rs @@ -4,13 +4,15 @@ #![allow(non_snake_case)] +#[doc = "__attribute__(__aligned__(16))"] #[repr(C)] #[derive(Debug, Copy)] -pub struct _bindgen_ty_1 { +pub struct max_align_t { + #[doc = "__attribute__(__aligned__(__alignof__(longlong)))"] pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, + #[doc = "__attribute__(__aligned__(__alignof__(longdouble)))"] pub __clang_max_align_nonce2: f64, } -impl Clone for _bindgen_ty_1 { +impl Clone for max_align_t { fn clone(&self) -> Self { *self } } -pub type max_align_t = _bindgen_ty_1; diff --git a/tests/headers/attributes.hpp b/tests/headers/attributes.hpp new file mode 100644 index 0000000000..54f406067e --- /dev/null +++ b/tests/headers/attributes.hpp @@ -0,0 +1,60 @@ +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +int x __attribute__ ((aligned (16))) = 0; + +struct foo { int x[2] __attribute__ ((unused, aligned (8), deprecated)); }; + +extern int old_var __attribute__ ((deprecated ("dont' use it"))); + +enum E { + oldval __attribute__((deprecated)), + newval +} __attribute__ ((unused)); + +int foo __attribute__ ((vector_size (16))); + +int old_fn () __attribute__ ((deprecated, cold)); + +extern int +my_printf (void *my_object, const char *my_format, ...) + __attribute__ ((format (printf, 2, 3))); + +void fatal () __attribute__ ((noreturn)); + +/** + * Force alignment + */ +#define __rte_aligned(a) __attribute__((__aligned__(a))) + +/** + * Force a structure to be packed + */ +#define __rte_packed __attribute__((__packed__)) + +#define RTE_CACHE_LINE_SIZE 64 /**< Minimum Cache line size. */ + +/** + * Force alignment to cache line. + */ +#define __rte_cache_aligned __rte_aligned(RTE_CACHE_LINE_SIZE) + +/** + * The generic rte_mbuf, containing a packet mbuf. + */ +struct rte_mbuf { + /** Timesync flags for use with IEEE1588. */ + uint16_t timesync; +} __rte_cache_aligned; + +/** + * Physical memory segment descriptor. + */ +struct rte_memseg { + uint32_t nchannel; /**< Number of channels. */ + uint32_t nrank; /**< Number of ranks. */ +} __rte_packed; + +struct align { + int foo; +} __attribute__((aligned(2 * sizeof(long long)))); \ No newline at end of file diff --git a/tests/headers/unknown_attr.h b/tests/headers/unknown_attr.h index f87e9f0b3a..b7d9483fda 100644 --- a/tests/headers/unknown_attr.h +++ b/tests/headers/unknown_attr.h @@ -1,6 +1,6 @@ -typedef struct { +struct max_align_t { long long __clang_max_align_nonce1 __attribute__((__aligned__(__alignof__(long long)))); long double __clang_max_align_nonce2 __attribute__((__aligned__(__alignof__(long double)))); -} max_align_t; +} __attribute__((__aligned__(16)));