Add parser support for initializing sized arrays

Still missing from this patch: HLSL output, implicitly sized arrays.

Tested with WebGL 2 test sdk/tests/deqp/data/gles3/shaders/arrays.html

TEST=WebGL 2 conformance tests
BUG=angleproject:941

Change-Id: I900f2af843fd8046f23dd4b77352e77026bbba84
Reviewed-on: https://chromium-review.googlesource.com/265652
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 5a6b60a..27eed39 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1333,6 +1333,48 @@
     }
 }
 
+TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(TPublicType &publicType,
+                                                                 const TSourceLoc &identifierLocation,
+                                                                 const TString &identifier,
+                                                                 const TSourceLoc &indexLocation,
+                                                                 TIntermTyped *indexExpression,
+                                                                 const TSourceLoc &initLocation,
+                                                                 TIntermTyped *initializer)
+{
+    mDeferredSingleDeclarationErrorCheck = false;
+
+    if (singleDeclarationErrorCheck(publicType, identifierLocation))
+        recover();
+
+    if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
+    {
+        recover();
+    }
+
+    TPublicType arrayType(publicType);
+
+    int size;
+    if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    {
+        recover();
+    }
+    // Make the type an array even if size check failed.
+    // This ensures useless error messages regarding the variable's non-arrayness won't follow.
+    arrayType.setArraySize(size);
+
+    // initNode will correspond to the whole of "type b[n] = initializer".
+    TIntermNode *initNode = nullptr;
+    if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+    {
+        return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
+    }
+    else
+    {
+        recover();
+        return nullptr;
+    }
+}
+
 TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
                                                            const TSourceLoc &identifierLoc,
                                                            const TString *identifier,
@@ -1483,6 +1525,61 @@
     }
 }
 
+TIntermAggregate *TParseContext::parseArrayInitDeclarator(TPublicType &publicType,
+                                                          TIntermAggregate *aggregateDeclaration,
+                                                          const TSourceLoc& identifierLocation,
+                                                          const TString &identifier,
+                                                          const TSourceLoc& indexLocation,
+                                                          TIntermTyped *indexExpression,
+                                                          const TSourceLoc &initLocation, TIntermTyped *initializer)
+{
+    // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
+    if (mDeferredSingleDeclarationErrorCheck)
+    {
+        if (singleDeclarationErrorCheck(publicType, identifierLocation))
+            recover();
+        mDeferredSingleDeclarationErrorCheck = false;
+    }
+
+    if (locationDeclaratorListCheck(identifierLocation, publicType))
+        recover();
+
+    if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
+    {
+        recover();
+    }
+
+    TPublicType arrayType(publicType);
+
+    int size;
+    if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    {
+        recover();
+    }
+    // Make the type an array even if size check failed.
+    // This ensures useless error messages regarding the variable's non-arrayness won't follow.
+    arrayType.setArraySize(size);
+
+    // initNode will correspond to the whole of "b[n] = initializer".
+    TIntermNode *initNode = nullptr;
+    if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+    {
+        if (initNode)
+        {
+            return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
+        }
+        else
+        {
+            return aggregateDeclaration;
+        }
+    }
+    else
+    {
+        recover();
+        return nullptr;
+    }
+}
+
 void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
 {
     if (typeQualifier.qualifier != EvqUniform)