Add support for implicit array size

ESSL3 introduces implicit array size that is determined automatically
according to the initializer. Implicit sizes are resolved when parsing
constructors and when initializers are evaluated, so ANGLE's AST will not
contain implicit sizes.

Declarations where there are two differently sized arrays with the same
implicitly sized type, for example:

float[] a = float[](0.0), b = float[](0.0, 1.0);

will be transformed into declarations where the two arrays don't share
the array size like this:

float a[1] = float[1](0.0), float b[2] = float[2](0.0, 1.0);

so they are not a problem.

Unlike sized arrays, implicitly sized arrays don't have a size limit
enforced by the parser.

Include a test that verifies that non-initialization of an implicitly
sized array defined using ESSL3 type syntax is caught by the parser.

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

TEST=WebGL 2 conformance tests, angle_unittests
BUG=angleproject:941

Change-Id: Ib55b7601848102a103af9db284a80f09abaeb021
Reviewed-on: https://chromium-review.googlesource.com/265653
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 27eed39..fefd531 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -512,9 +512,17 @@
     if (constType)
         type->setQualifier(EvqConst);
 
-    if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
-        error(line, "array constructor needs one argument per array element", "constructor");
-        return true;
+    if (type->isArray())
+    {
+        if (type->isUnsizedArray())
+        {
+            type->setArraySize(function.getParamCount());
+        }
+        else if (static_cast<size_t>(type->getArraySize()) != function.getParamCount())
+        {
+            error(line, "array constructor needs one argument per array element", "constructor");
+            return true;
+        }
     }
 
     if (arrayArg && op != EOpConstructStruct) {
@@ -763,7 +771,7 @@
 //
 // Returns true if there was an error.
 //
-bool TParseContext::nonInitConstErrorCheck(const TSourceLoc &line, const TString &identifier, TPublicType *type)
+bool TParseContext::nonInitErrorCheck(const TSourceLoc &line, const TString &identifier, TPublicType *type)
 {
     ASSERT(type != nullptr);
     if (type->qualifier == EvqConst)
@@ -784,6 +792,11 @@
 
         return true;
     }
+    if (type->isUnsizedArray())
+    {
+        error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
+        return true;
+    }
     return false;
 }
 
@@ -1083,6 +1096,10 @@
     TType type = TType(pType);
 
     TVariable *variable = nullptr;
+    if (type.isUnsizedArray())
+    {
+        type.setArraySize(initializer->getArraySize());
+    }
     if (!declareVariable(line, identifier, type, &variable))
     {
         return true;
@@ -1252,7 +1269,7 @@
         if (singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
             recover();
 
-        if (nonInitConstErrorCheck(identifierOrTypeLocation, identifier, &publicType))
+        if (nonInitErrorCheck(identifierOrTypeLocation, identifier, &publicType))
             recover();
 
         TVariable *variable = nullptr;
@@ -1277,7 +1294,7 @@
     if (singleDeclarationErrorCheck(publicType, identifierLocation))
         recover();
 
-    if (nonInitConstErrorCheck(identifierLocation, identifier, &publicType))
+    if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
         recover();
 
     if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
@@ -1353,8 +1370,9 @@
 
     TPublicType arrayType(publicType);
 
-    int size;
-    if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    int size = 0;
+    // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
+    if (indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
     {
         recover();
     }
@@ -1428,7 +1446,7 @@
     if (locationDeclaratorListCheck(identifierLocation, publicType))
         recover();
 
-    if (nonInitConstErrorCheck(identifierLocation, identifier, &publicType))
+    if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
         recover();
 
     TVariable *variable = nullptr;
@@ -1457,7 +1475,7 @@
     if (locationDeclaratorListCheck(identifierLocation, publicType))
         recover();
 
-    if (nonInitConstErrorCheck(identifierLocation, identifier, &publicType))
+    if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
         recover();
 
     if (arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
@@ -1551,8 +1569,9 @@
 
     TPublicType arrayType(publicType);
 
-    int size;
-    if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    int size = 0;
+    // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
+    if (indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
     {
         recover();
     }
@@ -2873,6 +2892,7 @@
             error(loc, "Invalid operation for arrays", GetOperatorString(op));
             return false;
         }
+        // At this point, size of implicitly sized arrays should be resolved.
         if (left->getArraySize() != right->getArraySize())
         {
             error(loc, "array size mismatch", GetOperatorString(op));