Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions bindgen-tests/tests/expectations/tests/issue-753.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions bindgen-tests/tests/expectations/tests/issue-923.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bindgen-tests/tests/headers/issue-753.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

#define CONST UINT32_C(5)
#define OTHER_CONST UINT32_C(6)
#define LARGE_CONST UINT32_C(6 << 8)
#define LARGE_CONST (UINT32_C(6) << 8)

#endif
10 changes: 10 additions & 0 deletions bindgen-tests/tests/headers/issue-923.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// bindgen-flags: --macro-const-use-ctypes

#ifndef ISSUE_923_H
#define ISSUE_923_H

#define ULONG_ZERO 0UL
#define ULONGLONG_ZERO 0ULL
#define CHAR_ZERO ((char)'\0')

#endif
13 changes: 13 additions & 0 deletions bindgen-tests/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,17 @@ fn create_bindgen_builder(header: &Path) -> Result<BuilderState, Error> {

let source = fs::File::open(header)?;
let reader = BufReader::new(source);
// Safety: assume that headers in our test suite have distinct names.
let basename = header.file_name().unwrap();
let per_test_folder = format!(
"./{}",
basename
.to_str()
.unwrap()
.replace('_', "__")
.replace('.', "_")
);
fs::create_dir_all(&per_test_folder)?;

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

let args = prepend.iter().map(ToString::to_string).chain(flags);
Expand Down
26 changes: 25 additions & 1 deletion bindgen/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2329,7 +2329,8 @@ impl EvalResult {
})
}

fn kind(&self) -> CXEvalResultKind {
/// Return the kind of the evaluation result.
pub(crate) fn kind(&self) -> CXEvalResultKind {
unsafe { clang_EvalResult_getKind(self.x) }
}

Expand Down Expand Up @@ -2370,6 +2371,29 @@ impl EvalResult {
Some(value as i64)
}

/// Try to resolve the result into a string literal.
/// This returns `None` if the result is not immediately a string literal.
pub(crate) fn as_str_literal(&self) -> Option<Vec<u8>> {
if !matches!(
self.kind(),
CXEval_StrLiteral | CXEval_CFStr | CXEval_ObjCStrLiteral,
) {
return None;
}
// Safety: we are only copying the content, not assuming a borrow.
// TODO(@dingxiangfei2009): LLVM Libclang does not return the true size
// of a string literal, which could be truncated due to a null character
// '\0' in the middle.
let value =
unsafe { CStr::from_ptr(clang_EvalResult_getAsStr(self.x)) };
Some(value.to_bytes().into())
}

/// Return the type of the value.
pub(crate) fn value_type(&self) -> Type {
self.ty
}

/// Evaluates the expression as a literal string, that may or may not be
/// valid utf-8.
pub(crate) fn as_literal_string(&self) -> Option<Vec<u8>> {
Expand Down
15 changes: 9 additions & 6 deletions bindgen/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ pub(crate) struct BindgenContext {
/// hard errors while parsing duplicated macros, as well to allow macro
/// expression parsing.
///
/// This needs to be an `std::HashMap` because the `cexpr` API requires it.
/// This needs to be an `std::HashMap` because the [`cexpr`] API requires it.
parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,

/// A map with all include locations.
Expand Down Expand Up @@ -2055,10 +2055,12 @@ If you encounter an error missing from this list, please file an issue or a PR!"
let mut header_names_to_compile = Vec::new();
let mut header_paths = Vec::new();
let mut header_includes = Vec::new();
let single_header = self.options().input_headers.last().cloned()?;
for input_header in &self.options.input_headers
[..self.options.input_headers.len() - 1]
{
let [input_headers @ .., single_header] =
&self.options().input_headers[..]
else {
return None;
};
for input_header in input_headers {
let path = Path::new(input_header.as_ref());
if let Some(header_path) = path.parent() {
if header_path == Path::new("") {
Expand Down Expand Up @@ -2095,7 +2097,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
let mut tu = clang::TranslationUnit::parse(
&index,
&single_header,
single_header,
&c_args,
&[],
clang_sys::CXTranslationUnit_ForSerialization,
Expand Down Expand Up @@ -2129,6 +2131,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}

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