Skip to content

Commit 460e427

Browse files
anforowiczcopybara-github
authored andcommitted
Map int to core::ffi::c_int (also for most other builtin C++ types).
This CL provides mappings for most types under `core::ffi`, except for: * Types like `core::ffi::ptrdiff_t`, because they depend on an experimental feature: rust-lang/rust#88345 * `core::ffi::c_char` because of b/276931370 and because continuing translating `char` to `u8` reduces the amount of cascading changes in this CL (e.g. changes to `crubit/support/cc_std/string_view.rs`). Note that some other `clang/AST/BuiltinTypes.def` types like `char16_t` don't have an equivelent under `core::ffi`. This CL doesn't change how such types are handled (some of them are already covered by `rs_bindings_from_cc/type_map.cc`). PiperOrigin-RevId: 533279988
1 parent f164e03 commit 460e427

31 files changed

+498
-418
lines changed

docs/bindings/reference/primitive_scalar_types.md

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,35 +30,32 @@ The C++ types below are mapped one-way into the corresponding Rust types.
3030
("one-way" means that the type doesn't round-trip - for example `size_t` maps to
3131
`usize`, but `usize` maps to `uintptr_t`.)
3232

33-
C++ | Rust
34-
----------- | -------
35-
`ptrdiff_t` | `isize`
36-
`size_t` | `usize`
37-
`char16_t` | `u16`
38-
`char32_t` | `u32`
39-
`wchar_t` | `i32`
40-
41-
### Platform-specific map
42-
43-
TODO(b/276790180): These will eventually become `ffi::c_char`, `ffi::c_int`,
44-
etc.
45-
46-
The following C++ types are mapped in a platform-dependent way to the
47-
corresponding Rust type of the same width and signedness:
48-
49-
C++ | Rust
50-
-------------------- | -----------------------
51-
`char` | `i8` or `u8`, or higher
52-
`signed char` | `i8` or higher
53-
`unsigned char` | `u8` or higher
54-
`short` | `i16` or higher
55-
`unsigned short` | `u16` or higher
56-
`int` | `i16` or higher
57-
`unsigned int` | `u16` or higher
58-
`long` | `i32` or higher
59-
`unsigned long` | `u32` or higher
60-
`long long` | `i64`
61-
`unsigned long long` | `u64`
33+
TODO(b/283258442): `::core::ffi::*` should eventually be a bidirectional mapping
34+
35+
| C++ | Rust | Notes |
36+
| -------------------- | -------------------------- | ------------------------ |
37+
| `ptrdiff_t` | `isize` | |
38+
| `size_t` | `usize` | |
39+
| `char16_t` | `u16` | |
40+
| `char32_t` | `u32` | Unlike `rs_std::rs_char` |
41+
: : : above, `char32_t` may :
42+
: : : contain invalid Unicode :
43+
: : : characters :
44+
| `wchar_t` | `i32` | TODO(b/283268558): This |
45+
: : : is wrong on Windows. :
46+
| `char` | `u8` or `i8` depending on | TODO(b/276790180): This |
47+
: : whether `char` is signed : may eventually become :
48+
: : on the target platform : `c_char` :
49+
| `signed char` | `::core::ffi::c_schar` | |
50+
| `unsigned char` | `::core::ffi::c_uchar` | |
51+
| `short` | `::core::ffi::c_short` | |
52+
| `unsigned short` | `::core::ffi::c_ushort` | |
53+
| `int` | `::core::ffi::c_int` | |
54+
| `unsigned int` | `::core::ffi::c_uint` | |
55+
| `long` | `::core::ffi::c_long` | |
56+
| `unsigned long` | `::core::ffi::c_ulong` | |
57+
| `long long` | `::core::ffi::c_longlong` | |
58+
| `unsigned long long` | `::core::ffi::c_ulonglong` | |
6259

6360
## Unsupported types
6461

rs_bindings_from_cc/importer.cc

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -837,30 +837,52 @@ absl::StatusOr<MappedType> Importer::ConvertType(
837837
switch (builtin_type->getKind()) {
838838
case clang::BuiltinType::Bool:
839839
return MappedType::Simple("bool", "bool");
840-
break;
840+
case clang::BuiltinType::Void:
841+
return MappedType::Void();
842+
843+
// Floating-point numbers
844+
//
845+
// TODO(b/255768062): Generated bindings should explicitly check if
846+
// `math.h` defines the `__STDC_IEC_559__` macro.
841847
case clang::BuiltinType::Float:
842-
// TODO(b/255768062): Generated bindings should explicitly check if
843-
// `math.h` defines the `__STDC_IEC_559__` macro.
844848
return MappedType::Simple("f32", "float");
845-
break;
846849
case clang::BuiltinType::Double:
847-
// TODO(b/255768062): Generated bindings should explicitly check if
848-
// `math.h` defines the `__STDC_IEC_559__` macro.
849850
return MappedType::Simple("f64", "double");
850-
break;
851-
case clang::BuiltinType::Void:
852-
return MappedType::Void();
853-
break;
851+
852+
// `char`
853+
case clang::BuiltinType::Char_S: // 'char' in targets where it's signed
854+
// TODO(b/276790180, b/276931370): use `::core::ffi::c_char` instead.
855+
return MappedType::Simple("i8", "char");
856+
case clang::BuiltinType::Char_U: // 'char' in targets where it's unsigned
857+
// TODO(b/276790180, b/276931370): use `::core::ffi::c_char` instead.
858+
return MappedType::Simple("u8", "char");
859+
case clang::BuiltinType::SChar: // 'signed char', explicitly qualified
860+
return MappedType::Simple("::core::ffi::c_schar", "signed char");
861+
case clang::BuiltinType::UChar: // 'unsigned char', explicitly qualified
862+
return MappedType::Simple("::core::ffi::c_uchar", "unsigned char");
863+
864+
// Signed integers
865+
case clang::BuiltinType::Short:
866+
return MappedType::Simple("::core::ffi::c_short", "short");
867+
case clang::BuiltinType::Int:
868+
return MappedType::Simple("::core::ffi::c_int", "int");
869+
case clang::BuiltinType::Long:
870+
return MappedType::Simple("::core::ffi::c_long", "long");
871+
case clang::BuiltinType::LongLong:
872+
return MappedType::Simple("::core::ffi::c_longlong", "long long");
873+
874+
// Unsigned integers
875+
case clang::BuiltinType::UShort:
876+
return MappedType::Simple("::core::ffi::c_ushort", "unsigned short");
877+
case clang::BuiltinType::UInt:
878+
return MappedType::Simple("::core::ffi::c_uint", "unsigned int");
879+
case clang::BuiltinType::ULong:
880+
return MappedType::Simple("::core::ffi::c_ulong", "unsigned long");
881+
case clang::BuiltinType::ULongLong:
882+
return MappedType::Simple("::core::ffi::c_ulonglong",
883+
"unsigned long long");
854884
default:
855-
if (builtin_type->isIntegerType()) {
856-
auto size = ctx_.getTypeSize(builtin_type);
857-
if (size == 8 || size == 16 || size == 32 || size == 64) {
858-
return MappedType::Simple(
859-
absl::Substitute(
860-
"$0$1", builtin_type->isSignedInteger() ? 'i' : 'u', size),
861-
type_string);
862-
}
863-
}
885+
break;
864886
}
865887
} else if (const auto* tag_type = type->getAsAdjusted<clang::TagType>()) {
866888
return ConvertTypeDecl(tag_type->getDecl());

rs_bindings_from_cc/importer_test.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ auto CcTypeParamsAre(const Args&... matchers) {
185185

186186
auto IsCcInt() { return AllOf(NameIs("int"), CcTypeParamsAre()); }
187187

188-
auto IsRsInt() { return AllOf(NameIs("i32"), RsTypeParamsAre()); }
188+
auto IsRsInt() {
189+
return AllOf(NameIs("::core::ffi::c_int"), RsTypeParamsAre());
190+
}
189191

190192
// Matches a CcType that is a pointer to a type matching `matcher`.
191193
template <typename Matcher>

rs_bindings_from_cc/ir.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ struct RsType {
185185
llvm::json::Value ToJson() const;
186186

187187
// The name of the type. Examples:
188-
// - "i32" or "bool"
188+
// - "i32" or "bool" or "::core::ffi::c_int"
189189
// - "()" (the unit type, equivalent of "void" in CcType)
190190
// - "&", "&mut", "*const", "*mut" (pointee stored in `type_args[0]`)
191191
// - "Option" (e.g. representing nullable, lifetime-annotated C++ pointer as

rs_bindings_from_cc/ir_from_cc_test.rs

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn test_function() {
3333
doc_comment: None,
3434
return_type: MappedType {
3535
rs_type: RsType {
36-
name: Some("i32"),
36+
name: Some("::core::ffi::c_int"),
3737
lifetime_args: [],
3838
type_args: [],
3939
decl_id: None,
@@ -49,7 +49,7 @@ fn test_function() {
4949
FuncParam {
5050
type_: MappedType {
5151
rs_type: RsType {
52-
name: Some("i32"),
52+
name: Some("::core::ffi::c_int"),
5353
lifetime_args: [],
5454
type_args: [],
5555
decl_id: None,
@@ -66,7 +66,7 @@ fn test_function() {
6666
FuncParam {
6767
type_: MappedType {
6868
rs_type: RsType {
69-
name: Some("i32"),
69+
name: Some("::core::ffi::c_int"),
7070
lifetime_args: [],
7171
type_args: [],
7272
decl_id: None,
@@ -399,7 +399,7 @@ fn test_bitfields() {
399399
Field {
400400
identifier: Some("b1"), ...
401401
type_: Ok(MappedType {
402-
rs_type: RsType { name: Some("i32"), ... },
402+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
403403
cc_type: CcType { name: Some("int"), ... },
404404
}), ...
405405
offset: 0,
@@ -409,7 +409,7 @@ fn test_bitfields() {
409409
Field {
410410
identifier: Some("b2"), ...
411411
type_: Ok(MappedType {
412-
rs_type: RsType { name: Some("i32"), ... },
412+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
413413
cc_type: CcType { name: Some("int"), ... },
414414
}), ...
415415
offset: 1,
@@ -419,7 +419,7 @@ fn test_bitfields() {
419419
Field {
420420
identifier: Some("b3"), ...
421421
type_: Ok(MappedType {
422-
rs_type: RsType { name: Some("i32"), ... },
422+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
423423
cc_type: CcType { name: Some("int"), ... },
424424
}), ...
425425
offset: 3,
@@ -429,7 +429,7 @@ fn test_bitfields() {
429429
Field {
430430
identifier: Some("b4"), ...
431431
type_: Ok(MappedType {
432-
rs_type: RsType { name: Some("i32"), ... },
432+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
433433
cc_type: CcType { name: Some("int"), ... },
434434
}), ...
435435
offset: 16,
@@ -909,37 +909,36 @@ fn test_type_conversion() -> Result<()> {
909909

910910
assert_eq!(type_mapping["bool"], "bool");
911911

912-
// TODO(b/276790180, b/276931370): use c_char instead.
912+
// TODO(b/276790180, b/276931370): use `::core::ffi::c_char` instead.
913913
if multiplatform_testing::test_platform() == multiplatform_testing::Platform::X86Linux {
914914
assert_eq!(type_mapping["char"], "i8");
915915
} else {
916916
assert_eq!(type_mapping["char"], "u8");
917917
}
918+
assert_eq!(type_mapping["unsigned char"], "::core::ffi::c_uchar");
919+
assert_eq!(type_mapping["signed char"], "::core::ffi::c_schar");
918920

919-
assert_eq!(type_mapping["unsigned char"], "u8");
920-
assert_eq!(type_mapping["signed char"], "i8");
921921
assert_eq!(type_mapping["char16_t"], "u16");
922+
922923
// We cannot map C++ char32_t or wchar_t to Rust char,
923924
// because Rust requires that chars are valid UTF scalar values.
924925
assert_eq!(type_mapping["char32_t"], "u32");
925-
assert_eq!(type_mapping["wchar_t"], "i32");
926926

927-
assert_eq!(type_mapping["short"], "i16");
928-
assert_eq!(type_mapping["int"], "i32");
929-
assert_eq!(type_mapping["long"], "i64");
930-
assert_eq!(type_mapping["long long"], "i64");
927+
// TODO(b/283268558): Per https://en.cppreference.com/w/cpp/language/types#Character_types
928+
// maybe `wchar_t` should translate to`i16` on Windows?
929+
assert_eq!(type_mapping["wchar_t"], "i32");
931930

932-
assert_eq!(type_mapping["unsigned short"], "u16");
933-
assert_eq!(type_mapping["unsigned int"], "u32");
934-
assert_eq!(type_mapping["unsigned long"], "u64");
935-
assert_eq!(type_mapping["unsigned long long"], "u64");
931+
assert_eq!(type_mapping["short"], "::core::ffi::c_short");
932+
assert_eq!(type_mapping["int"], "::core::ffi::c_int");
933+
assert_eq!(type_mapping["long"], "::core::ffi::c_long");
934+
assert_eq!(type_mapping["long long"], "::core::ffi::c_longlong");
936935

937-
assert_eq!(type_mapping["short"], "i16");
938-
assert_eq!(type_mapping["int"], "i32");
939-
assert_eq!(type_mapping["long"], "i64");
940-
assert_eq!(type_mapping["long long"], "i64");
936+
assert_eq!(type_mapping["unsigned short"], "::core::ffi::c_ushort");
937+
assert_eq!(type_mapping["unsigned int"], "::core::ffi::c_uint");
938+
assert_eq!(type_mapping["unsigned long"], "::core::ffi::c_ulong");
939+
assert_eq!(type_mapping["unsigned long long"], "::core::ffi::c_ulonglong");
941940

942-
/* TOOD(b/275876867): Reenable assertions below after fix the `#include` problem.
941+
/* TOOD(b/275876867): Reenable assertions below after fixing the `#include` problem.
943942
assert_eq!(type_mapping["int8_t"], "i8");
944943
assert_eq!(type_mapping["int16_t"], "i16");
945944
assert_eq!(type_mapping["int32_t"], "i32");
@@ -989,7 +988,7 @@ fn test_typedef() -> Result<()> {
989988
let int = quote! {
990989
MappedType {
991990
rs_type: RsType {
992-
name: Some("i32"),
991+
name: Some("::core::ffi::c_int"),
993992
lifetime_args: [],
994993
type_args: [],
995994
decl_id: None,
@@ -1117,7 +1116,7 @@ fn test_typedef_of_full_template_specialization() -> Result<()> {
11171116
identifier: Some("value"), ...
11181117
doc_comment: Some("Doc comment of `value` field."), ...
11191118
type_: Ok(MappedType {
1120-
rs_type: RsType { name: Some("i32"), ... },
1119+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
11211120
cc_type: CcType { name: Some("int"), ... },
11221121
}),
11231122
access: Public,
@@ -1226,7 +1225,7 @@ fn test_typedef_for_explicit_template_specialization() -> Result<()> {
12261225
identifier: Some("value"), ...
12271226
doc_comment: Some("Doc comment of the `value` field specialization for T=int."), ...
12281227
type_: Ok(MappedType {
1229-
rs_type: RsType { name: Some("i32"), ... },
1228+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
12301229
cc_type: CcType { name: Some("int"), ... },
12311230
}),
12321231
access: Public,
@@ -1503,14 +1502,14 @@ fn test_subst_template_type_parm_pack_type() -> Result<()> {
15031502
params: [
15041503
FuncParam {
15051504
type_: MappedType {
1506-
rs_type: RsType { name: Some("i32"), ... },
1505+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
15071506
cc_type: CcType { name: Some("int"), ... },
15081507
},
15091508
identifier: "__my_args_0",
15101509
},
15111510
FuncParam {
15121511
type_: MappedType {
1513-
rs_type: RsType { name: Some("i32"), ... },
1512+
rs_type: RsType { name: Some("::core::ffi::c_int"), ... },
15141513
cc_type: CcType { name: Some("int"), ... },
15151514
},
15161515
identifier: "__my_args_1",
@@ -1759,7 +1758,7 @@ fn test_template_with_decltype_and_with_auto() -> Result<()> {
17591758
Func {
17601759
name: "TemplatedAdd", ...
17611760
return_type: MappedType {
1762-
rs_type: RsType { name: Some("i64"), ... },
1761+
rs_type: RsType { name: Some("::core::ffi::c_longlong"), ... },
17631762
cc_type: CcType { name: Some("long long"), ... },
17641763
}, ...
17651764
}
@@ -1798,7 +1797,7 @@ fn test_subst_template_type_parm_type_vs_const_when_non_const_template_param() -
17981797
return_type: MappedType {
17991798
rs_type: RsType {
18001799
name: Some("&"), ...
1801-
type_args: [RsType { name: Some("i32"), ... }], ...
1800+
type_args: [RsType { name: Some("::core::ffi::c_int"), ... }], ...
18021801
},
18031802
cc_type: CcType {
18041803
name: Some("&"),
@@ -1820,7 +1819,7 @@ fn test_subst_template_type_parm_type_vs_const_when_non_const_template_param() -
18201819
return_type: MappedType {
18211820
rs_type: RsType {
18221821
name: Some("&mut"), ...
1823-
type_args: [RsType { name: Some("i32"), ... }], ...
1822+
type_args: [RsType { name: Some("::core::ffi::c_int"), ... }], ...
18241823
},
18251824
cc_type: CcType {
18261825
name: Some("&"),
@@ -1867,7 +1866,7 @@ fn test_subst_template_type_parm_type_vs_const_when_const_template_param() -> Re
18671866
return_type: MappedType {
18681867
rs_type: RsType {
18691868
name: Some("&"), ...
1870-
type_args: [RsType { name: Some("i32"), ... }], ...
1869+
type_args: [RsType { name: Some("::core::ffi::c_int"), ... }], ...
18711870
},
18721871
cc_type: CcType {
18731872
name: Some("&"),
@@ -1889,7 +1888,7 @@ fn test_subst_template_type_parm_type_vs_const_when_const_template_param() -> Re
18891888
return_type: MappedType {
18901889
rs_type: RsType {
18911890
name: Some("&"), ...
1892-
type_args: [RsType { name: Some("i32"), ... }], ...
1891+
type_args: [RsType { name: Some("::core::ffi::c_int"), ... }], ...
18931892
},
18941893
cc_type: CcType {
18951894
name: Some("&"),
@@ -2528,7 +2527,7 @@ fn test_struct() {
25282527
Field {
25292528
identifier: Some("first_field"), ...
25302529
type_: Ok(MappedType {
2531-
rs_type : RsType { name : Some ("i32"), ...},
2530+
rs_type : RsType { name : Some("::core::ffi::c_int"), ...},
25322531
cc_type : CcType { name : Some ("int"), ...},
25332532
}), ...
25342533
offset: 0, ...
@@ -2538,7 +2537,7 @@ fn test_struct() {
25382537
Field {
25392538
identifier: Some("second_field"), ...
25402539
type_: Ok(MappedType {
2541-
rs_type : RsType { name : Some ("i32"), ...},
2540+
rs_type : RsType { name : Some("::core::ffi::c_int"), ...},
25422541
cc_type : CcType { name : Some ("int"), ...},
25432542
}), ...
25442543
offset: 32, ...
@@ -2631,7 +2630,7 @@ fn test_union() {
26312630
Field {
26322631
identifier: Some("first_field"), ...
26332632
type_: Ok(MappedType {
2634-
rs_type : RsType { name : Some ("i32"), ...},
2633+
rs_type : RsType { name : Some("::core::ffi::c_int"), ...},
26352634
cc_type : CcType { name : Some ("int"), ...},
26362635
}), ...
26372636
offset: 0, ...
@@ -2641,7 +2640,7 @@ fn test_union() {
26412640
Field {
26422641
identifier: Some("second_field"), ...
26432642
type_: Ok(MappedType {
2644-
rs_type : RsType { name : Some ("i32"), ...},
2643+
rs_type : RsType { name : Some("::core::ffi::c_int"), ...},
26452644
cc_type : CcType { name : Some ("int"), ...},
26462645
}), ...
26472646
offset: 0, ...

0 commit comments

Comments
 (0)