Skip to content

Commit f35d69d

Browse files
committed
Keep radix for integer literals in generated bindings
1 parent 5f7aa4b commit f35d69d

File tree

7 files changed

+650
-38
lines changed

7 files changed

+650
-38
lines changed

bindgen-tests/tests/expectations/tests/different_radix_literals.rs

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// bindgen-flags: -- -std=c++14
2+
// (C23 is not available in clang 9.0, but C++14 supports the same literals)
3+
4+
// Binary integer literals (C23) - 0b10 is 2 in decimal
5+
6+
#define DEFINE_BIN_LITERAL 0b10
7+
#define DEFINE_NEG_BIN_LITERAL -0b10
8+
const int CONST_INT_BIN_LITERAL = 0b10;
9+
const int CONST_INT_NEG_BIN_LITERAL = -0b10;
10+
11+
// Octal integer literals - 010 is 8 in decimal
12+
13+
#define DEFINE_OCT_LITERAL 010
14+
#define DEFINE_NEG_OCT_LITERAL -010
15+
const int CONST_INT_OCT_LITERAL = 010;
16+
const int CONST_INT_NEG_OCT_LITERAL = -010;
17+
18+
// Hexadecimal integer literals - 0x10 is 16 in decimal
19+
20+
#define DEFINE_HEX_LITERAL 0x10
21+
#define DEFINE_NEG_HEX_LITERAL -0x10
22+
const int CONST_INT_HEX_LITERAL = 0x10;
23+
const int CONST_INT_NEG_HEX_LITERAL = -0x10;
24+
25+
// Default decimal integer literals - 10 is 10 in decimal
26+
27+
#define DEFINE_DEC_LITERAL 10
28+
#define DEFINE_NEG_DEC_LITERAL -10
29+
const int CONST_INT_DEC_LITERAL = 10;
30+
const int CONST_INT_NEG_DEC_LITERAL = -10;
31+
32+
// Enums with binary, octal, and hexadecimal integer literals
33+
34+
enum MultiRadixLiteral {
35+
ENUM_BIN_LITERAL = 0b10,
36+
ENUM_NEG_BIN_LITERAL = -0b10,
37+
ENUM_OCT_LITERAL = 010,
38+
ENUM_NEG_OCT_LITERAL = -010,
39+
ENUM_HEX_LITERAL = 0x10,
40+
ENUM_NEG_HEX_LITERAL = -0x10,
41+
ENUM_DEC_LITERAL = 10,
42+
ENUM_NEG_DEC_LITERAL = -10,
43+
};
44+
45+
// Edge cases: minimum i64s
46+
47+
const long long MIN_I64_BIN = -0b1000000000000000000000000000000000000000000000000000000000000000;
48+
const long long MIN_I64_OCT = -01000000000000000000000;
49+
const long long MIN_I64_DEC = -9223372036854775808;
50+
const long long MIN_I64_HEX = -0x8000000000000000;
51+
52+
// Big B or big X
53+
54+
const int BIG_B_BIN = 0B1;
55+
const int BIG_X_HEX = 0XF;
56+
57+
// Octal with extra leading zero
58+
59+
const char AGENT = 007;
60+
61+
// C23 and C++14 thousands'/digit separator '
62+
63+
const unsigned long long SEP_BIN = 0b11111111'00000000;
64+
const unsigned long long SEP_OCT = 07777'7777'7777;
65+
const unsigned long long SEP_DEC = 299'792'458;
66+
const unsigned long long SEP_HEX = 0x1111'bbbb'cccc'dddd;
67+
68+
// Multiple declarations
69+
70+
const long BIN_1ST = 0b10101010, OCT_2ND = 0777, DEC_3RD = 1234, HEX_4TH = 0xffff;
71+
72+
// Smaller integer types
73+
74+
const unsigned short USHORT_HEX = 0xFFFF;
75+
const short SHORT_HEX = 0x7FFF;
76+
const unsigned char UCHAR_HEX = 0xFF;
77+
const char CHAR_HEX = 0x7F;

bindgen/clang.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![deny(clippy::missing_docs_in_private_items)]
66

77
use crate::ir::context::BindgenContext;
8+
use crate::ir::var::LiteralRadix;
89
use clang_sys::*;
910
use std::cmp;
1011

@@ -973,6 +974,48 @@ impl Cursor {
973974
pub(crate) fn is_inline_namespace(&self) -> bool {
974975
unsafe { clang_Cursor_isInlineNamespace(self.x) != 0 }
975976
}
977+
978+
/// Obtain the number base (radix) of an integer literal definition
979+
/// corresponding to the cursor.
980+
///
981+
/// Returns `None` if unable to infer a base.
982+
pub(crate) fn get_literal_radix(&self) -> Option<LiteralRadix> {
983+
self.tokens().iter().find_map(|token| {
984+
if token.kind == CXToken_Literal {
985+
LiteralRadix::from_integer_literal_token(token.spelling())
986+
} else {
987+
None
988+
}
989+
})
990+
}
991+
992+
/// Obtain the number base (radix) of an integer literal definition
993+
/// corresponding to the cursor, ensuring that the radix is from the literal
994+
/// following a given identifier in the list of tokens.
995+
///
996+
/// Returns `None` if unable to infer a base.
997+
pub(crate) fn get_literal_radix_of_identifier(
998+
&self,
999+
identifier: &str,
1000+
) -> Option<LiteralRadix> {
1001+
self.tokens()
1002+
.iter()
1003+
.scan(false, |identifier_found, token| {
1004+
if token.kind == CXToken_Identifier &&
1005+
token.spelling() == identifier.as_bytes()
1006+
{
1007+
*identifier_found = true;
1008+
}
1009+
Some((*identifier_found, token))
1010+
})
1011+
.find_map(|(identifier_found, token)| {
1012+
if identifier_found && token.kind == CXToken_Literal {
1013+
LiteralRadix::from_integer_literal_token(token.spelling())
1014+
} else {
1015+
None
1016+
}
1017+
})
1018+
}
9761019
}
9771020

9781021
/// A struct that owns the tokenizer result from a given cursor.

0 commit comments

Comments
 (0)