Skip to content

Commit 49790f1

Browse files
committed
Keep radix for integer literals in generated bindings
1 parent bd011d4 commit 49790f1

File tree

7 files changed

+638
-38
lines changed

7 files changed

+638
-38
lines changed

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

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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;

bindgen/clang.rs

Lines changed: 42 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,47 @@ 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 corresponding to the cursor.
979+
///
980+
/// Returns `None` if unable to infer a base.
981+
pub(crate) fn get_literal_radix(&self) -> Option<LiteralRadix> {
982+
self.tokens().iter().find_map(|token| {
983+
if token.kind == CXToken_Literal {
984+
LiteralRadix::from_integer_literal_token(token.spelling())
985+
} else {
986+
None
987+
}
988+
})
989+
}
990+
991+
/// Obtain the number base (radix) of an integer literal definition corresponding to the cursor,
992+
/// ensuring that the radix is from the literal following a given identifier in the list of
993+
/// tokens.
994+
///
995+
/// Returns `None` if unable to infer a base.
996+
pub(crate) fn get_literal_radix_of_identifier(
997+
&self,
998+
identifier: &str,
999+
) -> Option<LiteralRadix> {
1000+
self.tokens()
1001+
.iter()
1002+
.scan(false, |identifier_found, token| {
1003+
if token.kind == CXToken_Identifier &&
1004+
token.spelling() == identifier.as_bytes()
1005+
{
1006+
*identifier_found = true;
1007+
}
1008+
Some((*identifier_found, token))
1009+
})
1010+
.find_map(|(identifier_found, token)| {
1011+
if identifier_found && token.kind == CXToken_Literal {
1012+
LiteralRadix::from_integer_literal_token(token.spelling())
1013+
} else {
1014+
None
1015+
}
1016+
})
1017+
}
9761018
}
9771019

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

0 commit comments

Comments
 (0)