]> granicus.if.org Git - esp-idf/commitdiff
esp_attr: add flag_attr to support enums used as flags
authorMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Thu, 8 Aug 2019 09:49:12 +0000 (17:49 +0800)
committerMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Fri, 9 Aug 2019 05:46:32 +0000 (13:46 +0800)
components/cxx/test/test_cxx.cpp
components/esp32/include/esp_attr.h
components/soc/include/hal/timer_types.h

index 0f5cce331853ee4ea4303dc5812e1e4156ac93f1..0bf92f324bae79986ac3924676c2dba0f330c039 100644 (file)
@@ -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<typename T> __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<timer_intr_t>();
+
+
+
+
index 58fef76c71aa0d5123ebf66f8e7a587a484b0a5e..34458948a774ff6f34ba59af4d97999779d0f9b4 100644 (file)
 // 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"
index 8ab5757f288891132b1c2befaa930e9f6c73be68..e9bcc9985d85c2bcd1ac38ac637d7bafbae99301 100644 (file)
@@ -40,7 +40,6 @@ typedef enum {
     TIMER_START = 1, /*!<Start timer counter*/
 } timer_start_t;
 
-
 /**
  * @brief Interrupt types of the timer.
  */
@@ -50,6 +49,7 @@ typedef enum {
     TIMER_INTR_T1 = BIT(1), /*!< interrupt of timer 1 */
     TIMER_INTR_WDT = BIT(2), /*!< interrupt of watchdog */
 } timer_intr_t;
+FLAG_ATTR(timer_intr_t)
 
 /**
  * @brief Behavior of the watchdog if a stage times out.