Skip to content

Commit a10bcfd

Browse files
adetayloremilio
authored andcommitted
Distinguish char16_t.
With a new command-line option, this ensures that char16_t is distinct from uint16_t in generated bindings. On some platforms these are distinct types, so it can be important for downstream post processors to spot the difference. See the documentation on the new command-line option for expected behavior and usage here. Part of google/autocxx#124.
1 parent 76920aa commit a10bcfd

File tree

7 files changed

+53
-3
lines changed

7 files changed

+53
-3
lines changed

bindgen-tests/tests/expectations/tests/char16_t.rs

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// bindgen-flags: --use-distinct-char16-t --raw-line '#[repr(transparent)] pub struct bindgen_cchar16_t(u16);' -- -x c++ -std=c++14
2+
3+
void receive_char16_t(char16_t input) {
4+
}

bindgen/codegen/helpers.rs

+6
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ pub(crate) mod ast_ty {
187187
match ik {
188188
IntKind::Bool => syn::parse_quote! { bool },
189189
IntKind::Char { .. } => raw_type(ctx, "c_char"),
190+
// The following is used only when an unusual command-line
191+
// argument is used. bindgen_cchar16_t is not a real type;
192+
// but this allows downstream postprocessors to distinguish
193+
// this case and do something special for C++ bindings
194+
// containing char16_t.
195+
IntKind::Char16 => syn::parse_quote! { bindgen_cchar16_t },
190196
IntKind::SChar => raw_type(ctx, "c_schar"),
191197
IntKind::UChar => raw_type(ctx, "c_uchar"),
192198
IntKind::Short => raw_type(ctx, "c_short"),

bindgen/ir/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
19801980
CXType_Short => TypeKind::Int(IntKind::Short),
19811981
CXType_UShort => TypeKind::Int(IntKind::UShort),
19821982
CXType_WChar => TypeKind::Int(IntKind::WChar),
1983+
CXType_Char16 if self.options().use_distinct_char16_t => {
1984+
TypeKind::Int(IntKind::Char16)
1985+
}
19831986
CXType_Char16 => TypeKind::Int(IntKind::U16),
19841987
CXType_Char32 => TypeKind::Int(IntKind::U32),
19851988
CXType_Long => TypeKind::Int(IntKind::Long),

bindgen/ir/int.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ pub enum IntKind {
5454
/// A 16-bit signed integer.
5555
I16,
5656

57-
/// Either a `char16_t` or a `wchar_t`.
57+
/// A 16-bit integer, used only for enum size representation.
5858
U16,
5959

60+
/// Either a `char16_t` or a `wchar_t`.
61+
Char16,
62+
6063
/// A 32-bit signed integer.
6164
I32,
6265

@@ -94,7 +97,7 @@ impl IntKind {
9497
// to know whether it is or not right now (unlike char, there's no
9598
// WChar_S / WChar_U).
9699
Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 |
97-
WChar | U32 | U64 | U128 => false,
100+
Char16 | WChar | U32 | U64 | U128 => false,
98101

99102
SChar | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 |
100103
I128 => true,
@@ -110,7 +113,7 @@ impl IntKind {
110113
use self::IntKind::*;
111114
Some(match *self {
112115
Bool | UChar | SChar | U8 | I8 | Char { .. } => 1,
113-
U16 | I16 => 2,
116+
U16 | I16 | Char16 => 2,
114117
U32 | I32 => 4,
115118
U64 | I64 => 8,
116119
I128 | U128 => 16,

bindgen/options/cli.rs

+5
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ struct BindgenCommand {
441441
/// Always output explicit padding fields.
442442
#[arg(long)]
443443
explicit_padding: bool,
444+
/// Use distinct char16_t
445+
#[arg(long)]
446+
use_distinct_char16_t: bool,
444447
/// Enables generation of vtable functions.
445448
#[arg(long)]
446449
vtable_generation: bool,
@@ -629,6 +632,7 @@ where
629632
translate_enum_integer_types,
630633
c_naming,
631634
explicit_padding,
635+
use_distinct_char16_t,
632636
vtable_generation,
633637
sort_semantically,
634638
merge_extern_blocks,
@@ -926,6 +930,7 @@ where
926930
translate_enum_integer_types,
927931
c_naming,
928932
explicit_padding,
933+
use_distinct_char16_t,
929934
vtable_generation,
930935
sort_semantically,
931936
merge_extern_blocks,

bindgen/options/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,28 @@ macro_rules! options {
153153
}
154154

155155
options! {
156+
/// Whether we should distinguish between 'char16_t' and 'u16'.
157+
/// As standard, bindgen represents `char16_t` as `u16`.
158+
/// Rust does not have a `std::os::raw::c_char16_t` type, and thus
159+
/// we can't use a built-in Rust type in the generated bindings.
160+
/// But for some uses of bindgen, especially when downstream
161+
/// post-processing occurs, it's important to distinguish `char16_t`
162+
/// from normal `uint16_t`. When this option is enabled, bindgen
163+
/// generates a fake type called `bindgen_cchar16_t`. Downstream
164+
/// code post-processors should arrange to replace this with a
165+
/// real type.
166+
use_distinct_char16_t: bool {
167+
methods: {
168+
/// If this is true, denote 'char16_t' as a separate type from 'u16'
169+
/// Disabled by default.
170+
pub fn use_distinct_char16_t(mut self, doit: bool) -> Builder {
171+
self.options.use_distinct_char16_t = doit;
172+
self
173+
}
174+
},
175+
as_args: "--use-distinct-char16-t",
176+
},
177+
156178
/// Types that have been blocklisted and should not appear anywhere in the generated code.
157179
blocklisted_types: RegexSet {
158180
methods: {

0 commit comments

Comments
 (0)