From 89af914f0ae4aa66e255d4b21fc422fe1cea2754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 7 Jun 2022 16:35:46 +0200 Subject: [PATCH 1/3] bitflags: Make more operations constexpr. --- src/bindgen/ir/structure.rs | 26 ++++++++++++++------ tests/expectations/associated_in_body.cpp | 10 ++++---- tests/expectations/bitflags.cpp | 30 +++++++++++------------ 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index be199739..3db3e7a4 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -205,6 +205,7 @@ impl Struct { fn emit_bitflags_binop( &self, + constexpr_prefix: &str, operator: char, other: &str, out: &mut SourceWriter, @@ -212,7 +213,8 @@ impl Struct { out.new_line(); write!( out, - "{} operator{}(const {}& {}) const", + "{}{} operator{}(const {}& {}) const", + constexpr_prefix, self.export_name(), operator, self.export_name(), @@ -531,21 +533,31 @@ impl Source for Struct { wrote_start_newline = true; out.new_line(); } + let constexpr_prefix = if config.constant.allow_constexpr { + "constexpr " + } else { + "" + }; + out.new_line(); - write!(out, "explicit operator bool() const"); + write!(out, "{}explicit operator bool() const", constexpr_prefix); out.open_brace(); write!(out, "return !!bits;"); out.close_brace(false); out.new_line(); - write!(out, "{} operator~() const", self.export_name()); + write!( + out, + "{}{} operator~() const", + constexpr_prefix, + self.export_name() + ); out.open_brace(); write!(out, "return {{static_cast(~bits)}};"); out.close_brace(false); - - self.emit_bitflags_binop('|', &other, out); - self.emit_bitflags_binop('&', &other, out); - self.emit_bitflags_binop('^', &other, out); + self.emit_bitflags_binop(constexpr_prefix, '|', &other, out); + self.emit_bitflags_binop(constexpr_prefix, '&', &other, out); + self.emit_bitflags_binop(constexpr_prefix, '^', &other, out); } // Generate a serializer function that allows dumping this struct diff --git a/tests/expectations/associated_in_body.cpp b/tests/expectations/associated_in_body.cpp index 14c59e39..d1319efb 100644 --- a/tests/expectations/associated_in_body.cpp +++ b/tests/expectations/associated_in_body.cpp @@ -10,27 +10,27 @@ struct StyleAlignFlags { uint8_t bits; - explicit operator bool() const { + constexpr explicit operator bool() const { return !!bits; } - StyleAlignFlags operator~() const { + constexpr StyleAlignFlags operator~() const { return {static_cast(~bits)}; } - StyleAlignFlags operator|(const StyleAlignFlags& other) const { + constexpr StyleAlignFlags operator|(const StyleAlignFlags& other) const { return {static_cast(this->bits | other.bits)}; } StyleAlignFlags& operator|=(const StyleAlignFlags& other) { *this = (*this | other); return *this; } - StyleAlignFlags operator&(const StyleAlignFlags& other) const { + constexpr StyleAlignFlags operator&(const StyleAlignFlags& other) const { return {static_cast(this->bits & other.bits)}; } StyleAlignFlags& operator&=(const StyleAlignFlags& other) { *this = (*this & other); return *this; } - StyleAlignFlags operator^(const StyleAlignFlags& other) const { + constexpr StyleAlignFlags operator^(const StyleAlignFlags& other) const { return {static_cast(this->bits ^ other.bits)}; } StyleAlignFlags& operator^=(const StyleAlignFlags& other) { diff --git a/tests/expectations/bitflags.cpp b/tests/expectations/bitflags.cpp index c7710061..49dadbad 100644 --- a/tests/expectations/bitflags.cpp +++ b/tests/expectations/bitflags.cpp @@ -10,27 +10,27 @@ struct AlignFlags { uint8_t bits; - explicit operator bool() const { + constexpr explicit operator bool() const { return !!bits; } - AlignFlags operator~() const { + constexpr AlignFlags operator~() const { return {static_cast(~bits)}; } - AlignFlags operator|(const AlignFlags& other) const { + constexpr AlignFlags operator|(const AlignFlags& other) const { return {static_cast(this->bits | other.bits)}; } AlignFlags& operator|=(const AlignFlags& other) { *this = (*this | other); return *this; } - AlignFlags operator&(const AlignFlags& other) const { + constexpr AlignFlags operator&(const AlignFlags& other) const { return {static_cast(this->bits & other.bits)}; } AlignFlags& operator&=(const AlignFlags& other) { *this = (*this & other); return *this; } - AlignFlags operator^(const AlignFlags& other) const { + constexpr AlignFlags operator^(const AlignFlags& other) const { return {static_cast(this->bits ^ other.bits)}; } AlignFlags& operator^=(const AlignFlags& other) { @@ -55,27 +55,27 @@ constexpr static const AlignFlags AlignFlags_MIXED_SELF = AlignFlags{ /* .bits = struct DebugFlags { uint32_t bits; - explicit operator bool() const { + constexpr explicit operator bool() const { return !!bits; } - DebugFlags operator~() const { + constexpr DebugFlags operator~() const { return {static_cast(~bits)}; } - DebugFlags operator|(const DebugFlags& other) const { + constexpr DebugFlags operator|(const DebugFlags& other) const { return {static_cast(this->bits | other.bits)}; } DebugFlags& operator|=(const DebugFlags& other) { *this = (*this | other); return *this; } - DebugFlags operator&(const DebugFlags& other) const { + constexpr DebugFlags operator&(const DebugFlags& other) const { return {static_cast(this->bits & other.bits)}; } DebugFlags& operator&=(const DebugFlags& other) { *this = (*this & other); return *this; } - DebugFlags operator^(const DebugFlags& other) const { + constexpr DebugFlags operator^(const DebugFlags& other) const { return {static_cast(this->bits ^ other.bits)}; } DebugFlags& operator^=(const DebugFlags& other) { @@ -89,27 +89,27 @@ constexpr static const DebugFlags DebugFlags_BIGGEST_ALLOWED = DebugFlags{ /* .b struct LargeFlags { uint64_t bits; - explicit operator bool() const { + constexpr explicit operator bool() const { return !!bits; } - LargeFlags operator~() const { + constexpr LargeFlags operator~() const { return {static_cast(~bits)}; } - LargeFlags operator|(const LargeFlags& other) const { + constexpr LargeFlags operator|(const LargeFlags& other) const { return {static_cast(this->bits | other.bits)}; } LargeFlags& operator|=(const LargeFlags& other) { *this = (*this | other); return *this; } - LargeFlags operator&(const LargeFlags& other) const { + constexpr LargeFlags operator&(const LargeFlags& other) const { return {static_cast(this->bits & other.bits)}; } LargeFlags& operator&=(const LargeFlags& other) { *this = (*this & other); return *this; } - LargeFlags operator^(const LargeFlags& other) const { + constexpr LargeFlags operator^(const LargeFlags& other) const { return {static_cast(this->bits ^ other.bits)}; } LargeFlags& operator^=(const LargeFlags& other) { From 72f46bbc5612443d4e2f101dc791cbcb6b04153a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 7 Jun 2022 16:53:58 +0200 Subject: [PATCH 2/3] constant: Add support for unary negation. --- src/bindgen/ir/constant.rs | 7 +++++++ tests/expectations/bitflags.both.c | 1 + tests/expectations/bitflags.both.compat.c | 1 + tests/expectations/bitflags.c | 1 + tests/expectations/bitflags.compat.c | 1 + tests/expectations/bitflags.cpp | 1 + tests/expectations/bitflags.pyx | 1 + tests/expectations/bitflags.tag.c | 1 + tests/expectations/bitflags.tag.compat.c | 1 + tests/expectations/bitflags.tag.pyx | 1 + tests/rust/bitflags.rs | 1 + 11 files changed, 17 insertions(+) diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index c181c346..42182ab9 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -417,6 +417,13 @@ impl Literal { syn::Expr::Unary(syn::ExprUnary { ref op, ref expr, .. }) => match *op { + UnOp::Not(_) => { + let val = Self::load(expr)?; + Ok(Literal::PostfixUnaryOp { + op: "~", + value: Box::new(val), + }) + } UnOp::Neg(_) => { let val = Self::load(expr)?; Ok(Literal::PostfixUnaryOp { diff --git a/tests/expectations/bitflags.both.c b/tests/expectations/bitflags.both.c index 6003cfda..b5cb6a7c 100644 --- a/tests/expectations/bitflags.both.c +++ b/tests/expectations/bitflags.both.c @@ -50,5 +50,6 @@ typedef struct LargeFlags { * Flag with a very large shift that usually would be narrowed. */ #define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } +#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits } void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags); diff --git a/tests/expectations/bitflags.both.compat.c b/tests/expectations/bitflags.both.compat.c index e5b560bb..35726624 100644 --- a/tests/expectations/bitflags.both.compat.c +++ b/tests/expectations/bitflags.both.compat.c @@ -50,6 +50,7 @@ typedef struct LargeFlags { * Flag with a very large shift that usually would be narrowed. */ #define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } +#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits } #ifdef __cplusplus extern "C" { diff --git a/tests/expectations/bitflags.c b/tests/expectations/bitflags.c index f8148db9..9af76af4 100644 --- a/tests/expectations/bitflags.c +++ b/tests/expectations/bitflags.c @@ -50,5 +50,6 @@ typedef struct { * Flag with a very large shift that usually would be narrowed. */ #define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } +#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits } void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags); diff --git a/tests/expectations/bitflags.compat.c b/tests/expectations/bitflags.compat.c index 84b38e35..863de08b 100644 --- a/tests/expectations/bitflags.compat.c +++ b/tests/expectations/bitflags.compat.c @@ -50,6 +50,7 @@ typedef struct { * Flag with a very large shift that usually would be narrowed. */ #define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } +#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits } #ifdef __cplusplus extern "C" { diff --git a/tests/expectations/bitflags.cpp b/tests/expectations/bitflags.cpp index 49dadbad..9df48b69 100644 --- a/tests/expectations/bitflags.cpp +++ b/tests/expectations/bitflags.cpp @@ -119,6 +119,7 @@ struct LargeFlags { }; /// Flag with a very large shift that usually would be narrowed. constexpr static const LargeFlags LargeFlags_LARGE_SHIFT = LargeFlags{ /* .bits = */ (uint64_t)(1ull << 44) }; +constexpr static const LargeFlags LargeFlags_INVERTED = LargeFlags{ /* .bits = */ (uint64_t)~(LargeFlags_LARGE_SHIFT).bits }; extern "C" { diff --git a/tests/expectations/bitflags.pyx b/tests/expectations/bitflags.pyx index 68639f8b..e3d10401 100644 --- a/tests/expectations/bitflags.pyx +++ b/tests/expectations/bitflags.pyx @@ -34,5 +34,6 @@ cdef extern from *: uint64_t bits; # Flag with a very large shift that usually would be narrowed. const LargeFlags LargeFlags_LARGE_SHIFT # = { (1ull << 44) } + const LargeFlags LargeFlags_INVERTED # = { ~(LargeFlags_LARGE_SHIFT).bits } void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags); diff --git a/tests/expectations/bitflags.tag.c b/tests/expectations/bitflags.tag.c index 0492d120..c4be368d 100644 --- a/tests/expectations/bitflags.tag.c +++ b/tests/expectations/bitflags.tag.c @@ -50,5 +50,6 @@ struct LargeFlags { * Flag with a very large shift that usually would be narrowed. */ #define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } +#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits } void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags); diff --git a/tests/expectations/bitflags.tag.compat.c b/tests/expectations/bitflags.tag.compat.c index 52c1e8de..d12ba40f 100644 --- a/tests/expectations/bitflags.tag.compat.c +++ b/tests/expectations/bitflags.tag.compat.c @@ -50,6 +50,7 @@ struct LargeFlags { * Flag with a very large shift that usually would be narrowed. */ #define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } +#define LargeFlags_INVERTED (LargeFlags){ .bits = (uint64_t)~(LargeFlags_LARGE_SHIFT).bits } #ifdef __cplusplus extern "C" { diff --git a/tests/expectations/bitflags.tag.pyx b/tests/expectations/bitflags.tag.pyx index ba2d37f7..d5f2df6d 100644 --- a/tests/expectations/bitflags.tag.pyx +++ b/tests/expectations/bitflags.tag.pyx @@ -34,5 +34,6 @@ cdef extern from *: uint64_t bits; # Flag with a very large shift that usually would be narrowed. const LargeFlags LargeFlags_LARGE_SHIFT # = { (1ull << 44) } + const LargeFlags LargeFlags_INVERTED # = { ~(LargeFlags_LARGE_SHIFT).bits } void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags); diff --git a/tests/rust/bitflags.rs b/tests/rust/bitflags.rs index 4d05cb08..7e78bd81 100644 --- a/tests/rust/bitflags.rs +++ b/tests/rust/bitflags.rs @@ -34,6 +34,7 @@ bitflags! { pub struct LargeFlags: u64 { /// Flag with a very large shift that usually would be narrowed. const LARGE_SHIFT = 1u64 << 44; + const INVERTED = !Self::LARGE_SHIFT.bits; } } From 78bb3b93ae87cb62d33775fa6cd4a938ad6c3f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 7 Jun 2022 18:27:30 +0200 Subject: [PATCH 3/3] Version bump. --- CHANGES | 5 +++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 2cba7f71..2579deb9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +## 0.24.1 + + * Add support for unary negation (#765). + * Make more bitfield operators constexpr (#765). + ## 0.24.0 * Basic const generic support (#759, #760 #762). diff --git a/Cargo.lock b/Cargo.lock index 7a6e0779..3593ee5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cbindgen" -version = "0.24.0" +version = "0.24.1" dependencies = [ "clap", "heck", diff --git a/Cargo.toml b/Cargo.toml index 4174d4ba..f89c4f6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cbindgen" -version = "0.24.0" +version = "0.24.1" authors = [ "Emilio Cobos Álvarez ", "Jeff Muizelaar ",