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

Wrong binding for `static constexpr` with clang v14 and newer

Open hannometer opened this issue 2 years ago • 0 comments

The generated bindings for some C++ constants (static constexpr) with newer clang versions (v14 and onwards) result in a linked static value, instead of a const value. For older versions (v11, v12, v13) it works as expected.

Test setup:

  • Ubuntu 22.04
  • clang versions 11 to 15 available in the apt repositories
  • bindgen v0.68.1
  • rust v1.65

Input C/C++ Header

// This is more-or-less how it's done in <cstdint>
typedef unsigned int uint32_t;
namespace std {
     using ::uint32_t;
 }

namespace foo {
    using uint32_t = std::uint32_t;
    static constexpr uint32_t MY_CONST_VALUE = 200;
}

This seems to be the minimum amount of typedefs needed to reproduce the issue. For example, with static constexpr std::uint32_t MY_CONST_VALUE = 200; or removing the using uint32_t = std::uint32_t; line, it seems to work correctly again - but since in my project the code is inside a provided lib header, I cannot work around it.

Bindgen Invocation

    let bindings = bindgen::Builder::default()
        .header("header.h")
        .clang_arg("--std=c++11")
        .clang_arg("-x")
        .clang_arg("c++")
        .allowlist_item(".*_VALUE")
        .enable_cxx_namespaces()
        .generate()
        .expect("Unable to generate bindings");

Actual Results

With clang >v14 (I tested with clang v14 and v15), this is the result:

/* automatically generated by rust-bindgen 0.68.1 */

#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[allow(unused_imports)]
    use self::super::root;
    pub mod foo {
        #[allow(unused_imports)]
        use self::super::super::root;
        extern "C" {
            #[link_name = "\u{1}_ZN3fooL14MY_CONST_VALUEE"]
            pub static MY_CONST_VALUE: u32;
        }
    }
}

Expected Results

I'd expect the static constexpr to result in a pub const in the bindings. And this is the result with clang v11, v12 and v13:

/* automatically generated by rust-bindgen 0.68.1 */

#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[allow(unused_imports)]
    use self::super::root;
    pub mod foo {
        #[allow(unused_imports)]
        use self::super::super::root;
        pub const MY_CONST_VALUE: u32 = 200;
    }
}

hannometer avatar Sep 13 '23 09:09 hannometer