Fix build with clang on big-endian targets (#4440)
authorKhem Raj <raj.khem@gmail.com>
Thu, 21 Sep 2017 15:51:08 +0000 (08:51 -0700)
committerWouter van Oortmerssen <aardappel@gmail.com>
Thu, 21 Sep 2017 15:51:08 +0000 (08:51 -0700)
* flatbuffers: Move EndianSwap template to flatbuffers/base.h

Clang complains
call to function 'EndianSwap' that is neither visible in the template definition nor found by argument-dependent lookup
     return EndianSwap(t);

This seems to be due to limitation of two-phase lookup of dependent names in template definitions

Its not being found using associated namespaces therefore
it has to be made visible at the template definition site as well

Signed-off-by: Khem Raj <raj.khem@gmail.com>
* use __builtin_bswap16 when building with clang

clang pretends to be gcc 4.2.0 and therefore the code does
not use __builtin_bswap16 but tries to synthesize it

Signed-off-by: Khem Raj <raj.khem@gmail.com>
include/flatbuffers/base.h
include/flatbuffers/flatbuffers.h

index a96c856..538784a 100644 (file)
@@ -167,6 +167,39 @@ typedef uintmax_t largest_scalar_t;
 // We support aligning the contents of buffers up to this size.
 #define FLATBUFFERS_MAX_ALIGNMENT 16
 
+template<typename T> T EndianSwap(T t) {
+  #if defined(_MSC_VER)
+    #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
+    #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
+    #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
+  #else
+    #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
+      // __builtin_bswap16 was missing prior to GCC 4.8.
+      #define FLATBUFFERS_BYTESWAP16(x) \
+        static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
+    #else
+      #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
+    #endif
+    #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
+    #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
+  #endif
+  if (sizeof(T) == 1) {   // Compile-time if-then's.
+    return t;
+  } else if (sizeof(T) == 2) {
+    auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
+    return *reinterpret_cast<T *>(&r);
+  } else if (sizeof(T) == 4) {
+    auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
+    return *reinterpret_cast<T *>(&r);
+  } else if (sizeof(T) == 8) {
+    auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
+    return *reinterpret_cast<T *>(&r);
+  } else {
+    assert(0);
+  }
+}
+
+
 template<typename T> T EndianScalar(T t) {
   #if FLATBUFFERS_LITTLEENDIAN
     return t;
index 627f097..b7bad53 100644 (file)
@@ -37,38 +37,6 @@ inline void EndianCheck() {
   (void)endiantest;
 }
 
-template<typename T> T EndianSwap(T t) {
-  #if defined(_MSC_VER)
-    #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
-    #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
-    #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
-  #else
-    #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408
-      // __builtin_bswap16 was missing prior to GCC 4.8.
-      #define FLATBUFFERS_BYTESWAP16(x) \
-        static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
-    #else
-      #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
-    #endif
-    #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
-    #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
-  #endif
-  if (sizeof(T) == 1) {   // Compile-time if-then's.
-    return t;
-  } else if (sizeof(T) == 2) {
-    auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
-    return *reinterpret_cast<T *>(&r);
-  } else if (sizeof(T) == 4) {
-    auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
-    return *reinterpret_cast<T *>(&r);
-  } else if (sizeof(T) == 8) {
-    auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
-    return *reinterpret_cast<T *>(&r);
-  } else {
-    assert(0);
-  }
-}
-
 template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
   #ifdef _MSC_VER
     return __alignof(T);