Skip to content

Commit da9dfbe

Browse files
Allow macro definitions to pick up precise C types
Upon activating the `--macro-const-use-ctypes` flag, `bindgen` should generate bindings with precise type resolution to the exact C types. This flag implies `--clang-macro-fallback` as its pre-requisite. Signed-off-by: Xiangfei Ding <[email protected]>
1 parent 5813198 commit da9dfbe

File tree

11 files changed

+344
-47
lines changed

11 files changed

+344
-47
lines changed

bindgen-tests/tests/expectations/tests/issue-753.rs

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/issue-923.rs

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/test_macro_fallback_non_system_dir.rs

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/headers/issue-753.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
#define CONST UINT32_C(5)
99
#define OTHER_CONST UINT32_C(6)
10-
#define LARGE_CONST UINT32_C(6 << 8)
10+
#define LARGE_CONST (UINT32_C(6) << 8)
1111

1212
#endif
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// bindgen-flags: --macro-const-use-ctypes
2+
3+
#ifndef ISSUE_923_H
4+
#define ISSUE_923_H
5+
6+
#define ULONG_ZERO 0UL
7+
#define ULONGLONG_ZERO 0ULL
8+
#define CHAR_ZERO ((char)'\0')
9+
10+
#endif

bindgen-tests/tests/tests.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,17 @@ fn create_bindgen_builder(header: &Path) -> Result<BuilderState, Error> {
269269

270270
let source = fs::File::open(header)?;
271271
let reader = BufReader::new(source);
272+
// Safety: assume that headers in our test suite have distinct names.
273+
let basename = header.file_name().unwrap();
274+
let per_test_folder = format!(
275+
"./{}",
276+
basename
277+
.to_str()
278+
.unwrap()
279+
.replace("_", "__")
280+
.replace(".", "_")
281+
);
282+
fs::create_dir_all(&per_test_folder)?;
272283

273284
// Scoop up bindgen-flags from test header
274285
let mut flags = Vec::with_capacity(2);
@@ -334,6 +345,8 @@ fn create_bindgen_builder(header: &Path) -> Result<BuilderState, Error> {
334345
"#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]",
335346
"--raw-line",
336347
"",
348+
"--clang-macro-fallback-build-dir",
349+
&per_test_folder,
337350
];
338351

339352
let args = prepend.iter().map(ToString::to_string).chain(flags);

bindgen/clang.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2329,7 +2329,8 @@ impl EvalResult {
23292329
})
23302330
}
23312331

2332-
fn kind(&self) -> CXEvalResultKind {
2332+
/// Return the kind of the evaluation result.
2333+
pub(crate) fn kind(&self) -> CXEvalResultKind {
23332334
unsafe { clang_EvalResult_getKind(self.x) }
23342335
}
23352336

@@ -2370,6 +2371,29 @@ impl EvalResult {
23702371
Some(value as i64)
23712372
}
23722373

2374+
/// Try to resolve the result into a string literal.
2375+
/// This returns `None` if the result is not immediately a string literal.
2376+
pub(crate) fn as_str_literal(&self) -> Option<Vec<u8>> {
2377+
if !matches!(
2378+
self.kind(),
2379+
CXEval_StrLiteral | CXEval_CFStr | CXEval_ObjCStrLiteral,
2380+
) {
2381+
return None;
2382+
}
2383+
// Safety: we are only copying the content, not assuming a borrow.
2384+
// TODO(@dingxiangfei2009): LLVM Libclang does not return the true size
2385+
// of a string literal, which could be truncated due to a null character
2386+
// '\0' in the middle.
2387+
let value =
2388+
unsafe { CStr::from_ptr(clang_EvalResult_getAsStr(self.x)) };
2389+
Some(value.to_bytes().into())
2390+
}
2391+
2392+
/// Return the type of the value.
2393+
pub(crate) fn value_type(&self) -> Type {
2394+
self.ty
2395+
}
2396+
23732397
/// Evaluates the expression as a literal string, that may or may not be
23742398
/// valid utf-8.
23752399
pub(crate) fn as_literal_string(&self) -> Option<Vec<u8>> {

bindgen/ir/context.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ pub(crate) struct BindgenContext {
353353
/// hard errors while parsing duplicated macros, as well to allow macro
354354
/// expression parsing.
355355
///
356-
/// This needs to be an `std::HashMap` because the `cexpr` API requires it.
356+
/// This needs to be an `std::HashMap` because the [`cexpr`] API requires it.
357357
parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
358358

359359
/// A map with all include locations.
@@ -2055,10 +2055,12 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20552055
let mut header_names_to_compile = Vec::new();
20562056
let mut header_paths = Vec::new();
20572057
let mut header_includes = Vec::new();
2058-
let single_header = self.options().input_headers.last().cloned()?;
2059-
for input_header in &self.options.input_headers
2060-
[..self.options.input_headers.len() - 1]
2061-
{
2058+
let [input_headers @ .., single_header] =
2059+
&self.options().input_headers[..]
2060+
else {
2061+
return None;
2062+
};
2063+
for input_header in input_headers {
20622064
let path = Path::new(input_header.as_ref());
20632065
if let Some(header_path) = path.parent() {
20642066
if header_path == Path::new("") {
@@ -2095,7 +2097,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20952097
}
20962098
let mut tu = clang::TranslationUnit::parse(
20972099
&index,
2098-
&single_header,
2100+
single_header,
20992101
&c_args,
21002102
&[],
21012103
clang_sys::CXTranslationUnit_ForSerialization,
@@ -2129,6 +2131,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21292131
}
21302132

21312133
/// Get the currently parsed macros.
2134+
/// This map only contains macros accepted by [`cexpr`]
21322135
pub(crate) fn parsed_macros(
21332136
&self,
21342137
) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {

0 commit comments

Comments
 (0)