From 15e1131160f394b11dcabae96ca599cfaf868884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 21 Apr 2022 12:28:13 +0200 Subject: [PATCH] constant: Allow more constexpr constants. --- src/bindgen/ir/constant.rs | 59 ++++++++++++++++++----- src/bindgen/ir/ty.rs | 4 ++ tests/expectations/associated_in_body.cpp | 20 ++++---- tests/expectations/bitflags.cpp | 18 +++---- tests/expectations/constant_constexpr.cpp | 2 +- tests/rust/associated_in_body.toml | 3 ++ tests/rust/bitflags.toml | 3 ++ 7 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index c108870..d1cbcba 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -183,22 +183,60 @@ impl Literal { } } - pub fn uses_only_primitive_types(&self) -> bool { + fn can_be_constexpr(&self) -> bool { + !self.has_pointer_casts() + } + + fn visit(&self, visitor: &mut impl FnMut(&Self) -> bool) -> bool { + if !visitor(self) { + return false; + } match self { Literal::Expr(..) | Literal::Path { .. } => true, - Literal::PostfixUnaryOp { ref value, .. } => value.uses_only_primitive_types(), + Literal::PostfixUnaryOp { ref value, .. } => value.visit(visitor), Literal::BinOp { ref left, ref right, .. - } => left.uses_only_primitive_types() & right.uses_only_primitive_types(), - Literal::FieldAccess { ref base, .. } => base.uses_only_primitive_types(), - Literal::Struct { .. } => false, - Literal::Cast { ref value, ref ty } => { - value.uses_only_primitive_types() && ty.is_primitive_or_ptr_primitive() + } => left.visit(visitor) && right.visit(visitor), + Literal::FieldAccess { ref base, .. } => base.visit(visitor), + Literal::Struct { ref fields, .. } => { + for (_name, field) in fields.iter() { + if !field.visit(visitor) { + return false; + } + } + true } + Literal::Cast { ref value, .. } => value.visit(visitor), } } + + fn has_pointer_casts(&self) -> bool { + let mut has_pointer_casts = false; + self.visit(&mut |lit| { + if let Literal::Cast { ref ty, .. } = *lit { + has_pointer_casts = has_pointer_casts || ty.is_ptr(); + } + !has_pointer_casts + }); + has_pointer_casts + } + + pub fn uses_only_primitive_types(&self) -> bool { + let mut uses_only_primitive_types = true; + self.visit(&mut |lit| { + // XXX This is a bit sketchy, but alas. + uses_only_primitive_types = uses_only_primitive_types + && match *lit { + Literal::Struct { .. } => false, + Literal::Cast { ref ty, .. } => ty.is_primitive_or_ptr_primitive(), + _ => true, + }; + uses_only_primitive_types + }); + uses_only_primitive_types + } } impl Literal { @@ -720,12 +758,7 @@ impl Constant { self.documentation.write(config, out); - let allow_constexpr = if let Type::Primitive(..) = self.ty { - config.constant.allow_constexpr - } else { - false - }; - + let allow_constexpr = config.constant.allow_constexpr && self.value.can_be_constexpr(); match config.language { Language::Cxx if config.constant.allow_static_const || allow_constexpr => { if allow_constexpr { diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 6f2ba67..2edfd73 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -501,6 +501,10 @@ impl Type { Ok(Some(converted)) } + pub fn is_ptr(&self) -> bool { + matches!(*self, Type::Ptr { .. } | Type::FuncPtr { .. }) + } + pub fn is_primitive_or_ptr_primitive(&self) -> bool { match *self { Type::Primitive(..) => true, diff --git a/tests/expectations/associated_in_body.cpp b/tests/expectations/associated_in_body.cpp index 5ccf281..14c59e3 100644 --- a/tests/expectations/associated_in_body.cpp +++ b/tests/expectations/associated_in_body.cpp @@ -47,18 +47,18 @@ struct StyleAlignFlags { static const StyleAlignFlags MIXED_SELF; }; /// 'auto' -inline const StyleAlignFlags StyleAlignFlags::AUTO = StyleAlignFlags{ /* .bits = */ (uint8_t)0 }; +constexpr inline const StyleAlignFlags StyleAlignFlags::AUTO = StyleAlignFlags{ /* .bits = */ (uint8_t)0 }; /// 'normal' -inline const StyleAlignFlags StyleAlignFlags::NORMAL = StyleAlignFlags{ /* .bits = */ (uint8_t)1 }; +constexpr inline const StyleAlignFlags StyleAlignFlags::NORMAL = StyleAlignFlags{ /* .bits = */ (uint8_t)1 }; /// 'start' -inline const StyleAlignFlags StyleAlignFlags::START = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 1) }; +constexpr inline const StyleAlignFlags StyleAlignFlags::START = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 1) }; /// 'end' -inline const StyleAlignFlags StyleAlignFlags::END = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 2) }; -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' -inline const StyleAlignFlags StyleAlignFlags::FLEX_START = StyleAlignFlags{ /* .bits = */ (uint8_t)(1 << 3) }; -inline const StyleAlignFlags StyleAlignFlags::MIXED = StyleAlignFlags{ /* .bits = */ (uint8_t)(((1 << 4) | (StyleAlignFlags::FLEX_START).bits) | (StyleAlignFlags::END).bits) }; -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 +66,7 @@ struct StyleNativeSurfaceId { static const StyleNativeSurfaceId DEBUG_OVERLAY; }; /// A special id for the native surface that is used for debug / profiler overlays. -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 +75,7 @@ struct StyleNativeTileId { static const StyleNativeTileId DEBUG_OVERLAY; }; /// A special id for the native surface that is used for debug / profiler overlays. -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 31cb639..c67a122 100644 --- a/tests/expectations/bitflags.cpp +++ b/tests/expectations/bitflags.cpp @@ -39,18 +39,18 @@ struct AlignFlags { } }; /// 'auto' -static const AlignFlags AlignFlags_AUTO = AlignFlags{ /* .bits = */ (uint8_t)0 }; +constexpr static const AlignFlags AlignFlags_AUTO = AlignFlags{ /* .bits = */ (uint8_t)0 }; /// 'normal' -static const AlignFlags AlignFlags_NORMAL = AlignFlags{ /* .bits = */ (uint8_t)1 }; +constexpr static const AlignFlags AlignFlags_NORMAL = AlignFlags{ /* .bits = */ (uint8_t)1 }; /// 'start' -static const AlignFlags AlignFlags_START = AlignFlags{ /* .bits = */ (uint8_t)(1 << 1) }; +constexpr static const AlignFlags AlignFlags_START = AlignFlags{ /* .bits = */ (uint8_t)(1 << 1) }; /// 'end' -static const AlignFlags AlignFlags_END = AlignFlags{ /* .bits = */ (uint8_t)(1 << 2) }; -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' -static const AlignFlags AlignFlags_FLEX_START = AlignFlags{ /* .bits = */ (uint8_t)(1 << 3) }; -static const AlignFlags AlignFlags_MIXED = AlignFlags{ /* .bits = */ (uint8_t)(((1 << 4) | (AlignFlags_FLEX_START).bits) | (AlignFlags_END).bits) }; -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 +84,7 @@ struct DebugFlags { } }; /// Flag with the topmost bit set of the u32 -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) }; extern "C" { diff --git a/tests/expectations/constant_constexpr.cpp b/tests/expectations/constant_constexpr.cpp index 9870a1e..dab7437 100644 --- a/tests/expectations/constant_constexpr.cpp +++ b/tests/expectations/constant_constexpr.cpp @@ -18,4 +18,4 @@ struct Foo { }; constexpr inline const int64_t Foo::CONSTANT_I64_BODY = 216; -static const Foo SomeFoo = Foo{ /* .x = */ 99 }; +constexpr static const Foo SomeFoo = Foo{ /* .x = */ 99 }; diff --git a/tests/rust/associated_in_body.toml b/tests/rust/associated_in_body.toml index 0fbdc7e..a52609b 100644 --- a/tests/rust/associated_in_body.toml +++ b/tests/rust/associated_in_body.toml @@ -6,3 +6,6 @@ bitflags = true [export] prefix = "Style" # Just ensuring they play well together :) + +[const] +allow_constexpr = true diff --git a/tests/rust/bitflags.toml b/tests/rust/bitflags.toml index eab1378..465689e 100644 --- a/tests/rust/bitflags.toml +++ b/tests/rust/bitflags.toml @@ -1,2 +1,5 @@ [macro_expansion] bitflags = true + +[const] +allow_constexpr = true