Seems to me the variable templates in Endian.h are not specific to enums and may as well be called little_t and big_t.  Thoughts?<br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 8, 2019 at 10:03 AM Pavel Labath via Phabricator <<a href="mailto:reviews@reviews.llvm.org">reviews@reviews.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">labath created this revision.<br>
labath added reviewers: Bigcheese, zturner.<br>
Herald added a subscriber: kristina.<br>
Herald added a project: LLVM.<br>
<br>
Binary formats often include various enumerations or bitsets, but using<br>
endian-specific types for accessing them is tricky because they<br>
currently only support integral types. This is particularly true for<br>
scoped enums (enum class), as these are not implicitly convertible to<br>
integral types, and so one has to perform two casts just to read the<br>
enum value.<br>
<br>
This fixes that support by adding first-class support for enumeration<br>
types to endian-specific types. The support for them was already almost<br>
working -- all I needed to do was overload getSwappedBytes for<br>
enumeration types (which casts the enum to its underlying type and performs the<br>
conversion there). I also add some convenience template aliases to simplify<br>
declaring endian-specific enums.<br>
<br>
<br>
Repository:<br>
  rL LLVM<br>
<br>
<a href="https://reviews.llvm.org/D59141" rel="noreferrer" target="_blank">https://reviews.llvm.org/D59141</a><br>
<br>
Files:<br>
  include/llvm/Support/Endian.h<br>
  include/llvm/Support/SwapByteOrder.h<br>
  unittests/Support/EndianTest.cpp<br>
<br>
<br>
Index: unittests/Support/EndianTest.cpp<br>
===================================================================<br>
--- unittests/Support/EndianTest.cpp<br>
+++ unittests/Support/EndianTest.cpp<br>
@@ -200,4 +200,13 @@<br>
   EXPECT_EQ(*big_val, *little_val);<br>
 }<br>
<br>
+TEST(Endian, PacketEndianSpecificIntegralAsEnum) {<br>
+  enum class Test : uint16_t { ONETWO = 0x0102, TWOONE = 0x0201 };<br>
+  unsigned char bytes[] = {0x01, 0x02};<br>
+  using LittleTest = little_enum_t<Test>;<br>
+  using BigTest = big_enum_t<Test>;<br>
+  EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes));<br>
+  EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes));<br>
+}<br>
+<br>
 } // end anon namespace<br>
Index: include/llvm/Support/SwapByteOrder.h<br>
===================================================================<br>
--- include/llvm/Support/SwapByteOrder.h<br>
+++ include/llvm/Support/SwapByteOrder.h<br>
@@ -115,6 +115,13 @@<br>
   return out.d;<br>
 }<br>
<br>
+template <typename T><br>
+inline typename std::enable_if<std::is_enum<T>::value, T>::type<br>
+getSwappedBytes(T C) {<br>
+  return static_cast<T>(<br>
+      getSwappedBytes(static_cast<typename std::underlying_type<T>::type>(C)));<br>
+}<br>
+<br>
 template<typename T><br>
 inline void swapByteOrder(T &Value) {<br>
   Value = getSwappedBytes(Value);<br>
Index: include/llvm/Support/Endian.h<br>
===================================================================<br>
--- include/llvm/Support/Endian.h<br>
+++ include/llvm/Support/Endian.h<br>
@@ -338,6 +338,12 @@<br>
 using unaligned_int64_t =<br>
     detail::packed_endian_specific_integral<int64_t, native, unaligned>;<br>
<br>
+template <typename T><br>
+using little_enum_t =<br>
+    detail::packed_endian_specific_integral<T, little, unaligned>;<br>
+template <typename T><br>
+using big_enum_t = detail::packed_endian_specific_integral<T, big, unaligned>;<br>
+<br>
 namespace endian {<br>
<br>
 template <typename T> inline T read(const void *P, endianness E) {<br>
<br>
<br>
</blockquote></div>