diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index 2f1d3bff..ca6499d8 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -184,7 +184,7 @@ impl Literal { } } - fn can_be_constexpr(&self) -> bool { + pub(crate) fn can_be_constexpr(&self) -> bool { !self.has_pointer_casts() } diff --git a/src/bindgen/language_backend/clike.rs b/src/bindgen/language_backend/clike.rs index bf5a39fb..b41a3c46 100644 --- a/src/bindgen/language_backend/clike.rs +++ b/src/bindgen/language_backend/clike.rs @@ -893,33 +893,61 @@ impl LanguageBackend for CLikeLanguageBackend<'_> { fields, path, } => { + let allow_constexpr = self.config.constant.allow_constexpr && l.can_be_constexpr(); + let is_constexpr = self.config.language == Language::Cxx + && (self.config.constant.allow_static_const || allow_constexpr); if self.config.language == Language::C { write!(out, "({})", export_name); } else { write!(out, "{}", export_name); } - write!(out, "{{ "); - let mut is_first_field = true; + write!(out, "{{"); + if is_constexpr { + out.push_tab(); + } else { + write!(out, " "); + } // In C++, same order as defined is required. let ordered_fields = out.bindings().struct_field_names(path); - for ordered_key in ordered_fields.iter() { + for (i, ordered_key) in ordered_fields.iter().enumerate() { if let Some(lit) = fields.get(ordered_key) { - if !is_first_field { - write!(out, ", "); - } - is_first_field = false; - if self.config.language == Language::Cxx { + if is_constexpr { + out.new_line(); + // TODO: Some C++ versions (c++20?) now support designated // initializers, consider generating them. write!(out, "/* .{} = */ ", ordered_key); + self.write_literal(out, lit); + if i + 1 != ordered_fields.len() { + write!(out, ","); + if !is_constexpr { + write!(out, " "); + } + } } else { - write!(out, ".{} = ", ordered_key); + if i > 0 { + write!(out, ", "); + } + + if self.config.language == Language::Cxx { + // TODO: Some C++ versions (c++20?) now support designated + // initializers, consider generating them. + write!(out, "/* .{} = */ ", ordered_key); + } else { + write!(out, ".{} = ", ordered_key); + } + self.write_literal(out, lit); } - self.write_literal(out, lit); } } - write!(out, " }}"); + if is_constexpr { + out.pop_tab(); + out.new_line(); + } else { + write!(out, " "); + } + write!(out, "}}"); } } } diff --git a/tests/expectations/associated_in_body.cpp b/tests/expectations/associated_in_body.cpp index edbcbea4..29f6bd68 100644 --- a/tests/expectations/associated_in_body.cpp +++ b/tests/expectations/associated_in_body.cpp @@ -47,18 +47,34 @@ struct StyleAlignFlags { static const StyleAlignFlags MIXED_SELF; }; /// 'auto' -constexpr inline const StyleAlignFlags StyleAlignFlags::AUTO = StyleAlignFlags{ /* .bits = */ (uint8_t)0 }; +constexpr inline const StyleAlignFlags StyleAlignFlags::AUTO = StyleAlignFlags{ + /* .bits = */ (uint8_t)0 +}; /// 'normal' -constexpr inline const StyleAlignFlags StyleAlignFlags::NORMAL = StyleAlignFlags{ /* .bits = */ (uint8_t)1 }; +constexpr inline const StyleAlignFlags StyleAlignFlags::NORMAL = StyleAlignFlags{ + /* .bits = */ (uint8_t)1 +}; /// 'start' -constexpr inline const StyleAlignFlags StyleAlignFlags::START = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 1) }; +constexpr inline const StyleAlignFlags StyleAlignFlags::START = StyleAlignFlags{ + /* .bits = */ (uint8_t)(1 << 1) +}; /// 'end' -constexpr inline const StyleAlignFlags StyleAlignFlags::END = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 2) }; -constexpr inline const StyleAlignFlags StyleAlignFlags::ALIAS = StyleAlignFlags{ /* .bits = */ (uint8_t)(StyleAlignFlags::END).bits }; +constexpr inline const StyleAlignFlags StyleAlignFlags::END = StyleAlignFlags{ + /* .bits = */ (uint8_t)(1 << 2) +}; +constexpr inline const StyleAlignFlags StyleAlignFlags::ALIAS = StyleAlignFlags{ + /* .bits = */ (uint8_t)(StyleAlignFlags::END).bits +}; /// 'flex-start' -constexpr inline const StyleAlignFlags StyleAlignFlags::FLEX_START = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 3) }; -constexpr inline const StyleAlignFlags StyleAlignFlags::MIXED = StyleAlignFlags{ /* .bits = */ (uint8_t)(((1 << 4) | (StyleAlignFlags::FLEX_START).bits) | (StyleAlignFlags::END).bits) }; -constexpr inline const StyleAlignFlags StyleAlignFlags::MIXED_SELF = StyleAlignFlags{ /* .bits = */ (uint8_t)(((1 << 5) | (StyleAlignFlags::FLEX_START).bits) | (StyleAlignFlags::END).bits) }; +constexpr inline const StyleAlignFlags StyleAlignFlags::FLEX_START = StyleAlignFlags{ + /* .bits = */ (uint8_t)(1 << 3) +}; +constexpr inline const StyleAlignFlags StyleAlignFlags::MIXED = StyleAlignFlags{ + /* .bits = */ (uint8_t)(((1 << 4) | (StyleAlignFlags::FLEX_START).bits) | (StyleAlignFlags::END).bits) +}; +constexpr inline const StyleAlignFlags StyleAlignFlags::MIXED_SELF = StyleAlignFlags{ + /* .bits = */ (uint8_t)(((1 << 5) | (StyleAlignFlags::FLEX_START).bits) | (StyleAlignFlags::END).bits) +}; /// An arbitrary identifier for a native (OS compositor) surface struct StyleNativeSurfaceId { @@ -66,7 +82,9 @@ struct StyleNativeSurfaceId { static const StyleNativeSurfaceId DEBUG_OVERLAY; }; /// A special id for the native surface that is used for debug / profiler overlays. -constexpr inline const StyleNativeSurfaceId StyleNativeSurfaceId::DEBUG_OVERLAY = StyleNativeSurfaceId{ /* ._0 = */ UINT64_MAX }; +constexpr inline const StyleNativeSurfaceId StyleNativeSurfaceId::DEBUG_OVERLAY = StyleNativeSurfaceId{ + /* ._0 = */ UINT64_MAX +}; struct StyleNativeTileId { StyleNativeSurfaceId surface_id; @@ -75,7 +93,11 @@ struct StyleNativeTileId { static const StyleNativeTileId DEBUG_OVERLAY; }; /// A special id for the native surface that is used for debug / profiler overlays. -constexpr inline const StyleNativeTileId StyleNativeTileId::DEBUG_OVERLAY = StyleNativeTileId{ /* .surface_id = */ StyleNativeSurfaceId::DEBUG_OVERLAY, /* .x = */ 0, /* .y = */ 0 }; +constexpr inline const StyleNativeTileId StyleNativeTileId::DEBUG_OVERLAY = StyleNativeTileId{ + /* .surface_id = */ StyleNativeSurfaceId::DEBUG_OVERLAY, + /* .x = */ 0, + /* .y = */ 0 +}; extern "C" { diff --git a/tests/expectations/bitflags.cpp b/tests/expectations/bitflags.cpp index 13bc3c52..6cbe7ef5 100644 --- a/tests/expectations/bitflags.cpp +++ b/tests/expectations/bitflags.cpp @@ -39,18 +39,34 @@ struct AlignFlags { } }; /// 'auto' -constexpr static const AlignFlags AlignFlags_AUTO = AlignFlags{ /* .bits = */ (uint8_t)0 }; +constexpr static const AlignFlags AlignFlags_AUTO = AlignFlags{ + /* .bits = */ (uint8_t)0 +}; /// 'normal' -constexpr static const AlignFlags AlignFlags_NORMAL = AlignFlags{ /* .bits = */ (uint8_t)1 }; +constexpr static const AlignFlags AlignFlags_NORMAL = AlignFlags{ + /* .bits = */ (uint8_t)1 +}; /// 'start' -constexpr static const AlignFlags AlignFlags_START = AlignFlags{ /* .bits = */ (uint8_t)(1 << 1) }; +constexpr static const AlignFlags AlignFlags_START = AlignFlags{ + /* .bits = */ (uint8_t)(1 << 1) +}; /// 'end' -constexpr static const AlignFlags AlignFlags_END = AlignFlags{ /* .bits = */ (uint8_t)(1 << 2) }; -constexpr static const AlignFlags AlignFlags_ALIAS = AlignFlags{ /* .bits = */ (uint8_t)(AlignFlags_END).bits }; +constexpr static const AlignFlags AlignFlags_END = AlignFlags{ + /* .bits = */ (uint8_t)(1 << 2) +}; +constexpr static const AlignFlags AlignFlags_ALIAS = AlignFlags{ + /* .bits = */ (uint8_t)(AlignFlags_END).bits +}; /// 'flex-start' -constexpr static const AlignFlags AlignFlags_FLEX_START = AlignFlags{ /* .bits = */ (uint8_t)(1 << 3) }; -constexpr static const AlignFlags AlignFlags_MIXED = AlignFlags{ /* .bits = */ (uint8_t)(((1 << 4) | (AlignFlags_FLEX_START).bits) | (AlignFlags_END).bits) }; -constexpr static const AlignFlags AlignFlags_MIXED_SELF = AlignFlags{ /* .bits = */ (uint8_t)(((1 << 5) | (AlignFlags_FLEX_START).bits) | (AlignFlags_END).bits) }; +constexpr static const AlignFlags AlignFlags_FLEX_START = AlignFlags{ + /* .bits = */ (uint8_t)(1 << 3) +}; +constexpr static const AlignFlags AlignFlags_MIXED = AlignFlags{ + /* .bits = */ (uint8_t)(((1 << 4) | (AlignFlags_FLEX_START).bits) | (AlignFlags_END).bits) +}; +constexpr static const AlignFlags AlignFlags_MIXED_SELF = AlignFlags{ + /* .bits = */ (uint8_t)(((1 << 5) | (AlignFlags_FLEX_START).bits) | (AlignFlags_END).bits) +}; struct DebugFlags { uint32_t bits; @@ -84,7 +100,9 @@ struct DebugFlags { } }; /// Flag with the topmost bit set of the u32 -constexpr static const DebugFlags DebugFlags_BIGGEST_ALLOWED = DebugFlags{ /* .bits = */ (uint32_t)(1 << 31) }; +constexpr static const DebugFlags DebugFlags_BIGGEST_ALLOWED = DebugFlags{ + /* .bits = */ (uint32_t)(1 << 31) +}; struct LargeFlags { uint64_t bits; @@ -118,8 +136,12 @@ 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 }; +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 +}; struct OutOfLine { uint32_t _0; @@ -152,9 +174,15 @@ struct OutOfLine { return *this; } }; -constexpr static const OutOfLine OutOfLine_A = OutOfLine{ /* ._0 = */ (uint32_t)1 }; -constexpr static const OutOfLine OutOfLine_B = OutOfLine{ /* ._0 = */ (uint32_t)2 }; -constexpr static const OutOfLine OutOfLine_AB = OutOfLine{ /* ._0 = */ (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) }; +constexpr static const OutOfLine OutOfLine_A = OutOfLine{ + /* ._0 = */ (uint32_t)1 +}; +constexpr static const OutOfLine OutOfLine_B = OutOfLine{ + /* ._0 = */ (uint32_t)2 +}; +constexpr static const OutOfLine OutOfLine_AB = OutOfLine{ + /* ._0 = */ (uint32_t)((OutOfLine_A)._0 | (OutOfLine_B)._0) +}; extern "C" { diff --git a/tests/expectations/const_generics_constant.cpp b/tests/expectations/const_generics_constant.cpp index f0dd5fd7..2d6a1de7 100644 --- a/tests/expectations/const_generics_constant.cpp +++ b/tests/expectations/const_generics_constant.cpp @@ -16,7 +16,11 @@ using FontWeightFixedPoint = FixedPoint; struct FontWeight { FontWeightFixedPoint _0; }; -constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FontWeightFixedPoint{ /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) } }; +constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ + /* ._0 = */ FontWeightFixedPoint{ + /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) + } +}; extern "C" { diff --git a/tests/expectations/constant_constexpr.cpp b/tests/expectations/constant_constexpr.cpp index f600980c..a6120ccb 100644 --- a/tests/expectations/constant_constexpr.cpp +++ b/tests/expectations/constant_constexpr.cpp @@ -18,4 +18,6 @@ struct Foo { }; inline const int64_t Foo::CONSTANT_I64_BODY = 216; -static const Foo SomeFoo = Foo{ /* .x = */ 99 }; +static const Foo SomeFoo = Foo{ + /* .x = */ 99 +}; diff --git a/tests/expectations/constant_user_defined_type.cpp b/tests/expectations/constant_user_defined_type.cpp index f1272926..47c354f4 100644 --- a/tests/expectations/constant_user_defined_type.cpp +++ b/tests/expectations/constant_user_defined_type.cpp @@ -14,7 +14,9 @@ struct S { using A = uint8_t; -constexpr static const S C1 = S{ /* .field = */ 0 }; +constexpr static const S C1 = S{ + /* .field = */ 0 +}; constexpr static const E C2 = V; diff --git a/tests/expectations/prefixed_struct_literal.cpp b/tests/expectations/prefixed_struct_literal.cpp index c8f5dbab..1a815261 100644 --- a/tests/expectations/prefixed_struct_literal.cpp +++ b/tests/expectations/prefixed_struct_literal.cpp @@ -8,9 +8,15 @@ struct PREFIXFoo { int32_t a; uint32_t b; }; -constexpr static const PREFIXFoo PREFIXFoo_FOO = PREFIXFoo{ /* .a = */ 42, /* .b = */ 47 }; +constexpr static const PREFIXFoo PREFIXFoo_FOO = PREFIXFoo{ + /* .a = */ 42, + /* .b = */ 47 +}; -constexpr static const PREFIXFoo PREFIXBAR = PREFIXFoo{ /* .a = */ 42, /* .b = */ 1337 }; +constexpr static const PREFIXFoo PREFIXBAR = PREFIXFoo{ + /* .a = */ 42, + /* .b = */ 1337 +}; extern "C" { diff --git a/tests/expectations/prefixed_struct_literal_deep.cpp b/tests/expectations/prefixed_struct_literal_deep.cpp index bd883f64..19c2b439 100644 --- a/tests/expectations/prefixed_struct_literal_deep.cpp +++ b/tests/expectations/prefixed_struct_literal_deep.cpp @@ -14,7 +14,13 @@ struct PREFIXFoo { PREFIXBar bar; }; -constexpr static const PREFIXFoo PREFIXVAL = PREFIXFoo{ /* .a = */ 42, /* .b = */ 1337, /* .bar = */ PREFIXBar{ /* .a = */ 323 } }; +constexpr static const PREFIXFoo PREFIXVAL = PREFIXFoo{ + /* .a = */ 42, + /* .b = */ 1337, + /* .bar = */ PREFIXBar{ + /* .a = */ 323 + } +}; extern "C" { diff --git a/tests/expectations/struct_literal.cpp b/tests/expectations/struct_literal.cpp index 678cf930..1ccc6319 100644 --- a/tests/expectations/struct_literal.cpp +++ b/tests/expectations/struct_literal.cpp @@ -10,12 +10,24 @@ struct Foo { int32_t a; uint32_t b; }; -constexpr static const Foo Foo_FOO = Foo{ /* .a = */ 42, /* .b = */ 47 }; -constexpr static const Foo Foo_FOO2 = Foo{ /* .a = */ 42, /* .b = */ 47 }; -constexpr static const Foo Foo_FOO3 = Foo{ /* .a = */ 42, /* .b = */ 47 }; +constexpr static const Foo Foo_FOO = Foo{ + /* .a = */ 42, + /* .b = */ 47 +}; +constexpr static const Foo Foo_FOO2 = Foo{ + /* .a = */ 42, + /* .b = */ 47 +}; +constexpr static const Foo Foo_FOO3 = Foo{ + /* .a = */ 42, + /* .b = */ 47 +}; -constexpr static const Foo BAR = Foo{ /* .a = */ 42, /* .b = */ 1337 }; +constexpr static const Foo BAR = Foo{ + /* .a = */ 42, + /* .b = */ 1337 +}; diff --git a/tests/expectations/struct_literal_order.cpp b/tests/expectations/struct_literal_order.cpp index cd385880..6d20dfe2 100644 --- a/tests/expectations/struct_literal_order.cpp +++ b/tests/expectations/struct_literal_order.cpp @@ -9,18 +9,42 @@ struct ABC { uint32_t b; uint32_t c; }; -constexpr static const ABC ABC_abc = ABC{ /* .a = */ 1.0, /* .b = */ 2, /* .c = */ 3 }; -constexpr static const ABC ABC_bac = ABC{ /* .a = */ 1.0, /* .b = */ 2, /* .c = */ 3 }; -constexpr static const ABC ABC_cba = ABC{ /* .a = */ 1.0, /* .b = */ 2, /* .c = */ 3 }; +constexpr static const ABC ABC_abc = ABC{ + /* .a = */ 1.0, + /* .b = */ 2, + /* .c = */ 3 +}; +constexpr static const ABC ABC_bac = ABC{ + /* .a = */ 1.0, + /* .b = */ 2, + /* .c = */ 3 +}; +constexpr static const ABC ABC_cba = ABC{ + /* .a = */ 1.0, + /* .b = */ 2, + /* .c = */ 3 +}; struct BAC { uint32_t b; float a; int32_t c; }; -constexpr static const BAC BAC_abc = BAC{ /* .b = */ 1, /* .a = */ 2.0, /* .c = */ 3 }; -constexpr static const BAC BAC_bac = BAC{ /* .b = */ 1, /* .a = */ 2.0, /* .c = */ 3 }; -constexpr static const BAC BAC_cba = BAC{ /* .b = */ 1, /* .a = */ 2.0, /* .c = */ 3 }; +constexpr static const BAC BAC_abc = BAC{ + /* .b = */ 1, + /* .a = */ 2.0, + /* .c = */ 3 +}; +constexpr static const BAC BAC_bac = BAC{ + /* .b = */ 1, + /* .a = */ 2.0, + /* .c = */ 3 +}; +constexpr static const BAC BAC_cba = BAC{ + /* .b = */ 1, + /* .a = */ 2.0, + /* .c = */ 3 +}; extern "C" {