From 597b033ccf96b884edc5e4e9c1acfa7bfdfbe291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 7 Jun 2022 16:03:55 +0200 Subject: [PATCH] constant: Support suffixes for integers that otherwise would be narrowed. --- src/bindgen/ir/constant.rs | 17 +++++++---- tests/expectations/bitflags.both.c | 10 ++++++- tests/expectations/bitflags.both.compat.c | 10 ++++++- tests/expectations/bitflags.c | 10 ++++++- tests/expectations/bitflags.compat.c | 10 ++++++- tests/expectations/bitflags.cpp | 36 ++++++++++++++++++++++- tests/expectations/bitflags.pyx | 7 ++++- tests/expectations/bitflags.tag.c | 10 ++++++- tests/expectations/bitflags.tag.compat.c | 10 ++++++- tests/expectations/bitflags.tag.pyx | 7 ++++- tests/expectations/constant_big.compat.c | 4 +-- tests/expectations/constant_big.cpp | 4 +-- tests/expectations/constant_big.pyx | 4 +-- tests/rust/bitflags.rs | 11 ++++++- 14 files changed, 129 insertions(+), 21 deletions(-) diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index d1cbcba..c181c34 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -340,11 +340,18 @@ impl Literal { other_code => format!(r"U'\U{:08X}'", other_code), })), syn::Lit::Int(ref value) => { - if value.base10_parse::().is_err() { - Ok(Literal::Expr(format!("{}ULL", value.base10_digits()))) - } else { - Ok(Literal::Expr(value.base10_digits().to_string())) - } + let suffix = match value.suffix() { + "u64" => "ull", + "i64" => "ll", + "u32" => "u", + _ if value.base10_parse::().is_err() => "ull", + _ => "", + }; + Ok(Literal::Expr(format!( + "{}{}", + value.base10_digits(), + suffix + ))) } syn::Lit::Float(ref value) => { Ok(Literal::Expr(value.base10_digits().to_string())) diff --git a/tests/expectations/bitflags.both.c b/tests/expectations/bitflags.both.c index 8428299..6003cfd 100644 --- a/tests/expectations/bitflags.both.c +++ b/tests/expectations/bitflags.both.c @@ -43,4 +43,12 @@ typedef struct DebugFlags { */ #define DebugFlags_BIGGEST_ALLOWED (DebugFlags){ .bits = (uint32_t)(1 << 31) } -void root(struct AlignFlags flags, struct DebugFlags bigger_flags); +typedef struct LargeFlags { + uint64_t bits; +} LargeFlags; +/** + * Flag with a very large shift that usually would be narrowed. + */ +#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } + +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 23b6243..e5b560b 100644 --- a/tests/expectations/bitflags.both.compat.c +++ b/tests/expectations/bitflags.both.compat.c @@ -43,11 +43,19 @@ typedef struct DebugFlags { */ #define DebugFlags_BIGGEST_ALLOWED (DebugFlags){ .bits = (uint32_t)(1 << 31) } +typedef struct LargeFlags { + uint64_t bits; +} LargeFlags; +/** + * Flag with a very large shift that usually would be narrowed. + */ +#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(struct AlignFlags flags, struct DebugFlags bigger_flags); +void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/bitflags.c b/tests/expectations/bitflags.c index 073f10f..f8148db 100644 --- a/tests/expectations/bitflags.c +++ b/tests/expectations/bitflags.c @@ -43,4 +43,12 @@ typedef struct { */ #define DebugFlags_BIGGEST_ALLOWED (DebugFlags){ .bits = (uint32_t)(1 << 31) } -void root(AlignFlags flags, DebugFlags bigger_flags); +typedef struct { + uint64_t bits; +} LargeFlags; +/** + * Flag with a very large shift that usually would be narrowed. + */ +#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } + +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 cbcf7c4..84b38e3 100644 --- a/tests/expectations/bitflags.compat.c +++ b/tests/expectations/bitflags.compat.c @@ -43,11 +43,19 @@ typedef struct { */ #define DebugFlags_BIGGEST_ALLOWED (DebugFlags){ .bits = (uint32_t)(1 << 31) } +typedef struct { + uint64_t bits; +} LargeFlags; +/** + * Flag with a very large shift that usually would be narrowed. + */ +#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(AlignFlags flags, DebugFlags bigger_flags); +void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/bitflags.cpp b/tests/expectations/bitflags.cpp index c67a122..c771006 100644 --- a/tests/expectations/bitflags.cpp +++ b/tests/expectations/bitflags.cpp @@ -86,8 +86,42 @@ struct DebugFlags { /// Flag with the topmost bit set of the u32 constexpr static const DebugFlags DebugFlags_BIGGEST_ALLOWED = DebugFlags{ /* .bits = */ (uint32_t)(1 << 31) }; +struct LargeFlags { + uint64_t bits; + + explicit operator bool() const { + return !!bits; + } + LargeFlags operator~() const { + return {static_cast(~bits)}; + } + 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 { + return {static_cast(this->bits & other.bits)}; + } + LargeFlags& operator&=(const LargeFlags& other) { + *this = (*this & other); + return *this; + } + LargeFlags operator^(const LargeFlags& other) const { + return {static_cast(this->bits ^ other.bits)}; + } + LargeFlags& operator^=(const LargeFlags& other) { + *this = (*this ^ other); + return *this; + } +}; +/// Flag with a very large shift that usually would be narrowed. +constexpr static const LargeFlags LargeFlags_LARGE_SHIFT = LargeFlags{ /* .bits = */ (uint64_t)(1ull << 44) }; + extern "C" { -void root(AlignFlags flags, DebugFlags bigger_flags); +void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags); } // extern "C" diff --git a/tests/expectations/bitflags.pyx b/tests/expectations/bitflags.pyx index fd33bdb..68639f8 100644 --- a/tests/expectations/bitflags.pyx +++ b/tests/expectations/bitflags.pyx @@ -30,4 +30,9 @@ cdef extern from *: # Flag with the topmost bit set of the u32 const DebugFlags DebugFlags_BIGGEST_ALLOWED # = { (1 << 31) } - void root(AlignFlags flags, DebugFlags bigger_flags); + ctypedef struct LargeFlags: + uint64_t bits; + # Flag with a very large shift that usually would be narrowed. + const LargeFlags LargeFlags_LARGE_SHIFT # = { (1ull << 44) } + + 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 1372909..0492d12 100644 --- a/tests/expectations/bitflags.tag.c +++ b/tests/expectations/bitflags.tag.c @@ -43,4 +43,12 @@ struct DebugFlags { */ #define DebugFlags_BIGGEST_ALLOWED (DebugFlags){ .bits = (uint32_t)(1 << 31) } -void root(struct AlignFlags flags, struct DebugFlags bigger_flags); +struct LargeFlags { + uint64_t bits; +}; +/** + * Flag with a very large shift that usually would be narrowed. + */ +#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } + +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 6b6e2b8..52c1e8d 100644 --- a/tests/expectations/bitflags.tag.compat.c +++ b/tests/expectations/bitflags.tag.compat.c @@ -43,11 +43,19 @@ struct DebugFlags { */ #define DebugFlags_BIGGEST_ALLOWED (DebugFlags){ .bits = (uint32_t)(1 << 31) } +struct LargeFlags { + uint64_t bits; +}; +/** + * Flag with a very large shift that usually would be narrowed. + */ +#define LargeFlags_LARGE_SHIFT (LargeFlags){ .bits = (uint64_t)(1ull << 44) } + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(struct AlignFlags flags, struct DebugFlags bigger_flags); +void root(struct AlignFlags flags, struct DebugFlags bigger_flags, struct LargeFlags largest_flags); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/bitflags.tag.pyx b/tests/expectations/bitflags.tag.pyx index 272cddc..ba2d37f 100644 --- a/tests/expectations/bitflags.tag.pyx +++ b/tests/expectations/bitflags.tag.pyx @@ -30,4 +30,9 @@ cdef extern from *: # Flag with the topmost bit set of the u32 const DebugFlags DebugFlags_BIGGEST_ALLOWED # = { (1 << 31) } - void root(AlignFlags flags, DebugFlags bigger_flags); + cdef struct LargeFlags: + uint64_t bits; + # Flag with a very large shift that usually would be narrowed. + const LargeFlags LargeFlags_LARGE_SHIFT # = { (1ull << 44) } + + void root(AlignFlags flags, DebugFlags bigger_flags, LargeFlags largest_flags); diff --git a/tests/expectations/constant_big.compat.c b/tests/expectations/constant_big.compat.c index 86867df..0a52aad 100644 --- a/tests/expectations/constant_big.compat.c +++ b/tests/expectations/constant_big.compat.c @@ -3,10 +3,10 @@ #include #include -#define UNSIGNED_NEEDS_ULL_SUFFIX 9223372036854775808ULL +#define UNSIGNED_NEEDS_ULL_SUFFIX 9223372036854775808ull #define UNSIGNED_DOESNT_NEED_ULL_SUFFIX 8070450532247928832 -#define SIGNED_NEEDS_ULL_SUFFIX -9223372036854775808ULL +#define SIGNED_NEEDS_ULL_SUFFIX -9223372036854775808ull #define SIGNED_DOESNT_NEED_ULL_SUFFIX -9223372036854775807 diff --git a/tests/expectations/constant_big.cpp b/tests/expectations/constant_big.cpp index d86c3e7..8b0ebc9 100644 --- a/tests/expectations/constant_big.cpp +++ b/tests/expectations/constant_big.cpp @@ -4,10 +4,10 @@ #include #include -constexpr static const uint64_t UNSIGNED_NEEDS_ULL_SUFFIX = 9223372036854775808ULL; +constexpr static const uint64_t UNSIGNED_NEEDS_ULL_SUFFIX = 9223372036854775808ull; constexpr static const uint64_t UNSIGNED_DOESNT_NEED_ULL_SUFFIX = 8070450532247928832; -constexpr static const int64_t SIGNED_NEEDS_ULL_SUFFIX = -9223372036854775808ULL; +constexpr static const int64_t SIGNED_NEEDS_ULL_SUFFIX = -9223372036854775808ull; constexpr static const int64_t SIGNED_DOESNT_NEED_ULL_SUFFIX = -9223372036854775807; diff --git a/tests/expectations/constant_big.pyx b/tests/expectations/constant_big.pyx index 664199d..178c637 100644 --- a/tests/expectations/constant_big.pyx +++ b/tests/expectations/constant_big.pyx @@ -6,10 +6,10 @@ cdef extern from *: cdef extern from *: - const uint64_t UNSIGNED_NEEDS_ULL_SUFFIX # = 9223372036854775808ULL + const uint64_t UNSIGNED_NEEDS_ULL_SUFFIX # = 9223372036854775808ull const uint64_t UNSIGNED_DOESNT_NEED_ULL_SUFFIX # = 8070450532247928832 - const int64_t SIGNED_NEEDS_ULL_SUFFIX # = -9223372036854775808ULL + const int64_t SIGNED_NEEDS_ULL_SUFFIX # = -9223372036854775808ull const int64_t SIGNED_DOESNT_NEED_ULL_SUFFIX # = -9223372036854775807 diff --git a/tests/rust/bitflags.rs b/tests/rust/bitflags.rs index 013e10b..4d05cb0 100644 --- a/tests/rust/bitflags.rs +++ b/tests/rust/bitflags.rs @@ -29,5 +29,14 @@ bitflags! { } } +bitflags! { + #[repr(C)] + pub struct LargeFlags: u64 { + /// Flag with a very large shift that usually would be narrowed. + const LARGE_SHIFT = 1u64 << 44; + } +} + + #[no_mangle] -pub extern "C" fn root(flags: AlignFlags, bigger_flags: DebugFlags) {} +pub extern "C" fn root(flags: AlignFlags, bigger_flags: DebugFlags, largest_flags: LargeFlags) {}