rust-bindgen
rust-bindgen copied to clipboard
Constants like `UINT_MAX` not recognized
Input C/C++ Header
#include <limits.h>
#define A 42
#define B UINT_MAX
static const unsigned int C = UINT_MAX;
Bindgen Invocation
Both bindgen defines.h and a minimal builder().header("defines.h").generate()?.write_to_file(…) create the observed behavior.
Actual Results
pub const A: u32 = 42;
extern "C" {
#[link_name = "\u{1}C"]
pub static mut C: ::std::os::raw::c_uint;
}
The __bindgen.i output from bindgen --dump-preprocessed-output ./defines.h contains a line
static const unsigned int C = (2147483647 *2U +1U);
which shows that to Clang, UINT_MAX is, with limits.h in place, valid.
Expected Results
B should be recognized as a compiler constant and expanded.
I did not manage to follow Clang's reasoning to the end, but when I looked through the ( kind = macro_definition debug output, not only did the B macro show up as invalid, but there was also a
(
kind = macro definition
spelling = "UINT_MAX"
location = /usr/lib/llvm-8/lib/clang/8.0.1/include/limits.h:72:9
is-definition? false
is-declaration? false
is-inlined-function? false
usr = "c:@macro@UINT_MAX"
type.kind = Invalid
)
section, following which I found UINT_MAX defined as (__INT_MAX__ *2U +1U), where there is no macro for __INT_MAX__ visible in the debug output -- so that's probably a compiler built-in constant. One way to resolve that might be to inject the compiler constants into the constant expression evaluation process that makes values out of nested defines. (Which otherwise work: a #define TWICE_A (A * 2) expands to 84 in bindgen).
Sorry for the delay here. We could probably define a few standard macros in BindgenContext::parsed_macros, if we wanted to fix this.
I just hit the same problem on macOS with limits.h:
Minimal input:
#include <limits.h>
const unsigned long VAR = ULONG_MAX;
Command:
bindgen minimal.h --allowlist-var ULONG_MAX --allowlist-var VAR
Output:
/* automatically generated by rust-bindgen 0.60.1 */
pub const ULONG_MAX: i32 = -1;
extern "C" {
pub static VAR: ::std::os::raw::c_ulong;
}
One potential solution would be to expose getIntWidth and equivalents for other types (short, long, etc.) in the clang-sys crate, pull that into bindgen, and insert __INT_MAX__ etc. into BindgenContext::parsed_macros for a given target. Happy to give that a stab if it sounds like the right direction.