From d850a0bd1c7fd96ec7dcf58a13f140124eba3a65 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Thu, 8 Aug 2019 17:49:12 +0800 Subject: [PATCH] esp_attr: add flag_attr to support enums used as flags --- components/cxx/test/test_cxx.cpp | 28 ++++++++++++++++++++++++ components/esp32/include/esp_attr.h | 24 ++++++++++++++++++++ components/soc/include/hal/timer_types.h | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/components/cxx/test/test_cxx.cpp b/components/cxx/test/test_cxx.cpp index 0f5cce3318..0bf92f324b 100644 --- a/components/cxx/test/test_cxx.cpp +++ b/components/cxx/test/test_cxx.cpp @@ -319,3 +319,31 @@ TEST_CASE("can call std::function and bind", "[cxx]") #endif +/* Tests below are done in the compile time, don't actually get run. */ +/* Check whether a enumerator flag can be used in C++ */ + + +template __attribute__((unused)) static void test_binary_operators() +{ + T flag1 = (T)0; + T flag2 = (T)0; + flag1 = ~flag1; + flag1 = flag1 | flag2; + flag1 = flag1 & flag2; + flag1 = flag1 ^ flag2; + flag1 = flag1 >> 2; + flag1 = flag1 << 2; + flag1 |= flag2; + flag1 &= flag2; + flag1 ^= flag2; + flag1 >>= 2; + flag1 <<= 2; +} + +//Add more types here. If any flags cannot pass the build, use FLAG_ATTR in esp_attr.h +#include "hal/timer_types.h" +template void test_binary_operators(); + + + + diff --git a/components/esp32/include/esp_attr.h b/components/esp32/include/esp_attr.h index 58fef76c71..34458948a7 100644 --- a/components/esp32/include/esp_attr.h +++ b/components/esp32/include/esp_attr.h @@ -76,6 +76,30 @@ // Forces to not inline function #define NOINLINE_ATTR __attribute__((noinline)) +// This allows using enum as flags in C++ +// Format: FLAG_ATTR(flag_enum_t) +#ifdef __cplusplus + +#define FLAG_ATTR_IMPL(TYPE, INT_TYPE) \ +constexpr TYPE operator~ (TYPE a) { return (TYPE)~(INT_TYPE)a; } \ +constexpr TYPE operator| (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a | (INT_TYPE)b); } \ +constexpr TYPE operator& (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a & (INT_TYPE)b); } \ +constexpr TYPE operator^ (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a ^ (INT_TYPE)b); } \ +constexpr TYPE operator>> (TYPE a, int b) { return (TYPE)((INT_TYPE)a >> b); } \ +constexpr TYPE operator<< (TYPE a, int b) { return (TYPE)((INT_TYPE)a << b); } \ +TYPE& operator|=(TYPE& a, TYPE b) { a = a | b; return a; } \ +TYPE& operator&=(TYPE& a, TYPE b) { a = a & b; return a; } \ +TYPE& operator^=(TYPE& a, TYPE b) { a = a ^ b; return a; } \ +TYPE& operator>>=(TYPE& a, int b) { a >>= b; return a; } \ +TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; } + +#define FLAG_ATTR_U32(TYPE) FLAG_ATTR_IMPL(TYPE, uint32_t) +#define FLAG_ATTR FLAG_ATTR_U32 + +#else +#define FLAG_ATTR(TYPE) +#endif + // Implementation for a unique custom section // // This prevents gcc producing "x causes a section type conflict with y" diff --git a/components/soc/include/hal/timer_types.h b/components/soc/include/hal/timer_types.h index 8ab5757f28..e9bcc9985d 100644 --- a/components/soc/include/hal/timer_types.h +++ b/components/soc/include/hal/timer_types.h @@ -40,7 +40,6 @@ typedef enum { TIMER_START = 1, /*!