Replace RAPIDJSON_CLZLL with internal clzll (#1660)

RAPIDJSON_CLZLL is defined as macro of __builtin_clzll when
using gcc to compile. This introduces two issues:
1. in gcc __builtin_clzll returns int, not uint32_t.
2. __builtin_clzll return is undefined when input x is 0
See: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

This patch removes RAPIDJSON_CLZLL, merges __builtin_clzll to
internal clzll with input check and return value explicit cast.

Change-Id: Iac4b355dc5e5b4ed9b3f35a640b6b5537e76f22c
Signed-off-by: Jun He <jun.he@arm.com>

Co-authored-by: Jun He <jun.he@arm.com>
diff --git a/include/rapidjson/internal/clzll.h b/include/rapidjson/internal/clzll.h
index abe44df..6cd7923 100644
--- a/include/rapidjson/internal/clzll.h
+++ b/include/rapidjson/internal/clzll.h
@@ -29,10 +29,6 @@
 RAPIDJSON_NAMESPACE_BEGIN
 namespace internal {
 
-#if (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
-#define RAPIDJSON_CLZLL __builtin_clzll
-#else
-
 inline uint32_t clzll(uint64_t x) {
     // Passing 0 to __builtin_clzll is UB in GCC and results in an
     // infinite loop in the software implementation.
@@ -52,7 +48,11 @@
 #endif // _WIN64
 
     return 63 - r;
+#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
+    // __builtin_clzll wrapper
+    return static_cast<uint32_t>(__builtin_clzll(x));
 #else
+    // naive version
     uint32_t r;
     while (!(x & (static_cast<uint64_t>(1) << 63))) {
         x <<= 1;
@@ -64,9 +64,8 @@
 }
 
 #define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
-#endif // (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
 
 } // namespace internal
 RAPIDJSON_NAMESPACE_END
 
-#endif // RAPIDJSON_CLZLL_H_
\ No newline at end of file
+#endif // RAPIDJSON_CLZLL_H_
diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h
index f46059a..8f7d853 100644
--- a/include/rapidjson/internal/diyfp.h
+++ b/include/rapidjson/internal/diyfp.h
@@ -100,7 +100,7 @@
     }
 
     DiyFp Normalize() const {
-        int s = static_cast<int>(RAPIDJSON_CLZLL(f));
+        int s = static_cast<int>(clzll(f));
         return DiyFp(f << s, e - s);
     }
 
diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h
index 2d73b19..0f85032 100644
--- a/include/rapidjson/reader.h
+++ b/include/rapidjson/reader.h
@@ -450,11 +450,11 @@
 
         if (low == 0) {
             if (high != 0) {
-                uint32_t lz = RAPIDJSON_CLZLL(high);
+                uint32_t lz = internal::clzll(high);
                 return p + 8 + (lz >> 3);
             }
         } else {
-            uint32_t lz = RAPIDJSON_CLZLL(low);
+            uint32_t lz = internal::clzll(low);
             return p + (lz >> 3);
         }
     }
@@ -486,11 +486,11 @@
 
         if (low == 0) {
             if (high != 0) {
-                uint32_t lz = RAPIDJSON_CLZLL(high);
+                uint32_t lz = internal::clzll(high);
                 return p + 8 + (lz >> 3);
             }
         } else {
-            uint32_t lz = RAPIDJSON_CLZLL(low);
+            uint32_t lz = internal::clzll(low);
             return p + (lz >> 3);
         }
     }
@@ -1257,12 +1257,12 @@
             bool escaped = false;
             if (low == 0) {
                 if (high != 0) {
-                    uint32_t lz = RAPIDJSON_CLZLL(high);
+                    uint32_t lz = internal::clzll(high);
                     length = 8 + (lz >> 3);
                     escaped = true;
                 }
             } else {
-                uint32_t lz = RAPIDJSON_CLZLL(low);
+                uint32_t lz = internal::clzll(low);
                 length = lz >> 3;
                 escaped = true;
             }
@@ -1327,12 +1327,12 @@
             bool escaped = false;
             if (low == 0) {
                 if (high != 0) {
-                    uint32_t lz = RAPIDJSON_CLZLL(high);
+                    uint32_t lz = internal::clzll(high);
                     length = 8 + (lz >> 3);
                     escaped = true;
                 }
             } else {
-                uint32_t lz = RAPIDJSON_CLZLL(low);
+                uint32_t lz = internal::clzll(low);
                 length = lz >> 3;
                 escaped = true;
             }
@@ -1381,12 +1381,12 @@
 
             if (low == 0) {
                 if (high != 0) {
-                    uint32_t lz = RAPIDJSON_CLZLL(high);
+                    uint32_t lz = internal::clzll(high);
                     p += 8 + (lz >> 3);
                     break;
                 }
             } else {
-                uint32_t lz = RAPIDJSON_CLZLL(low);
+                uint32_t lz = internal::clzll(low);
                 p += lz >> 3;
                 break;
             }
diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h
index ce39e76..e7fb873 100644
--- a/include/rapidjson/writer.h
+++ b/include/rapidjson/writer.h
@@ -676,12 +676,12 @@
         bool escaped = false;
         if (low == 0) {
             if (high != 0) {
-                uint32_t lz = RAPIDJSON_CLZLL(high);
+                uint32_t lz = internal::clzll(high);
                 len = 8 + (lz >> 3);
                 escaped = true;
             }
         } else {
-            uint32_t lz = RAPIDJSON_CLZLL(low);
+            uint32_t lz = internal::clzll(low);
             len = lz >> 3;
             escaped = true;
         }