Fix compile errors about shift counts too large.
authorCary Coutant <ccoutant@gmail.com>
Sun, 7 Feb 2016 02:18:51 +0000 (18:18 -0800)
committerCary Coutant <ccoutant@gmail.com>
Sun, 7 Feb 2016 02:19:13 +0000 (18:19 -0800)
In order to get around the optimizer and newer compiler warnings
about shift counts, the overflow checking code had resorted to
some messy shifting, and with the never-before-seen instantiations
of the template functions, we were still running afoul of the
compiler checks.

This patch replaces those messy shift sequences with a simple
class template that provides the min and max limits for any
bit size up to 64, with a specialization for 64 that prevents
the compiler from complaining.

gold/
PR gold/19577
* reloc.h (Limits): New class.
(Bits::has_overflow32): Use min/max values from Limits.
(Bits::has_unsigned_overflow32): Likewise.
(Bits::has_signed_unsigned_overflow32): Likewise.
(Bits::has_overflow): Likewise.
(Bits::has_unsigned_overflow): Likewise.
(Bits::has_signed_unsigned_overflow64): Likewise.

gold/ChangeLog
gold/reloc.h

index 628547e..e114198 100644 (file)
@@ -1,5 +1,16 @@
 2016-02-06  Cary Coutant  <ccoutant@gmail.com>
 
+       PR gold/19577
+       * reloc.h (Limits): New class.
+       (Bits::has_overflow32): Use min/max values from Limits.
+       (Bits::has_unsigned_overflow32): Likewise.
+       (Bits::has_signed_unsigned_overflow32): Likewise.
+       (Bits::has_overflow): Likewise.
+       (Bits::has_unsigned_overflow): Likewise.
+       (Bits::has_signed_unsigned_overflow64): Likewise.
+
+2016-02-06  Cary Coutant  <ccoutant@gmail.com>
+
        PR gold/19567
        * reloc.h (Relocate_functions::Overflow_check): Add comments.
        * x86_64.cc (X86_64_relocate_functions): New class.
index 72f6c46..0730a45 100644 (file)
@@ -974,6 +974,26 @@ class Relocate_functions
                              CHECK_NONE); }
 };
 
+// Convenience class for min and max values of a given BITS length.
+
+template<int bits>
+class Limits
+{
+ public:
+  static const uint64_t MAX_UNSIGNED = (1ULL << bits) - 1;
+  static const int64_t MAX_SIGNED = MAX_UNSIGNED >> 1;
+  static const int64_t MIN_SIGNED = -MAX_SIGNED - 1;
+};
+
+template<>
+class Limits<64>
+{
+ public:
+  static const uint64_t MAX_UNSIGNED = ~0ULL;
+  static const int64_t MAX_SIGNED = MAX_UNSIGNED >> 1;
+  static const int64_t MIN_SIGNED = -MAX_SIGNED - 1;
+};
+
 // Integer manipulation functions used by various targets when
 // performing relocations.
 
@@ -1006,8 +1026,8 @@ class Bits
     gold_assert(bits > 0 && bits <= 32);
     if (bits == 32)
       return false;
-    int32_t max = (1 << (bits - 1)) - 1;
-    int32_t min = -(1 << (bits - 1));
+    const int32_t max = static_cast<int32_t>(Limits<bits>::MAX_SIGNED);
+    const int32_t min = static_cast<int32_t>(Limits<bits>::MIN_SIGNED);
     int32_t as_signed = static_cast<int32_t>(val);
     return as_signed > max || as_signed < min;
   }
@@ -1020,7 +1040,7 @@ class Bits
     gold_assert(bits > 0 && bits <= 32);
     if (bits == 32)
       return false;
-    uint32_t max = static_cast<uint32_t>((1U << bits) - 1);
+    const uint32_t max = static_cast<uint32_t>(Limits<bits>::MAX_UNSIGNED);
     return val > max;
   }
 
@@ -1034,8 +1054,8 @@ class Bits
     gold_assert(bits > 0 && bits <= 32);
     if (bits == 32)
       return false;
-    int32_t max = static_cast<int32_t>((1U << bits) - 1);
-    int32_t min = -(1 << (bits - 1));
+    const int32_t max = static_cast<int32_t>(Limits<bits>::MAX_UNSIGNED);
+    const int32_t min = static_cast<int32_t>(Limits<bits>::MIN_SIGNED);
     int32_t as_signed = static_cast<int32_t>(val);
     return as_signed > max || as_signed < min;
   }
@@ -1072,8 +1092,8 @@ class Bits
     gold_assert(bits > 0 && bits <= 64);
     if (bits == 64)
       return false;
-    int64_t max = (static_cast<int64_t>(1) << (bits - 1)) - 1;
-    int64_t min = -(static_cast<int64_t>(1) << (bits - 1));
+    const int64_t max = Limits<bits>::MAX_SIGNED;
+    const int64_t min = Limits<bits>::MIN_SIGNED;
     int64_t as_signed = static_cast<int64_t>(val);
     return as_signed > max || as_signed < min;
   }
@@ -1086,7 +1106,7 @@ class Bits
     gold_assert(bits > 0 && bits <= 64);
     if (bits == 64)
       return false;
-    uint64_t max = (static_cast<uint64_t>(1) << bits) - 1;
+    const uint64_t max = Limits<bits>::MAX_UNSIGNED;
     return val > max;
   }
 
@@ -1100,8 +1120,8 @@ class Bits
     gold_assert(bits > 0 && bits <= 64);
     if (bits == 64)
       return false;
-    int64_t max = static_cast<int64_t>((static_cast<uint64_t>(1) << bits) - 1);
-    int64_t min = -(static_cast<int64_t>(1) << (bits - 1));
+    const int64_t max = static_cast<int64_t>(Limits<bits>::MAX_UNSIGNED);
+    const int64_t min = Limits<bits>::MIN_SIGNED;
     int64_t as_signed = static_cast<int64_t>(val);
     return as_signed > max || as_signed < min;
   }