From 8cae63c84349b7f6a09551a2f8470717372f56f2 Mon Sep 17 00:00:00 2001 From: Christopher Durand Date: Sun, 19 Mar 2017 01:38:24 +0100 Subject: [PATCH 1/3] [architecture] Add test for conversion from FlagsOperators to FlagsGroup --- src/xpcc/architecture/interface/test/register_test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xpcc/architecture/interface/test/register_test.cpp b/src/xpcc/architecture/interface/test/register_test.cpp index 283ad7206..c28959e2c 100644 --- a/src/xpcc/architecture/interface/test/register_test.cpp +++ b/src/xpcc/architecture/interface/test/register_test.cpp @@ -49,6 +49,11 @@ RegisterTest::testAssignments() a0 = translateCommonArgument(c3); TEST_ASSERT_EQUALS(a0, 0x42); + // flags operators to common struct + v0 = Test::A; + c0 = v0 | Test::C; + TEST_ASSERT_EQUALS(c0.value, 0b101); + // to register // these are not possible! From b28bed21d3ede81e4b8244b8926ed80b323b5706 Mon Sep 17 00:00:00 2001 From: Christopher Durand Date: Wed, 15 Mar 2017 01:30:15 +0100 Subject: [PATCH 2/3] [architecture] Allow conversion from FlagsOperators to FlagsGroup --- src/xpcc/architecture/interface/register.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/xpcc/architecture/interface/register.hpp b/src/xpcc/architecture/interface/register.hpp index f6def56be..2b908e611 100644 --- a/src/xpcc/architecture/interface/register.hpp +++ b/src/xpcc/architecture/interface/register.hpp @@ -598,9 +598,10 @@ struct FlagsGroup : public FlagsGroup // enum class constexpr FlagsGroup(typename T::EnumType value) : FlagsGroup(typename T::UnderlyingType(value)) {} - // Flags class - constexpr FlagsGroup(T value) + /// Flags operators and Flags constructor + constexpr FlagsGroup(::xpcc::FlagsOperators value) : FlagsGroup(value.value) {} + } xpcc_packed; /// @endcond @@ -656,9 +657,10 @@ struct FlagsGroup : public Register /// enum type constructor constexpr FlagsGroup(typename T::EnumType value) : Register(typename T::UnderlyingType(value)) {} - /// Flags type constructor - constexpr FlagsGroup(T value) + /// Flags operators and Flags constructor + constexpr FlagsGroup(::xpcc::FlagsOperators value) : Register(value.value) {} + } xpcc_packed; /** From ad206d983bc2d2ddf2a2a628afaaba3baab324b1 Mon Sep 17 00:00:00 2001 From: Christopher Durand Date: Wed, 22 Mar 2017 18:41:40 +0100 Subject: [PATCH 3/3] [architecture] Make bool conversion operator of Flags explicit The bool conversion of xpcc::Register and thus all derived flags classes is implemented in terms of "explicit operator bool()". This fixes issues with function overloading on flags parameters. Implicit bool conversion without an explicit cast is only applied in the following contexts: * conditions of if, while, for, do-while statements * logical operators (&&, ||) * negation (operator !) * static_assert This will probably break user code that relies on implicit bool conversion of flags in return statements or in assignments to bool variables. --- src/unittest/harness.hpp | 2 +- src/xpcc/architecture/interface/register.hpp | 45 ++++++------------- .../driver/adc/stm32f3/adc_impl.hpp.in | 4 +- .../driver/spi/stm32/spi_hal_impl.hpp.in | 4 +- src/xpcc/driver/temperature/tmp102_impl.hpp | 2 +- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/src/unittest/harness.hpp b/src/unittest/harness.hpp index 94feea70a..c8a58ca6d 100644 --- a/src/unittest/harness.hpp +++ b/src/unittest/harness.hpp @@ -262,7 +262,7 @@ namespace unittest } #define TEST_ASSERT_TRUE(expr) \ - TEST_RETURN__(::unittest::checkExpression((expr), __LINE__)) + TEST_RETURN__(::unittest::checkExpression(static_cast(expr), __LINE__)) #define TEST_ASSERT_FALSE(expr) \ TEST_RETURN__(::unittest::checkExpression(!static_cast(expr), __LINE__)) diff --git a/src/xpcc/architecture/interface/register.hpp b/src/xpcc/architecture/interface/register.hpp index 2b908e611..ec1eb28ce 100644 --- a/src/xpcc/architecture/interface/register.hpp +++ b/src/xpcc/architecture/interface/register.hpp @@ -229,13 +229,16 @@ struct Register : value(0) {} /// @{ - // The safe-bool idiom is not required here, since we are not - // dealing with complex objects, but with one integral value. - // So there is not need for it. - /* explicit */ - - /// Returns `true` if `value` is non-zero - constexpr operator bool() const + /** + * Returns `true` if `value` is non-zero + * + * The compiler will allow implicit conversions to bool in the following contexts: + * - conditions of if, while, for, do-while statements + * - logical operators (&&, ||) + * - negation (operator !) + * - static_assert + */ + explicit constexpr operator bool() const { return bool(value); } /// Returns `true` if `value` is zero @@ -252,28 +255,6 @@ struct Register /// This class is meant to be subclassed constexpr Register(UnderlyingType value) : value(value) {} - -#ifndef __DOXYGEN__ -public: - // do NOT cast to anything else - /// all other conversion operators are deleted and must be explicitly implemented - constexpr operator char16_t() const = delete; - constexpr operator char32_t() const = delete; - constexpr operator wchar_t() const = delete; - constexpr operator signed char() const = delete; - constexpr operator unsigned char() const = delete; - constexpr operator signed short int() const = delete; - constexpr operator unsigned short int() const = delete; - constexpr operator signed int() const = delete; - constexpr operator unsigned int() const = delete; - constexpr operator signed long int() const = delete; - constexpr operator unsigned long int() const = delete; - constexpr operator signed long long int() const = delete; - constexpr operator unsigned long long int() const = delete; - constexpr operator float() const = delete; - constexpr operator double() const = delete; - constexpr operator long double() const = delete; -#endif }; /// @ingroup register @@ -547,10 +528,10 @@ struct Flags : public ::xpcc::FlagsOperators /// Returns `true` if bit is set constexpr bool all(Enum const &flag) const - { return (*this & flag); } + { return bool(*this & flag); } /// Returns `true` if bit is set constexpr bool any(Enum const &flag) const - { return (*this & flag); } + { return bool(*this & flag); } /// Returns `true` if bit is **not** set constexpr bool none(Enum const &flag) const { return !(*this & flag); } @@ -563,7 +544,7 @@ struct Flags : public ::xpcc::FlagsOperators { return (*this & o) == o; } /// Returns `true` if **any** of the passed bits are set constexpr bool any(Flags const &o) const - { return *this & o; } + { return bool(*this & o); } /// Returns `true` if **none** of the passed bits are set constexpr bool none(Flags const &o) const { return (*this & o).value == 0; } diff --git a/src/xpcc/architecture/platform/driver/adc/stm32f3/adc_impl.hpp.in b/src/xpcc/architecture/platform/driver/adc/stm32f3/adc_impl.hpp.in index f9d274edc..42954bea3 100644 --- a/src/xpcc/architecture/platform/driver/adc/stm32f3/adc_impl.hpp.in +++ b/src/xpcc/architecture/platform/driver/adc/stm32f3/adc_impl.hpp.in @@ -87,7 +87,7 @@ xpcc::stm32::Adc{{ id }}::setPrescaler(const Prescaler pre) bool xpcc::stm32::Adc{{ id }}::isReady() { - return (getInterruptFlags() & InterruptFlag::Ready); + return static_cast(getInterruptFlags() & InterruptFlag::Ready); } void @@ -162,7 +162,7 @@ xpcc::stm32::Adc{{ id }}::startConversion(void) bool xpcc::stm32::Adc{{ id }}::isConversionFinished(void) { - return (getInterruptFlags() & InterruptFlag::EndOfSampling); + return static_cast(getInterruptFlags() & InterruptFlag::EndOfSampling); } // ---------------------------------------------------------------------------- diff --git a/src/xpcc/architecture/platform/driver/spi/stm32/spi_hal_impl.hpp.in b/src/xpcc/architecture/platform/driver/spi/stm32/spi_hal_impl.hpp.in index a7619f675..6f9a2af89 100644 --- a/src/xpcc/architecture/platform/driver/spi/stm32/spi_hal_impl.hpp.in +++ b/src/xpcc/architecture/platform/driver/spi/stm32/spi_hal_impl.hpp.in @@ -111,13 +111,13 @@ xpcc::stm32::SpiHal{{ id }}::setMasterSelection(MasterSelection masterSelection) inline bool xpcc::stm32::SpiHal{{ id }}::isReceiveRegisterNotEmpty() { - return getInterruptFlags() & InterruptFlag::RxBufferNotEmpty; + return static_cast(getInterruptFlags() & InterruptFlag::RxBufferNotEmpty); } inline bool xpcc::stm32::SpiHal{{ id }}::isTransmitRegisterEmpty() { - return getInterruptFlags() & InterruptFlag::TxBufferEmpty; + return static_cast(getInterruptFlags() & InterruptFlag::TxBufferEmpty); } void inline diff --git a/src/xpcc/driver/temperature/tmp102_impl.hpp b/src/xpcc/driver/temperature/tmp102_impl.hpp index 6015c32ca..12a0e25a6 100644 --- a/src/xpcc/driver/temperature/tmp102_impl.hpp +++ b/src/xpcc/driver/temperature/tmp102_impl.hpp @@ -141,7 +141,7 @@ xpcc::Tmp102::readComparatorMode(bool &result) if (RF_CALL( this->runTransaction() )) { reinterpret_cast(this->config_msb) = Config1_t(this->buffer[0]) & ~Resolution_t::mask(); - result = Config2_t(this->buffer[1]) & Config2::Alert; + result = static_cast(Config2_t(this->buffer[1]) & Config2::Alert); config_lsb = Config2_t(this->buffer[1]) & ~Config2::Alert; RF_RETURN(true); }