Fix constant folding right shift corner cases

Right-shifting the minimum signed integer needs to be handled as a
special case, since it can't go through the usual path that clears the
sign bit.

Code for right-shifting by zero also had a typo that resulted in
setting the wrong value to the result.

BUG=chromium:662706
TEST=angle_unittests

Change-Id: Ief24d738064906a72212242e0917ce30e45d6b25
Reviewed-on: https://chromium-review.googlesource.com/408158
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ConstantUnion.cpp b/src/compiler/translator/ConstantUnion.cpp
index 1ee3f64..66f444b 100644
--- a/src/compiler/translator/ConstantUnion.cpp
+++ b/src/compiler/translator/ConstantUnion.cpp
@@ -423,27 +423,42 @@
                 // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
                 // the sign bit." In C++ shifting negative integers is undefined, so we implement
                 // extending the sign bit manually.
-                bool extendSignBit = false;
                 int lhsSafe        = lhs.iConst;
-                if (lhsSafe < 0)
+                if (lhsSafe == std::numeric_limits<int>::min())
                 {
-                    extendSignBit = true;
-                    // Clear the sign bit so that bitshift right is defined in C++.
-                    lhsSafe &= 0x7fffffff;
-                    ASSERT(lhsSafe > 0);
+                    // The min integer needs special treatment because only bit it has set is the
+                    // sign bit, which we clear later to implement safe right shift of negative
+                    // numbers.
+                    lhsSafe = -0x40000000;
+                    --shiftOffset;
                 }
-                returnValue.setIConst(lhsSafe >> shiftOffset);
-
-                // Manually fill in the extended sign bit if necessary.
-                if (extendSignBit)
+                if (shiftOffset > 0)
                 {
-                    int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
-                    returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
+                    bool extendSignBit = false;
+                    if (lhsSafe < 0)
+                    {
+                        extendSignBit = true;
+                        // Clear the sign bit so that bitshift right is defined in C++.
+                        lhsSafe &= 0x7fffffff;
+                        ASSERT(lhsSafe > 0);
+                    }
+                    returnValue.setIConst(lhsSafe >> shiftOffset);
+
+                    // Manually fill in the extended sign bit if necessary.
+                    if (extendSignBit)
+                    {
+                        int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
+                        returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
+                    }
+                }
+                else
+                {
+                    returnValue.setIConst(lhsSafe);
                 }
             }
             else
             {
-                returnValue.setIConst(rhs.iConst);
+                returnValue.setIConst(lhs.iConst);
             }
             break;
         }