Skip to content

Commit 25e3a0b

Browse files
committed
codegen: Support new-type-alias constants
Fixes #3287
1 parent 1cf0a1f commit 25e3a0b

File tree

5 files changed

+77
-56
lines changed

5 files changed

+77
-56
lines changed

bindgen-integration/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@ fn setup_macro_test() {
251251
.blocklist_function("my_prefixed_function_to_remove")
252252
.constified_enum("my_prefixed_enum_to_be_constified")
253253
.opaque_type("my_prefixed_templated_foo<my_prefixed_baz>")
254+
.new_type_alias("MyInt")
255+
.new_type_alias("MyBool")
256+
.new_type_alias("MyFloat")
257+
.new_type_alias("MyChar")
254258
.new_type_alias("TestDeriveOnAlias")
255259
.depfile(out_rust_file_relative.display().to_string(), &out_dep_file)
256260
.generate()

bindgen-integration/cpp/Test.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,16 @@ enum MyOrderedEnum {
246246

247247
// Used to test custom derives on new-type alias. See `test_custom_derive`.
248248
typedef int TestDeriveOnAlias;
249+
250+
// Used to test new-type alias constants. See `test_new_type_alias_const`.
251+
typedef int MyInt;
252+
const MyInt MY_INT = 5;
253+
254+
typedef bool MyBool;
255+
const MyBool MY_BOOL = true;
256+
257+
typedef float MyFloat;
258+
const MyFloat MY_FLOAT = 1.23f;
259+
260+
typedef char MyChar;
261+
const MyChar MY_CHAR = 'a';

bindgen-integration/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,11 @@ fn test_colon_define() {
355355
let gold: u32 = (1u32 << 16) | 2;
356356
assert_eq!(gold, bindings::TESTMACRO_COLON_VALUE);
357357
}
358+
359+
#[test]
360+
fn test_new_type_alias_const() {
361+
assert_eq!(bindings::MY_INT.0, 5);
362+
assert_eq!(bindings::MY_BOOL.0, true);
363+
assert_eq!(bindings::MY_FLOAT.0, 1.23f32);
364+
assert_eq!(bindings::MY_CHAR.0, b'a' as std::ffi::c_char);
365+
}

bindgen/codegen/mod.rs

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -681,13 +681,8 @@ impl CodeGenerator for Var {
681681
let ty = var_ty.to_rust_ty_or_opaque(ctx, &());
682682

683683
if let Some(val) = self.val() {
684-
match *val {
685-
VarType::Bool(val) => {
686-
result.push(quote! {
687-
#(#attrs)*
688-
pub const #canonical_ident : #ty = #val ;
689-
});
690-
}
684+
let init = match *val {
685+
VarType::Bool(val) => Some((val.to_token_stream(), ty)),
691686
VarType::Int(val) => {
692687
let int_kind = var_ty
693688
.into_resolver()
@@ -702,10 +697,7 @@ impl CodeGenerator for Var {
702697
} else {
703698
helpers::ast_ty::uint_expr(val as _)
704699
};
705-
result.push(quote! {
706-
#(#attrs)*
707-
pub const #canonical_ident : #ty = #val ;
708-
});
700+
Some((val, ty))
709701
}
710702
VarType::String(ref bytes) => {
711703
let prefix = ctx.trait_prefix();
@@ -725,54 +717,50 @@ impl CodeGenerator for Var {
725717
None
726718
};
727719
if let Some(cstr) = cstr {
728-
let cstr_ty = quote! { ::#prefix::ffi::CStr };
720+
let cstr_ty =
721+
syn::parse_quote! { &::#prefix::ffi::CStr };
729722
if rust_features.literal_cstr {
730-
let cstr = proc_macro2::Literal::c_string(cstr);
731-
result.push(quote! {
732-
#(#attrs)*
733-
pub const #canonical_ident: &#cstr_ty = #cstr;
734-
});
723+
let cstr = proc_macro2::Literal::c_string(cstr)
724+
.into_token_stream();
725+
Some((cstr, cstr_ty))
735726
} else {
736-
let bytes =
727+
let bstr =
737728
proc_macro2::Literal::byte_string(&cstr_bytes);
738-
result.push(quote! {
739-
#(#attrs)*
740-
#[allow(unsafe_code)]
741-
pub const #canonical_ident: &#cstr_ty = unsafe {
742-
#cstr_ty::from_bytes_with_nul_unchecked(#bytes)
743-
};
744-
});
729+
let val = quote! {
730+
unsafe { ::#prefix::ffi::CStr::from_bytes_with_nul_unchecked(#bstr) }
731+
};
732+
attrs.push(quote! { #[allow(unsafe_code)] });
733+
Some((val, cstr_ty))
745734
}
746735
} else {
747736
// TODO: Here we ignore the type we just made up, probably
748737
// we should refactor how the variable type and ty ID work.
749-
let array_ty = quote! { [u8; #len] };
738+
let array_ty = syn::parse_quote! { &[u8; #len] };
750739
let bytes =
751-
proc_macro2::Literal::byte_string(&cstr_bytes);
752-
let lifetime =
753-
if true { None } else { Some(quote! { 'static }) }
754-
.into_iter();
755-
756-
result.push(quote! {
757-
#(#attrs)*
758-
pub const #canonical_ident: &#(#lifetime )*#array_ty = #bytes ;
759-
});
740+
proc_macro2::Literal::byte_string(&cstr_bytes)
741+
.into_token_stream();
742+
Some((bytes, array_ty))
760743
}
761744
}
762745
VarType::Float(f) => {
763-
if let Ok(expr) = helpers::ast_ty::float_expr(f) {
764-
result.push(quote! {
765-
#(#attrs)*
766-
pub const #canonical_ident : #ty = #expr ;
767-
});
768-
}
746+
helpers::ast_ty::float_expr(f).ok().map(|e| (e, ty))
769747
}
770-
VarType::Char(c) => {
771-
result.push(quote! {
772-
#(#attrs)*
773-
pub const #canonical_ident : #ty = #c ;
774-
});
748+
VarType::Char(c) => Some((c.to_token_stream(), ty)),
749+
};
750+
751+
if let Some((mut val, ty)) = init {
752+
let var_ty_item = ctx.resolve_item(var_ty);
753+
let alias_style = var_ty_item.alias_style(ctx);
754+
if matches!(
755+
alias_style,
756+
AliasVariation::NewType | AliasVariation::NewTypeDeref
757+
) {
758+
val = quote! { #ty(#val) };
775759
}
760+
result.push(quote! {
761+
#(#attrs)*
762+
pub const #canonical_ident : #ty = #val ;
763+
});
776764
}
777765
} else {
778766
let symbol: &str = self.link_name().unwrap_or_else(|| {
@@ -1005,15 +993,7 @@ impl CodeGenerator for Type {
1005993
quote! {}
1006994
};
1007995

1008-
let alias_style = if ctx.options().type_alias.matches(&name) {
1009-
AliasVariation::TypeAlias
1010-
} else if ctx.options().new_type_alias.matches(&name) {
1011-
AliasVariation::NewType
1012-
} else if ctx.options().new_type_alias_deref.matches(&name) {
1013-
AliasVariation::NewTypeDeref
1014-
} else {
1015-
ctx.options().default_alias_style
1016-
};
996+
let alias_style = item.alias_style(ctx);
1017997

1018998
// We prefer using `pub use` over `pub type` because of:
1019999
// https://github.com/rust-lang/rust/issues/26264

bindgen/ir/item.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Bindgen's core intermediate representation type.
22
3-
use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
3+
use super::super::codegen::{
4+
AliasVariation, EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME,
5+
};
46
use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
57
use super::annotations::Annotations;
68
use super::comp::{CompKind, MethodKind};
@@ -1103,6 +1105,20 @@ impl Item {
11031105
pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool {
11041106
self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
11051107
}
1108+
1109+
/// Get the alias style for this item.
1110+
pub(crate) fn alias_style(&self, ctx: &BindgenContext) -> AliasVariation {
1111+
let name = self.canonical_name(ctx);
1112+
if ctx.options().type_alias.matches(&name) {
1113+
AliasVariation::TypeAlias
1114+
} else if ctx.options().new_type_alias.matches(&name) {
1115+
AliasVariation::NewType
1116+
} else if ctx.options().new_type_alias_deref.matches(&name) {
1117+
AliasVariation::NewTypeDeref
1118+
} else {
1119+
ctx.options().default_alias_style
1120+
}
1121+
}
11061122
}
11071123

11081124
impl<T> IsOpaque for T

0 commit comments

Comments
 (0)