Allow to generate associated constants in the body of C++ structs.

Opt-in since it uses a C++17 feature, but this allow exactly the same usage in
C++ and Rust, which I think is nice.

This also fixes constants of transparent structs in general, since the initial
version of this patch broke a test (associated constants in enums), so I added a
test for that too.
This commit is contained in:
Emilio Cobos Álvarez
2019-02-23 17:24:09 -08:00
parent 9761df66c2
commit 80da1f59aa
49 changed files with 430 additions and 233 deletions
+30 -18
View File
@@ -8,12 +8,15 @@ use std::io::{Read, Write};
use std::path;
use bindgen::config::{Config, Language};
use bindgen::ir::{Constant, Function, ItemContainer, Static};
use bindgen::ir::{Path as BindgenPath, ItemMap, Struct, Constant, Function, ItemContainer, Static};
use bindgen::writer::{Source, SourceWriter};
/// A bindings header that can be written.
pub struct Bindings {
config: Config,
pub config: Config,
/// The map from path to struct, used to lookup whether a given type is a
/// transparent struct. This is needed to generate code for constants.
struct_map: ItemMap<Struct>,
globals: Vec<Static>,
constants: Vec<Constant>,
items: Vec<ItemContainer>,
@@ -23,20 +26,29 @@ pub struct Bindings {
impl Bindings {
pub(crate) fn new(
config: Config,
struct_map: ItemMap<Struct>,
constants: Vec<Constant>,
globals: Vec<Static>,
items: Vec<ItemContainer>,
functions: Vec<Function>,
) -> Bindings {
Bindings {
config: config,
globals: globals,
constants: constants,
items: items,
functions: functions,
config,
struct_map,
globals,
constants,
items,
functions,
}
}
// FIXME(emilio): What to do when the configuration doesn't match?
pub fn struct_is_transparent(&self, path: &BindgenPath) -> bool {
let mut any = false;
self.struct_map.for_items(path, |s| any |= s.is_transparent);
any
}
pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
// Don't compare files if we've never written this file before
if !path.as_ref().is_file() {
@@ -126,7 +138,7 @@ impl Bindings {
}
pub fn write<F: Write>(&self, file: F) {
let mut out = SourceWriter::new(file, &self.config);
let mut out = SourceWriter::new(file, self);
if !self.config.no_includes
|| !self.config.includes.is_empty()
@@ -142,7 +154,7 @@ impl Bindings {
for constant in &self.constants {
if constant.ty.is_primitive_or_ptr_primitive() {
out.new_line_if_not_start();
constant.write(&self.config, &mut out);
constant.write(&self.config, &mut out, None);
out.new_line();
}
}
@@ -158,14 +170,14 @@ impl Bindings {
}
out.new_line_if_not_start();
match item {
&ItemContainer::Constant(..) => unreachable!(),
&ItemContainer::Static(..) => unreachable!(),
&ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
&ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
&ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
&ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
&ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
match *item {
ItemContainer::Constant(..) => unreachable!(),
ItemContainer::Static(..) => unreachable!(),
ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
}
out.new_line();
}
@@ -173,7 +185,7 @@ impl Bindings {
for constant in &self.constants {
if !constant.ty.is_primitive_or_ptr_primitive() {
out.new_line_if_not_start();
constant.write(&self.config, &mut out);
constant.write(&self.config, &mut out, None);
out.new_line();
}
}
+4
View File
@@ -284,6 +284,9 @@ pub struct StructConfig {
pub derive_gt: bool,
/// Whether to generate a greater than or equal to operator on structs with one field
pub derive_gte: bool,
/// Whether associated constants should be in the body. Only applicable to
/// non-transparent structs, and in C++-only.
pub associated_constants_in_body: bool,
}
impl Default for StructConfig {
@@ -297,6 +300,7 @@ impl Default for StructConfig {
derive_lte: false,
derive_gt: false,
derive_gte: false,
associated_constants_in_body: false,
}
}
}
+117 -75
View File
@@ -5,6 +5,7 @@
use std::fmt;
use std::io::Write;
use std::mem;
use std::borrow::Cow;
use syn;
@@ -15,6 +16,7 @@ use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
ToCondition, Type,
Struct,
};
use bindgen::writer::{Source, SourceWriter};
@@ -27,7 +29,7 @@ pub enum Literal {
right: Box<Literal>,
},
Struct {
name: String,
path: Path,
export_name: String,
fields: Vec<(String, Literal)>,
},
@@ -41,7 +43,7 @@ impl fmt::Display for Literal {
write!(f, "{} {} {}", left, op, right)
},
Literal::Struct {
name: _,
path: _,
export_name,
fields,
} => write!(
@@ -62,7 +64,7 @@ impl Literal {
pub fn rename_for_config(&mut self, config: &Config) {
match self {
Literal::Struct {
name: _,
path: _,
ref mut export_name,
fields,
} => {
@@ -161,7 +163,7 @@ impl Literal {
field_pairs.push((key, value));
}
Ok(Literal::Struct {
name: struct_name.clone(),
path: Path::new(struct_name.clone()),
export_name: struct_name,
fields: field_pairs,
})
@@ -180,84 +182,48 @@ pub struct Constant {
pub cfg: Option<Cfg>,
pub annotations: AnnotationSet,
pub documentation: Documentation,
pub associated_to: Option<Path>,
}
fn can_handle(ty: &Type, expr: &syn::Expr) -> bool {
if ty.is_primitive_or_ptr_primitive() {
return true;
}
match *expr {
syn::Expr::Struct(_) => true,
_ => false,
}
}
impl Constant {
pub fn load(
path: Path,
item: &syn::ItemConst,
mod_cfg: &Option<Cfg>,
ty: &syn::Type,
expr: &syn::Expr,
attrs: &[syn::Attribute],
associated_to: Option<Path>,
) -> Result<Constant, String> {
let ty = Type::load(&item.ty)?;
if ty.is_none() {
return Err("Cannot have a zero sized const definition.".to_owned());
}
let ty = ty.unwrap();
if !ty.is_primitive_or_ptr_primitive()
&& match *item.expr {
syn::Expr::Struct(_) => false,
_ => true,
let ty = Type::load(ty)?;
let ty = match ty {
Some(ty) => ty,
None => {
return Err("Cannot have a zero sized const definition.".to_owned());
}
{
};
if !can_handle(&ty, expr) {
return Err("Unhanded const definition".to_owned());
}
Ok(Constant::new(
path,
ty,
Literal::load(&item.expr)?,
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
AnnotationSet::load(&item.attrs)?,
Documentation::load(&item.attrs),
))
}
pub fn load_assoc(
name: String,
item: &syn::ImplItemConst,
mod_cfg: &Option<Cfg>,
is_transparent: bool,
struct_path: &Path,
) -> Result<Constant, String> {
let ty = Type::load(&item.ty)?;
if ty.is_none() {
return Err("Cannot have a zero sized const definition.".to_owned());
}
let ty = ty.unwrap();
let can_handle_const_expr = match item.expr {
syn::Expr::Struct(_) => true,
_ => false,
};
if !ty.is_primitive_or_ptr_primitive() && !can_handle_const_expr {
return Err("Unhandled const definition".to_owned());
}
let expr = Literal::load(match item.expr {
syn::Expr::Struct(syn::ExprStruct { ref fields, .. }) => {
if is_transparent && fields.len() == 1 {
&fields[0].expr
} else {
&item.expr
}
}
_ => &item.expr,
})?;
let full_name = Path::new(format!("{}_{}", struct_path, name));
Ok(Constant::new(
full_name,
ty,
expr,
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
AnnotationSet::load(&item.attrs)?,
Documentation::load(&item.attrs),
Literal::load(&expr)?,
Cfg::append(mod_cfg, Cfg::load(attrs)),
AnnotationSet::load(attrs)?,
Documentation::load(attrs),
associated_to,
))
}
@@ -268,6 +234,7 @@ impl Constant {
cfg: Option<Cfg>,
annotations: AnnotationSet,
documentation: Documentation,
associated_to: Option<Path>,
) -> Self {
let export_name = path.name().to_owned();
Self {
@@ -278,6 +245,7 @@ impl Constant {
cfg,
annotations,
documentation,
associated_to,
}
}
}
@@ -312,7 +280,9 @@ impl Item for Constant {
}
fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.export_name);
if self.associated_to.is_none() {
config.export.rename(&mut self.export_name);
}
self.value.rename_for_config(config);
self.ty.rename_for_config(config, &GenericParams::default()); // FIXME: should probably propagate something here
}
@@ -322,20 +292,92 @@ impl Item for Constant {
}
}
impl Source for Constant {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
impl Constant {
pub fn write_declaration<F: Write>(
&self,
config: &Config,
out: &mut SourceWriter<F>,
associated_to_struct: &Struct,
) {
debug_assert!(self.associated_to.is_some());
debug_assert!(config.language == Language::Cxx);
debug_assert!(!associated_to_struct.is_transparent);
debug_assert!(config.structure.associated_constants_in_body);
debug_assert!(config.constant.allow_static_const);
if let Type::ConstPtr(..) = self.ty {
out.write("static ");
} else {
out.write("static const ");
}
self.ty.write(config, out);
write!(out, " {};", self.export_name())
}
pub fn write<F: Write>(
&self,
config: &Config,
out: &mut SourceWriter<F>,
associated_to_struct: Option<&Struct>,
) {
if let Some(assoc) = associated_to_struct {
if assoc.is_generic() {
return; // Not tested / implemented yet, so bail out.
}
}
let associated_to_transparent =
associated_to_struct.map_or(false, |s| s.is_transparent);
let in_body = associated_to_struct.is_some() &&
config.language == Language::Cxx &&
config.structure.associated_constants_in_body &&
config.constant.allow_static_const &&
!associated_to_transparent;
let condition = (&self.cfg).to_condition(config);
condition.write_before(config, out);
let name = if in_body {
Cow::Owned(format!(
"{}::{}",
associated_to_struct.unwrap().export_name(),
self.export_name(),
))
} else if self.associated_to.is_none() {
Cow::Borrowed(self.export_name())
} else {
let associated_name = match associated_to_struct {
Some(s) => Cow::Borrowed(s.export_name()),
None => {
let mut name =
self.associated_to.as_ref().unwrap().name().to_owned();
config.export.rename(&mut name);
Cow::Owned(name)
}
};
Cow::Owned(format!("{}_{}", associated_name, self.export_name()))
};
let value = match self.value {
Literal::Struct { ref fields, ref path, .. } if out.bindings().struct_is_transparent(path) => {
&fields[0].1
}
_ => &self.value,
};
if config.constant.allow_static_const && config.language == Language::Cxx {
out.write(if in_body { "inline " } else { "static " });
if let Type::ConstPtr(..) = self.ty {
out.write("static ");
// Nothing.
} else {
out.write("static const ");
out.write("const ");
}
self.ty.write(config, out);
write!(out, " {} = {};", self.export_name(), self.value)
write!(out, " {} = {};", name, value)
} else {
write!(out, "#define {} {}", self.export_name(), self.value)
write!(out, "#define {} {}", name, value)
}
condition.write_after(config, out);
}
-1
View File
@@ -206,7 +206,6 @@ impl<T: Item + Clone> ItemMap<T> {
}
}
#[allow(dead_code)]
pub fn for_items<F>(&self, path: &Path, mut callback: F)
where
F: FnMut(&T),
+36 -2
View File
@@ -11,7 +11,7 @@ use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
Repr, ToCondition, Type, Typedef,
Repr, ToCondition, Type, Typedef, Constant,
};
use bindgen::library::Library;
use bindgen::mangle;
@@ -37,6 +37,7 @@ pub struct Struct {
pub cfg: Option<Cfg>,
pub annotations: AnnotationSet,
pub documentation: Documentation,
pub associated_constants: Vec<Constant>,
}
impl Struct {
@@ -45,6 +46,10 @@ impl Struct {
!self.fields.is_empty() && self.fields.iter().all(|x| x.1.can_cmp_eq())
}
pub fn add_associated_constant(&mut self, c: Constant) {
self.associated_constants.push(c);
}
pub fn load(item: &syn::ItemStruct, mod_cfg: &Option<Cfg>) -> Result<Self, String> {
let is_transparent = match Repr::load(&item.attrs)? {
Repr::C => false,
@@ -118,6 +123,7 @@ impl Struct {
cfg,
annotations,
documentation,
associated_constants: vec![],
}
}
@@ -266,6 +272,10 @@ impl Item for Struct {
for field in &mut self.fields {
reserved::escape(&mut field.0);
}
for c in self.associated_constants.iter_mut() {
c.rename_for_config(config);
}
}
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
@@ -279,6 +289,10 @@ impl Item for Struct {
for &(_, ref ty, _) in fields {
ty.add_dependencies_ignoring_generics(&self.generic_params, library, out);
}
for c in &self.associated_constants {
c.add_dependencies(library, out);
}
}
fn instantiate_monomorph(
@@ -327,7 +341,12 @@ impl Source for Struct {
annotations: self.annotations.clone(),
documentation: self.documentation.clone(),
};
return typedef.write(config, out);
typedef.write(config, out);
for constant in &self.associated_constants {
out.new_line();
constant.write(config, out, Some(self));
}
return;
}
let condition = (&self.cfg).to_condition(config);
@@ -484,6 +503,16 @@ impl Source for Struct {
out.write_raw_block(body);
}
if config.language == Language::Cxx &&
config.structure.associated_constants_in_body &&
config.constant.allow_static_const
{
for constant in &self.associated_constants {
out.new_line();
constant.write_declaration(config, out, self);
}
}
if config.language == Language::C && config.style.generate_typedef() {
out.close_brace(false);
write!(out, " {};", self.export_name());
@@ -491,6 +520,11 @@ impl Source for Struct {
out.close_brace(true);
}
for constant in &self.associated_constants {
out.new_line();
constant.write(config, out, Some(self));
}
condition.write_after(config, out);
}
}
+1
View File
@@ -115,6 +115,7 @@ impl Library {
Ok(Bindings::new(
self.config,
self.structs,
constants,
globals,
items,
+24 -57
View File
@@ -12,7 +12,7 @@ use syn;
use bindgen::cargo::{Cargo, PackageRef};
use bindgen::error::Error;
use bindgen::ir::{
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams, ItemContainer,
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams,
ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
};
use bindgen::utilities::{SynAbiHelpers, SynItemHelpers};
@@ -663,40 +663,6 @@ impl Parse {
}
}
fn is_assoc_const_of_transparent_struct(
&self,
const_item: &syn::ImplItemConst,
) -> Result<bool, ()> {
let ty = match Type::load(&const_item.ty) {
Ok(Some(t)) => t,
_ => return Ok(false),
};
let path = match ty.get_root_path() {
Some(p) => p,
_ => return Ok(false),
};
match self.structs.get_items(&path) {
Some(items) => {
if items.len() != 1 {
error!(
"Expected one struct to match path {}, but found {}",
path,
items.len(),
);
return Err(());
}
Ok(if let ItemContainer::Struct(ref s) = items[0] {
s.is_transparent
} else {
false
})
}
_ => Ok(false),
}
}
/// Loads associated `const` declarations
fn load_syn_assoc_consts<'a, I>(
&mut self,
@@ -722,12 +688,6 @@ impl Parse {
let impl_path = ty.unwrap().get_root_path().unwrap();
for item in items.into_iter() {
let is_assoc_const_of_transparent_struct =
match self.is_assoc_const_of_transparent_struct(&item) {
Ok(b) => b,
Err(_) => continue,
};
if crate_name != binding_crate_name {
info!(
"Skip {}::{} - (const's outside of the binding crate are not used).",
@@ -736,23 +696,31 @@ impl Parse {
continue;
}
let const_name = item.ident.to_string();
// TODO(emilio): It'd be nice to load them as scoped constants in
// C++ mode.
match Constant::load_assoc(
const_name,
item,
let path = Path::new(item.ident.to_string());
match Constant::load(
path,
mod_cfg,
is_assoc_const_of_transparent_struct,
&impl_path,
&item.ty,
&item.expr,
&item.attrs,
Some(impl_path.clone()),
) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
let full_name = constant.path.clone();
if !self.constants.try_insert(constant) {
error!("Conflicting name for constant {}", full_name);
info!("Take {}::{}::{}.", crate_name, impl_path, &item.ident);
let mut any = false;
self.structs.for_items_mut(&impl_path, |item| {
any = true;
item.add_associated_constant(constant.clone());
});
// Handle associated constants to other item types that are
// not structs like enums or such as regular constants.
if !any && !self.constants.try_insert(constant) {
error!(
"Conflicting name for constant {}::{}::{}.",
crate_name,
impl_path,
&item.ident,
);
}
}
Err(msg) => {
@@ -779,8 +747,7 @@ impl Parse {
}
let path = Path::new(item.ident.to_string());
match Constant::load(path, item, mod_cfg) {
match Constant::load(path, mod_cfg, &item.ty, &item.expr, &item.attrs, None) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
+14 -9
View File
@@ -6,6 +6,7 @@ use std::cmp;
use std::io;
use std::io::Write;
use bindgen::Bindings;
use bindgen::config::{Braces, Config};
/// A type of way to format a list.
@@ -57,7 +58,7 @@ impl<'a, 'b, F: Write> Write for InnerWriter<'a, 'b, F> {
/// A utility writer for generating code easier.
pub struct SourceWriter<'a, F: Write> {
out: F,
config: &'a Config,
bindings: &'a Bindings,
spaces: Vec<usize>,
line_started: bool,
line_length: usize,
@@ -67,10 +68,10 @@ pub struct SourceWriter<'a, F: Write> {
pub type MeasureWriter<'a> = SourceWriter<'a, NullFile>;
impl<'a, F: Write> SourceWriter<'a, F> {
pub fn new(out: F, config: &'a Config) -> SourceWriter<'a, F> {
pub fn new(out: F, bindings: &'a Bindings) -> Self {
SourceWriter {
out: out,
config: config,
out,
bindings,
spaces: vec![0],
line_started: false,
line_length: 0,
@@ -79,6 +80,10 @@ impl<'a, F: Write> SourceWriter<'a, F> {
}
}
pub fn bindings(&self) -> &Bindings {
&self.bindings
}
/// Takes a function that writes source and returns the maximum line length
/// written.
pub fn measure<T>(&self, func: T) -> usize
@@ -87,7 +92,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {
{
let mut measurer = SourceWriter {
out: NullFile,
config: self.config,
bindings: self.bindings,
spaces: self.spaces.clone(),
line_started: self.line_started,
line_length: self.line_length,
@@ -118,7 +123,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {
pub fn push_tab(&mut self) {
let spaces =
self.spaces() - (self.spaces() % self.config.tab_width) + self.config.tab_width;
self.spaces() - (self.spaces() % self.bindings.config.tab_width) + self.bindings.config.tab_width;
self.spaces.push(spaces);
}
@@ -141,7 +146,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {
}
pub fn open_brace(&mut self) {
match self.config.braces {
match self.bindings.config.braces {
Braces::SameLine => {
self.write(" {");
self.push_tab();
@@ -186,7 +191,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {
list_type: ListType<'b>,
) {
for (i, ref item) in items.iter().enumerate() {
item.write(self.config, self);
item.write(&self.bindings.config, self);
match list_type {
ListType::Join(text) => {
@@ -209,7 +214,7 @@ impl<'a, F: Write> SourceWriter<'a, F> {
let align_length = self.line_length_for_align();
self.push_set_spaces(align_length);
for (i, ref item) in items.iter().enumerate() {
item.write(self.config, self);
item.write(&self.bindings.config, self);
match list_type {
ListType::Join(text) => {
+2 -4
View File
@@ -3,12 +3,10 @@
#include <stdint.h>
#include <stdlib.h>
#define Foo_GA 10
#define Foo_ZO 3.14
typedef struct {
} Foo;
#define Foo_GA 10
#define Foo_ZO 3.14
void root(Foo x);
+2 -4
View File
@@ -2,13 +2,11 @@
#include <cstdint>
#include <cstdlib>
static const int32_t Foo_GA = 10;
static const float Foo_ZO = 3.14;
struct Foo {
};
static const int32_t Foo_GA = 10;
static const float Foo_ZO = 3.14;
extern "C" {
+19
View File
@@ -0,0 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* Constants shared by multiple CSS Box Alignment properties
* These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
*/
typedef struct {
uint8_t bits;
} StyleAlignFlags;
#define StyleAlignFlags_AUTO (StyleAlignFlags){ .bits = 0 }
#define StyleAlignFlags_NORMAL (StyleAlignFlags){ .bits = 1 }
#define StyleAlignFlags_START (StyleAlignFlags){ .bits = 1 << 1 }
#define StyleAlignFlags_END (StyleAlignFlags){ .bits = 1 << 2 }
#define StyleAlignFlags_FLEX_START (StyleAlignFlags){ .bits = 1 << 3 }
void root(StyleAlignFlags flags);
+25
View File
@@ -0,0 +1,25 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
/// Constants shared by multiple CSS Box Alignment properties
/// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
struct StyleAlignFlags {
uint8_t bits;
static const StyleAlignFlags AUTO;
static const StyleAlignFlags NORMAL;
static const StyleAlignFlags START;
static const StyleAlignFlags END;
static const StyleAlignFlags FLEX_START;
};
inline const StyleAlignFlags StyleAlignFlags::AUTO = (StyleAlignFlags){ .bits = 0 };
inline const StyleAlignFlags StyleAlignFlags::NORMAL = (StyleAlignFlags){ .bits = 1 };
inline const StyleAlignFlags StyleAlignFlags::START = (StyleAlignFlags){ .bits = 1 << 1 };
inline const StyleAlignFlags StyleAlignFlags::END = (StyleAlignFlags){ .bits = 1 << 2 };
inline const StyleAlignFlags StyleAlignFlags::FLEX_START = (StyleAlignFlags){ .bits = 1 << 3 };
extern "C" {
void root(StyleAlignFlags flags);
} // extern "C"
+3 -6
View File
@@ -10,13 +10,10 @@
typedef struct {
uint8_t bits;
} AlignFlags;
#define AlignFlags_AUTO (AlignFlags){ .bits = 0 }
#define AlignFlags_NORMAL (AlignFlags){ .bits = 1 }
#define AlignFlags_START (AlignFlags){ .bits = 1 << 1 }
#define AlignFlags_END (AlignFlags){ .bits = 1 << 2 }
#define AlignFlags_FLEX_START (AlignFlags){ .bits = 1 << 3 }
#define AlignFlags_NORMAL (AlignFlags){ .bits = 1 }
#define AlignFlags_START (AlignFlags){ .bits = 1 << 1 }
void root(AlignFlags flags);
+6 -5
View File
@@ -7,13 +7,14 @@
struct AlignFlags {
uint8_t bits;
};
static const AlignFlags AlignFlags_AUTO = (AlignFlags){ .bits = 0 };
static const AlignFlags AlignFlags_NORMAL = (AlignFlags){ .bits = 1 };
static const AlignFlags AlignFlags_START = (AlignFlags){ .bits = 1 << 1 };
static const AlignFlags AlignFlags_END = (AlignFlags){ .bits = 1 << 2 };
static const AlignFlags AlignFlags_FLEX_START = (AlignFlags){ .bits = 1 << 3 };
static const AlignFlags AlignFlags_NORMAL = (AlignFlags){ .bits = 1 };
extern "C" {
static const AlignFlags AlignFlags_START = (AlignFlags){ .bits = 1 << 1 };
void root(AlignFlags flags);
} // extern "C"
+2 -4
View File
@@ -3,12 +3,10 @@
#include <stdint.h>
#include <stdlib.h>
#define Foo_GA 10
#define Foo_ZO 3.14
typedef struct Foo {
} Foo;
#define Foo_GA 10
#define Foo_ZO 3.14
void root(Foo x);
@@ -0,0 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* Constants shared by multiple CSS Box Alignment properties
* These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
*/
typedef struct StyleAlignFlags {
uint8_t bits;
} StyleAlignFlags;
#define StyleAlignFlags_AUTO (StyleAlignFlags){ .bits = 0 }
#define StyleAlignFlags_NORMAL (StyleAlignFlags){ .bits = 1 }
#define StyleAlignFlags_START (StyleAlignFlags){ .bits = 1 << 1 }
#define StyleAlignFlags_END (StyleAlignFlags){ .bits = 1 << 2 }
#define StyleAlignFlags_FLEX_START (StyleAlignFlags){ .bits = 1 << 3 }
void root(StyleAlignFlags flags);
+3 -6
View File
@@ -10,13 +10,10 @@
typedef struct AlignFlags {
uint8_t bits;
} AlignFlags;
#define AlignFlags_AUTO (AlignFlags){ .bits = 0 }
#define AlignFlags_NORMAL (AlignFlags){ .bits = 1 }
#define AlignFlags_START (AlignFlags){ .bits = 1 << 1 }
#define AlignFlags_END (AlignFlags){ .bits = 1 << 2 }
#define AlignFlags_FLEX_START (AlignFlags){ .bits = 1 << 3 }
#define AlignFlags_NORMAL (AlignFlags){ .bits = 1 }
#define AlignFlags_START (AlignFlags){ .bits = 1 << 1 }
void root(AlignFlags flags);
@@ -0,0 +1,8 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef uint8_t Transparent;
#define FOO 0
@@ -7,9 +7,8 @@ typedef struct PREFIXFoo {
int32_t a;
uint32_t b;
} PREFIXFoo;
#define PREFIXFoo_FOO (PREFIXFoo){ .a = 42, .b = 47 }
#define PREFIXBAR (PREFIXFoo){ .a = 42, .b = 1337 }
#define PREFIXFoo_FOO (PREFIXFoo){ .a = 42, .b = 47 }
void root(PREFIXFoo x);
+1 -2
View File
@@ -7,9 +7,8 @@ typedef struct Foo {
int32_t a;
uint32_t b;
} Foo;
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
#define BAR (Foo){ .a = 42, .b = 1337 }
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
void root(Foo x);
+2 -4
View File
@@ -20,12 +20,10 @@ typedef DummyStruct TransparentComplexWrapper_i32;
typedef uint32_t TransparentPrimitiveWrapper_i32;
typedef uint32_t TransparentPrimitiveWithAssociatedConstants;
#define EnumWithAssociatedConstantInImpl_TEN 10
#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
#define TransparentPrimitiveWithAssociatedConstants_ONE 1
#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
#define EnumWithAssociatedConstantInImpl_TEN 10
void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
+8
View File
@@ -0,0 +1,8 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef uint8_t Transparent;
#define FOO 0
+7
View File
@@ -0,0 +1,7 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
using Transparent = uint8_t;
static const Transparent FOO = 0;
+1 -2
View File
@@ -7,9 +7,8 @@ typedef struct {
int32_t a;
uint32_t b;
} PREFIXFoo;
#define PREFIXFoo_FOO (PREFIXFoo){ .a = 42, .b = 47 }
#define PREFIXBAR (PREFIXFoo){ .a = 42, .b = 1337 }
#define PREFIXFoo_FOO (PREFIXFoo){ .a = 42, .b = 47 }
void root(PREFIXFoo x);
@@ -6,11 +6,10 @@ struct PREFIXFoo {
int32_t a;
uint32_t b;
};
static const PREFIXFoo PREFIXFoo_FOO = (PREFIXFoo){ .a = 42, .b = 47 };
static const PREFIXFoo PREFIXBAR = (PREFIXFoo){ .a = 42, .b = 1337 };
static const PREFIXFoo PREFIXFoo_FOO = (PREFIXFoo){ .a = 42, .b = 47 };
extern "C" {
void root(PREFIXFoo x);
+1 -2
View File
@@ -7,9 +7,8 @@ typedef struct {
int32_t a;
uint32_t b;
} Foo;
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
#define BAR (Foo){ .a = 42, .b = 1337 }
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
void root(Foo x);
+1 -2
View File
@@ -6,11 +6,10 @@ struct Foo {
int32_t a;
uint32_t b;
};
static const Foo Foo_FOO = (Foo){ .a = 42, .b = 47 };
static const Foo BAR = (Foo){ .a = 42, .b = 1337 };
static const Foo Foo_FOO = (Foo){ .a = 42, .b = 47 };
extern "C" {
void root(Foo x);
+2 -4
View File
@@ -3,12 +3,10 @@
#include <stdint.h>
#include <stdlib.h>
#define Foo_GA 10
#define Foo_ZO 3.14
struct Foo {
};
#define Foo_GA 10
#define Foo_ZO 3.14
void root(struct Foo x);
@@ -0,0 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* Constants shared by multiple CSS Box Alignment properties
* These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
*/
struct StyleAlignFlags {
uint8_t bits;
};
#define StyleAlignFlags_AUTO (StyleAlignFlags){ .bits = 0 }
#define StyleAlignFlags_NORMAL (StyleAlignFlags){ .bits = 1 }
#define StyleAlignFlags_START (StyleAlignFlags){ .bits = 1 << 1 }
#define StyleAlignFlags_END (StyleAlignFlags){ .bits = 1 << 2 }
#define StyleAlignFlags_FLEX_START (StyleAlignFlags){ .bits = 1 << 3 }
void root(struct StyleAlignFlags flags);
+3 -6
View File
@@ -10,13 +10,10 @@
struct AlignFlags {
uint8_t bits;
};
#define AlignFlags_AUTO (AlignFlags){ .bits = 0 }
#define AlignFlags_NORMAL (AlignFlags){ .bits = 1 }
#define AlignFlags_START (AlignFlags){ .bits = 1 << 1 }
#define AlignFlags_END (AlignFlags){ .bits = 1 << 2 }
#define AlignFlags_FLEX_START (AlignFlags){ .bits = 1 << 3 }
#define AlignFlags_NORMAL (AlignFlags){ .bits = 1 }
#define AlignFlags_START (AlignFlags){ .bits = 1 << 1 }
void root(struct AlignFlags flags);
@@ -0,0 +1,8 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef uint8_t Transparent;
#define FOO 0
@@ -7,9 +7,8 @@ struct PREFIXFoo {
int32_t a;
uint32_t b;
};
#define PREFIXFoo_FOO (PREFIXFoo){ .a = 42, .b = 47 }
#define PREFIXBAR (PREFIXFoo){ .a = 42, .b = 1337 }
#define PREFIXFoo_FOO (PREFIXFoo){ .a = 42, .b = 47 }
void root(struct PREFIXFoo x);
+1 -2
View File
@@ -7,9 +7,8 @@ struct Foo {
int32_t a;
uint32_t b;
};
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
#define BAR (Foo){ .a = 42, .b = 1337 }
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
void root(struct Foo x);
+2 -4
View File
@@ -20,12 +20,10 @@ typedef struct DummyStruct TransparentComplexWrapper_i32;
typedef uint32_t TransparentPrimitiveWrapper_i32;
typedef uint32_t TransparentPrimitiveWithAssociatedConstants;
#define EnumWithAssociatedConstantInImpl_TEN 10
#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
#define TransparentPrimitiveWithAssociatedConstants_ONE 1
#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
#define EnumWithAssociatedConstantInImpl_TEN 10
void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
+2 -4
View File
@@ -20,12 +20,10 @@ typedef DummyStruct TransparentComplexWrapper_i32;
typedef uint32_t TransparentPrimitiveWrapper_i32;
typedef uint32_t TransparentPrimitiveWithAssociatedConstants;
#define EnumWithAssociatedConstantInImpl_TEN 10
#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
#define TransparentPrimitiveWithAssociatedConstants_ONE 1
#define TransparentPrimitiveWithAssociatedConstants_ZERO 0
#define EnumWithAssociatedConstantInImpl_TEN 10
void root(TransparentComplexWrappingStructTuple a,
TransparentPrimitiveWrappingStructTuple b,
+2 -4
View File
@@ -21,12 +21,10 @@ template<typename T>
using TransparentPrimitiveWrapper = uint32_t;
using TransparentPrimitiveWithAssociatedConstants = uint32_t;
static const TransparentPrimitiveWrappingStructure EnumWithAssociatedConstantInImpl_TEN = 10;
static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO = 0;
static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ONE = 1;
static const TransparentPrimitiveWithAssociatedConstants TransparentPrimitiveWithAssociatedConstants_ZERO = 0;
static const TransparentPrimitiveWrappingStructure EnumWithAssociatedConstantInImpl_TEN = 10;
extern "C" {
+22
View File
@@ -0,0 +1,22 @@
bitflags! {
/// Constants shared by multiple CSS Box Alignment properties
///
/// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
#[derive(MallocSizeOf, ToComputedValue)]
#[repr(C)]
pub struct AlignFlags: u8 {
/// 'auto'
const AUTO = 0;
/// 'normal'
const NORMAL = 1;
/// 'start'
const START = 1 << 1;
/// 'end'
const END = 1 << 2;
/// 'flex-start'
const FLEX_START = 1 << 3;
}
}
#[no_mangle]
pub extern "C" fn root(flags: AlignFlags) {}
+5
View File
@@ -0,0 +1,5 @@
[struct]
associated_constants_in_body = true
[export]
prefix = "Style" # Just ensuring they play well together :)
+3
View File
@@ -17,3 +17,6 @@ bitflags! {
const FLEX_START = 1 << 3;
}
}
#[no_mangle]
pub extern "C" fn root(flags: AlignFlags) {}
+4
View File
@@ -0,0 +1,4 @@
#[repr(transparent)]
struct Transparent { field: u8 }
const FOO: Transparent = Transparent { field: 0 };
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "derive-eq"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "expand"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "expand"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "expand"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "expand"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "mod_attr"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "mod_path"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "dependency"
version = "0.1.0"
+2
View File
@@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "child"
version = "0.1.0"