From fb7044a9a8918dafd8dfff1d4e57fdba1cc32f1c Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Thu, 13 Jun 2013 20:16:43 +0000
Subject: [PATCH] Semantic checks: ES doesn't have unsized arrays or noise*().

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21998 e7fa87d3-cd2b-0410-9028-fcbf551c1848
---
 Test/300.vert                              |  8 +++++
 Test/300BuiltIns.frag                      |  3 ++
 Test/array100.frag                         |  9 +----
 Test/cppSimple.vert                        |  3 ++
 glslang/MachineIndependent/Initialize.cpp  | 42 +++++++++++-----------
 glslang/MachineIndependent/ParseHelper.cpp | 27 +++++++-------
 glslang/MachineIndependent/ParseHelper.h   |  2 +-
 glslang/MachineIndependent/glslang.y       | 28 ++++++++++++---
 8 files changed, 76 insertions(+), 46 deletions(-)

diff --git a/Test/300.vert b/Test/300.vert
index 96c74b443..19f62d4a1 100644
--- a/Test/300.vert
+++ b/Test/300.vert
@@ -40,3 +40,11 @@ void main()
 #error GL_ES is not set
 #endif
 }
+
+float badsize[];    // ERROR
+float[] badsize2;   // ERROR
+uniform ub {
+    int a[];        // ERROR
+} ubInst[];         // ERROR
+void foo(int a[]);  // ERROR
+float okayA[] = float[](3.0, 4.0);  // Okay
diff --git a/Test/300BuiltIns.frag b/Test/300BuiltIns.frag
index 0c0844434..07cb7186a 100644
--- a/Test/300BuiltIns.frag
+++ b/Test/300BuiltIns.frag
@@ -65,4 +65,7 @@ void main()
     vec2 v16 = unpackUnorm2x16(uy);
     uint u17 = packHalf2x16(v2b);
     vec2 v18 = unpackHalf2x16(uy);
+
+    // not present
+    noise2(v18);
 }
diff --git a/Test/array100.frag b/Test/array100.frag
index 87c125b7d..6f0feb420 100644
--- a/Test/array100.frag
+++ b/Test/array100.frag
@@ -1,6 +1,6 @@
 #version 100
 
-float gu[];
+float gu[];              // ERROR
 float g4[4];
 float g5[5];
 
@@ -21,11 +21,6 @@ void main()
         gu[2] = 4.0;  // ERROR, overflow
     }
 
-    gu[2] = 4.0; // okay
-
-    gu[3] = 3.0;
-    gu[a] = 5.0; // ERROR
-
     g4 = foo(g5);
     g5 = g4;  // ERROR
     gu = g4;  // ERROR
@@ -36,8 +31,6 @@ void main()
     if (float[4](1.0, 2.0, 3.0, 4.0) == g4)  // ERROR
         gu[0] = 2.0;
 
-    float u[];
-    u[2] = 3.0; // okay
     float u[5];
     u[5] = 5.0; // ERROR
     foo(u);     // okay
diff --git a/Test/cppSimple.vert b/Test/cppSimple.vert
index 2dd9c3567..4cfa4f4eb 100644
--- a/Test/cppSimple.vert
+++ b/Test/cppSimple.vert
@@ -120,3 +120,6 @@ sum += 0.05;
 #if ((AA == BB || (AA == CC))))
 #error bad6
 #endif
+
+#define PASTE(a,b) a ## b
+float PASTE(tod, ay) = 17;
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index 4e278e67f..77f3ff17c 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -594,27 +594,29 @@ void TBuiltIns::initialize(int version, EProfile profile)
         //
         // Noise functions.
         //
-        s.append(TString("float noise1(float x);"));
-        s.append(TString("float noise1(vec2  x);"));
-        s.append(TString("float noise1(vec3  x);"));
-        s.append(TString("float noise1(vec4  x);"));
-
-        s.append(TString("vec2 noise2(float x);"));
-        s.append(TString("vec2 noise2(vec2  x);"));
-        s.append(TString("vec2 noise2(vec3  x);"));
-        s.append(TString("vec2 noise2(vec4  x);"));
-
-        s.append(TString("vec3 noise3(float x);"));
-        s.append(TString("vec3 noise3(vec2  x);"));
-        s.append(TString("vec3 noise3(vec3  x);"));
-        s.append(TString("vec3 noise3(vec4  x);"));
-
-        s.append(TString("vec4 noise4(float x);"));
-        s.append(TString("vec4 noise4(vec2  x);"));
-        s.append(TString("vec4 noise4(vec3  x);"));
-        s.append(TString("vec4 noise4(vec4  x);"));
+        if (profile != EEsProfile) {
+            s.append(TString("float noise1(float x);"));
+            s.append(TString("float noise1(vec2  x);"));
+            s.append(TString("float noise1(vec3  x);"));
+            s.append(TString("float noise1(vec4  x);"));
+
+            s.append(TString("vec2 noise2(float x);"));
+            s.append(TString("vec2 noise2(vec2  x);"));
+            s.append(TString("vec2 noise2(vec3  x);"));
+            s.append(TString("vec2 noise2(vec4  x);"));
+
+            s.append(TString("vec3 noise3(float x);"));
+            s.append(TString("vec3 noise3(vec2  x);"));
+            s.append(TString("vec3 noise3(vec3  x);"));
+            s.append(TString("vec3 noise3(vec4  x);"));
+
+            s.append(TString("vec4 noise4(float x);"));
+            s.append(TString("vec4 noise4(vec2  x);"));
+            s.append(TString("vec4 noise4(vec3  x);"));
+            s.append(TString("vec4 noise4(vec4  x);"));
 
-        s.append(TString("\n"));
+            s.append(TString("\n"));
+        }
     }
     {
         //============================================================================
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 01f3a9f26..a2b89070c 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -486,9 +486,9 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
 //
 // Returns true if there was an error in construction.
 //
-bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& function, TOperator op, TType& type)
 {
-    *type = function.getReturnType();
+    type = function.getReturnType();
 
     bool constructingMatrix = false;
     switch(op) {
@@ -535,7 +535,7 @@ bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& fun
             matrixInMatrix = true;
         if (full)
             overFull = true;
-        if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+        if (op != EOpConstructStruct && ! type.isArray() && size >= type.getObjectSize())
             full = true;
         if (function[i].type->getQualifier().storage != EvqConst)
             constType = false;
@@ -544,13 +544,13 @@ bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& fun
     }
     
     if (constType)
-        type->getQualifier().storage = EvqConst;
+        type.getQualifier().storage = EvqConst;
 
-    if (type->isArray()) {
-        if (type->getArraySize() == 0) {
+    if (type.isArray()) {
+        if (type.getArraySize() == 0) {
             // auto adapt the constructor type to the number of arguments
-            type->changeArraySize(function.getParamCount());
-        } else if (type->getArraySize() != function.getParamCount()) {
+            type.changeArraySize(function.getParamCount());
+        } else if (type.getArraySize() != function.getParamCount()) {
             error(line, "array constructor needs one argument per array element", "constructor", "");
             return true;
         }
@@ -561,7 +561,7 @@ bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& fun
         return true;
     }
 
-    if (matrixInMatrix && !type->isArray()) {
+    if (matrixInMatrix && ! type.isArray()) {
         profileRequires(line, ENoProfile, 120, 0, "constructing matrix from matrix");
         return false;
     }
@@ -571,13 +571,13 @@ bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& fun
         return true;
     }
     
-    if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->size() != function.getParamCount()) {
+    if (op == EOpConstructStruct && ! type.isArray() && type.getStruct()->size() != function.getParamCount()) {
         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
         return true;
     }
 
-    if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
-        (op == EOpConstructStruct && size < type->getObjectSize())) {
+    if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
+        (op == EOpConstructStruct && size < type.getObjectSize())) {
         error(line, "not enough data provided for construction", "constructor", "");
         return true;
     }
@@ -1473,6 +1473,9 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
     if (instanceName && reservedErrorCheck(line, *instanceName))
         return;
 
+    if (profile == EEsProfile && arraySizes)
+        arraySizeRequiredCheck(line, arraySizes->front());        
+
     if (blockType.basicType != EbtVoid) {
         error(line, "interface blocks cannot be declared with a type", blockName->c_str(), "");
 
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index e776a4adf..70ba6a0d7 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -114,7 +114,7 @@ struct TParseContext {
     void constCheck(TIntermTyped* node);
     void integerCheck(TIntermTyped* node, const char* token);
     void globalCheck(int line, bool global, const char* token);
-    bool constructorError(int line, TIntermNode*, TFunction&, TOperator, TType*);
+    bool constructorError(int line, TIntermNode*, TFunction&, TOperator, TType&);
     void arraySizeCheck(int line, TIntermTyped* expr, int& size);
     bool arrayQualifierError(int line, const TPublicType&);
     void arraySizeRequiredCheck(int line, int& size);
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index 0dc84055f..7efbbbfa9 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -464,7 +464,7 @@ function_call
             // Their parameters will be verified algorithmically.
             //
             TType type(EbtVoid);  // use this to get the type back
-            if (parseContext.constructorError($1.line, $1.intermNode, *fnCall, op, &type)) {
+            if (parseContext.constructorError($1.line, $1.intermNode, *fnCall, op, type)) {
                 $$ = 0;
             } else {
                 //
@@ -1120,11 +1120,13 @@ declaration
         $$ = 0;
     }
     | type_qualifier IDENTIFIER SEMICOLON {
+        // TODO: functionality: track what variables are declared with INVARIANT
         // precise foo;
         // invariant foo;
         $$ = 0;
     }
     | type_qualifier IDENTIFIER identifier_list SEMICOLON {
+        // TODO: functionality: track what variables are declared with INVARIANT
         // precise foo, bar;
         // invariant foo, bar;
         $$ = 0;
@@ -1250,6 +1252,7 @@ parameter_declarator
         if ($1.arraySizes) {
             parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
             parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");
+            parseContext.arraySizeRequiredCheck($1.line, $1.arraySizes->front());
         }
         if ($1.basicType == EbtVoid) {
             parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
@@ -1264,6 +1267,7 @@ parameter_declarator
         if ($1.arraySizes) {
             parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
             parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");
+            parseContext.arraySizeRequiredCheck($1.line, $1.arraySizes->front());
         }
 
         parseContext.arraySizeRequiredCheck($3.line, $3.arraySizes->front());
@@ -1332,7 +1336,9 @@ init_declarator_list
     }
     | init_declarator_list COMMA IDENTIFIER array_specifier {
         parseContext.nonInitConstCheck($3.line, *$3.string, $1.type);
-
+        if (parseContext.profile == EEsProfile)
+            parseContext.arraySizeRequiredCheck($4.line, $4.arraySizes->front());
+        
         $$ = $1;
 
         if (! parseContext.arrayQualifierError($4.line, $1.type)) {
@@ -1398,7 +1404,9 @@ single_declaration
     }
     | fully_specified_type IDENTIFIER array_specifier {
         $$.intermAggregate = 0;
-        parseContext.nonInitConstCheck($2.line, *$2.string, $1);
+        parseContext.nonInitConstCheck($2.line, *$2.string, $1);        
+        if (parseContext.profile == EEsProfile)
+            parseContext.arraySizeRequiredCheck($3.line, $3.arraySizes->front());
 
         $$.type = $1;
 
@@ -1458,6 +1466,8 @@ fully_specified_type
         if ($1.arraySizes) {
             parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
             parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");
+            if (parseContext.profile == EEsProfile)
+                parseContext.arraySizeRequiredCheck($1.line, $1.arraySizes->front());
         }
     }
     | type_qualifier type_specifier  {
@@ -1466,6 +1476,8 @@ fully_specified_type
         if ($2.arraySizes) {
             parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
             parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");
+            if (parseContext.profile == EEsProfile)
+                parseContext.arraySizeRequiredCheck($2.line, $2.arraySizes->front());
         }
 
         if ($2.arraySizes && parseContext.arrayQualifierError($2.line, $1))
@@ -1714,7 +1726,7 @@ type_specifier
         $$ = $1;
         $$.qualifier.precision = parseContext.defaultPrecision[$$.basicType];
     }
-    | type_specifier_nonarray array_specifier {
+    | type_specifier_nonarray array_specifier {        
         $$ = $1;
         $$.qualifier.precision = parseContext.defaultPrecision[$$.basicType];
         $$.arraySizes = $2.arraySizes;
@@ -2447,6 +2459,8 @@ struct_declaration
         if ($1.arraySizes) {
             parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
             parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");
+            if (parseContext.profile == EEsProfile)
+                parseContext.arraySizeRequiredCheck($1.line, $1.arraySizes->front());
         }
 
         $$ = $2;
@@ -2460,6 +2474,8 @@ struct_declaration
         if ($2.arraySizes) {
             parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
             parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");
+            if (parseContext.profile == EEsProfile)
+                parseContext.arraySizeRequiredCheck($2.line, $2.arraySizes->front());
         }
 
         $$ = $3;
@@ -2488,7 +2504,9 @@ struct_declarator
         $$.line = $1.line;
         $$.type->setFieldName(*$1.string);
     }
-    | IDENTIFIER array_specifier {
+    | IDENTIFIER array_specifier {        
+        if (parseContext.profile == EEsProfile)
+            parseContext.arraySizeRequiredCheck($2.line, $2.arraySizes->front());
         $$.type = new TType(EbtVoid);
         $$.line = $1.line;
         $$.type->setFieldName(*$1.string);
-- 
GitLab