rust-lang / rust-lang/rust-bindgen
Wrong binding for `static constexpr` with clang v14 and newer
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
Description
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
aptrepositories - 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;
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal C++ example in header.h and the bindgen::Builder invocation, running it across the reported clang versions 11 through 15. Compare the generated binding for foo::MY_CONST_VALUE; done means newer clang versions produce the expected public Rust const with value 200 rather than a linked static.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- compilers, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100