Fold ternary and comma ops only after parsing is done

In case folding a ternary op or a comma op would change the qualifier
of the expression, the folding is deferred to a separate traversal
step.

After this there are no more cases where the type of a TIntermSymbol
node needs to differ from the type of the variable it is referring to.
There are still some cases where some parts of TIntermSymbol type are
changed while keeping the TVariable type the same though, like when
assigning array size to gl_PerVertex nodes or sanitizing qualifiers of
struct declarations.

BUG=angleproject:2267
TEST=angle_unittests, angle_end2end_tests

Change-Id: I1501c8d361f5f765f43ca810d1b7248d9e2c5986
Reviewed-on: https://chromium-review.googlesource.com/850672
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index c4ded7a..a50b125 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -18,6 +18,7 @@
 #include "compiler/translator/DeferGlobalInitializers.h"
 #include "compiler/translator/EmulateGLFragColorBroadcast.h"
 #include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/FoldExpressions.h"
 #include "compiler/translator/Initialize.h"
 #include "compiler/translator/InitializeVariables.h"
 #include "compiler/translator/IntermNodePatternMatcher.h"
@@ -399,6 +400,18 @@
         return false;
     }
 
+    if (shouldRunLoopAndIndexingValidation(compileOptions) &&
+        !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics))
+    {
+        return false;
+    }
+
+    // Fold expressions that could not be folded before validation that was done as a part of
+    // parsing.
+    FoldExpressions(root, &mDiagnostics);
+    // Folding should only be able to generate warnings.
+    ASSERT(mDiagnostics.numErrors() == 0);
+
     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
     // The following kinds of no-ops are pruned:
     //   1. Empty declarations "int;".
@@ -454,12 +467,6 @@
         return false;
     }
 
-    if (shouldRunLoopAndIndexingValidation(compileOptions) &&
-        !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics))
-    {
-        return false;
-    }
-
     // Fail compilation if precision emulation not supported.
     if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
         !EmulatePrecision::SupportedInLanguage(outputType))