rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

Constants like `UINT_MAX` not recognized

Open chrysn opened this issue 6 years ago • 5 comments

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).

chrysn avatar Oct 04 '19 06:10 chrysn

Sorry for the delay here. We could probably define a few standard macros in BindgenContext::parsed_macros, if we wanted to fix this.

emilio avatar Oct 14 '19 12:10 emilio

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;
}

reitermarkus avatar Sep 07 '22 22:09 reitermarkus

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.

thedataking avatar Mar 14 '24 04:03 thedataking