Fix shaders with invariant keyword.

We would trigger assertion failures in Debug mode, and fail to
parse and translate correctly in Release.

BUG=angle:711

Change-Id: Ibb7f33b288376617598578f48c7bbdbdec044279
Reviewed-on: https://chromium-review.googlesource.com/210822
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index ba9ef5e..7260799 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -72,37 +72,7 @@
     EbtInvariant          // used as a type when qualifying a previously declared variable as being invariant
 };
 
-inline const char* getBasicString(TBasicType t)
-{
-    switch (t)
-    {
-      case EbtVoid:                 return "void";                 break;
-      case EbtFloat:                return "float";                break;
-      case EbtInt:                  return "int";                  break;
-      case EbtUInt:                 return "uint";                 break;
-      case EbtBool:                 return "bool";                 break;
-      case EbtSampler2D:            return "sampler2D";            break;
-      case EbtSampler3D:            return "sampler3D";            break;
-      case EbtSamplerCube:          return "samplerCube";          break;
-      case EbtSamplerExternalOES:   return "samplerExternalOES";   break;
-      case EbtSampler2DRect:        return "sampler2DRect";        break;
-      case EbtSampler2DArray:       return "sampler2DArray";       break;
-      case EbtISampler2D:           return "isampler2D";           break;
-      case EbtISampler3D:           return "isampler3D";           break;
-      case EbtISamplerCube:         return "isamplerCube";         break;
-      case EbtISampler2DArray:      return "isampler2DArray";      break;
-      case EbtUSampler2D:           return "usampler2D";           break;
-      case EbtUSampler3D:           return "usampler3D";           break;
-      case EbtUSamplerCube:         return "usamplerCube";         break;
-      case EbtUSampler2DArray:      return "usampler2DArray";      break;
-      case EbtSampler2DShadow:      return "sampler2DShadow";      break;
-      case EbtSamplerCubeShadow:    return "samplerCubeShadow";    break;
-      case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break;
-      case EbtStruct:               return "structure";            break;
-      case EbtInterfaceBlock:       return "interface block";      break;
-      default:                      return "unknown type";
-    }
-}
+const char* getBasicString(TBasicType t);
 
 inline bool IsSampler(TBasicType type)
 {
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 7839c04..09f7ad9 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -81,9 +81,11 @@
 {
     TInfoSinkBase &out = objSink();
     TQualifier qualifier = type.getQualifier();
-    // TODO(alokp): Validate qualifier for variable declarations.
-    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+    if (qualifier != EvqTemporary && qualifier != EvqGlobal &&
+        type.getBasicType() != EbtInvariant)
+    {
         out << type.getQualifierString() << " ";
+    }
     // Declare the struct if we have not done so already.
     if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
     {
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index ed082c9..93994ba 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1937,6 +1937,12 @@
             }
             else if (variable && IsVaryingOut(variable->getQualifier()))
             {
+                // Skip translation of invariant declarations
+                if (variable->getBasicType() == EbtInvariant)
+                {
+                    return false;
+                }
+
                 for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
                 {
                     TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index bafad0d..d39ab01 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -13,6 +13,39 @@
 #include <algorithm>
 #include <climits>
 
+const char* getBasicString(TBasicType t)
+{
+    switch (t)
+    {
+      case EbtVoid:                 return "void";                 break;
+      case EbtFloat:                return "float";                break;
+      case EbtInt:                  return "int";                  break;
+      case EbtUInt:                 return "uint";                 break;
+      case EbtBool:                 return "bool";                 break;
+      case EbtSampler2D:            return "sampler2D";            break;
+      case EbtSampler3D:            return "sampler3D";            break;
+      case EbtSamplerCube:          return "samplerCube";          break;
+      case EbtSamplerExternalOES:   return "samplerExternalOES";   break;
+      case EbtSampler2DRect:        return "sampler2DRect";        break;
+      case EbtSampler2DArray:       return "sampler2DArray";       break;
+      case EbtISampler2D:           return "isampler2D";           break;
+      case EbtISampler3D:           return "isampler3D";           break;
+      case EbtISamplerCube:         return "isamplerCube";         break;
+      case EbtISampler2DArray:      return "isampler2DArray";      break;
+      case EbtUSampler2D:           return "usampler2D";           break;
+      case EbtUSampler3D:           return "usampler3D";           break;
+      case EbtUSamplerCube:         return "usamplerCube";         break;
+      case EbtUSampler2DArray:      return "usampler2DArray";      break;
+      case EbtSampler2DShadow:      return "sampler2DShadow";      break;
+      case EbtSamplerCubeShadow:    return "samplerCubeShadow";    break;
+      case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break;
+      case EbtStruct:               return "structure";            break;
+      case EbtInterfaceBlock:       return "interface block";      break;
+      case EbtInvariant:            return "invariant";            break;
+      default: UNREACHABLE();       return "unknown type";
+    }
+}
+
 TType::TType(const TPublicType &p)
     : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier),
       primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize),
diff --git a/src/compiler/translator/VariableInfo.cpp b/src/compiler/translator/VariableInfo.cpp
index 153455c..0bd95cb 100644
--- a/src/compiler/translator/VariableInfo.cpp
+++ b/src/compiler/translator/VariableInfo.cpp
@@ -320,6 +320,8 @@
       case EOpDeclaration:
         {
             const TIntermSequence &sequence = *(node->getSequence());
+            ASSERT(!sequence.empty());
+
             const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
             TQualifier qualifier = typedNode.getQualifier();
 
@@ -344,14 +346,16 @@
                     visitInfoList(sequence, mUniforms);
                     break;
                   default:
-                    visitInfoList(sequence, mVaryings);
+                    // do not traverse invariant declarations such as
+                    //  "invariant gl_Position;"
+                    if (typedNode.getBasicType() != EbtInvariant)
+                    {
+                        visitInfoList(sequence, mVaryings);
+                    }
                     break;
                 }
 
-                if (!sequence.empty())
-                {
-                    visitChildren = false;
-                }
+                visitChildren = false;
             }
             break;
         }
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
index 85c89ca..46ce99c 100644
--- a/src/compiler/translator/util.cpp
+++ b/src/compiler/translator/util.cpp
@@ -268,6 +268,8 @@
       case EvqFragmentIn:
       case EvqVaryingIn:
       case EvqVaryingOut:
+      case EvqInvariantVaryingIn:
+      case EvqInvariantVaryingOut:
         return INTERPOLATION_SMOOTH;
 
       case EvqCentroidIn: