Move the parsing of single declarations into TParseContext.

TRAC #23268

Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Authored-by: Jamie Madill
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index eb2eb55..f79bbb8 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -759,7 +759,7 @@
 //
 // Returns true if there was an error.
 //
-bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
+bool TParseContext::arrayErrorCheck(int line, const TString& identifier, const TPublicType &type, TVariable*& variable)
 {
     //
     // Don't check for reserved word use until after we know it's not in the symbol table,
@@ -873,7 +873,7 @@
 //
 // Returns true if there was an error.
 //
-bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
+bool TParseContext::nonInitConstErrorCheck(int line, const TString& identifier, TPublicType& type, bool array)
 {
     if (type.qualifier == EvqConst)
     {
@@ -905,7 +905,7 @@
 //
 // Returns true if there was an error.
 //
-bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
+bool TParseContext::nonInitErrorCheck(int line, const TString& identifier, const TPublicType& type, TVariable*& variable)
 {
     if (reservedErrorCheck(line, identifier))
         recover();
@@ -1023,7 +1023,7 @@
 // Initializers show up in several places in the grammar.  Have one set of
 // code to handle them here.
 //
-bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
+bool TParseContext::executeInitializer(TSourceLoc line, const TString& identifier, TPublicType& pType, 
                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
 {
     TType type = TType(pType);
@@ -1179,6 +1179,95 @@
     return returnType;
 }
 
+TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier)
+{
+    TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
+    TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
+
+    if (identifier != "")
+    {
+        if (structQualifierErrorCheck(identifierLocation, publicType))
+            recover();
+
+        // this error check can mutate the type
+        if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false))
+            recover();
+
+        TVariable* variable = 0;
+
+        if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable))
+            recover();
+
+        if (variable && symbol)
+        {
+            symbol->setId(variable->getUniqueId());
+        }
+    }
+
+    return aggregate;
+}
+
+TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc indexLocation, TIntermTyped *indexExpression)
+{
+    if (structQualifierErrorCheck(identifierLocation, publicType))
+        recover();
+
+    // this error check can mutate the type
+    if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true))
+        recover();
+
+    if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
+    {
+        recover();
+    }
+
+    TPublicType arrayType = publicType;
+
+    int size;
+    if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    {
+        recover();
+    }
+    else
+    {
+        arrayType.setArray(true, size);
+    }
+
+    TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation);
+    TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
+    TVariable* variable = 0;
+
+    if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable))
+        recover();
+
+    if (variable && symbol)
+    {
+        symbol->setId(variable->getUniqueId());
+    }
+
+    return aggregate;
+}
+
+TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc initLocation, TIntermTyped *initializer)
+{
+    if (structQualifierErrorCheck(identifierLocation, publicType))
+        recover();
+
+    TIntermNode* intermNode;
+    if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
+    {
+        //
+        // Build intermediate representation
+        //
+        return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL;
+    }
+    else
+    {
+        recover();
+        return NULL;
+    }
+}
+
 TFunction *TParseContext::addConstructorFunc(TPublicType publicType)
 {
     TOperator op = EOpNull;
diff --git a/src/compiler/ParseHelper.h b/src/compiler/ParseHelper.h
index 1725e5f..4a0f2d5 100644
--- a/src/compiler/ParseHelper.h
+++ b/src/compiler/ParseHelper.h
@@ -89,15 +89,15 @@
     bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
     bool arrayQualifierErrorCheck(int line, TPublicType type);
     bool arrayTypeErrorCheck(int line, TPublicType type);
-    bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
+    bool arrayErrorCheck(int line, const TString& identifier, const TPublicType &type, TVariable*& variable);
     bool voidErrorCheck(int, const TString&, const TPublicType&);
     bool boolErrorCheck(int, const TIntermTyped*);
     bool boolErrorCheck(int, const TPublicType&);
     bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
     bool structQualifierErrorCheck(int line, const TPublicType& pType);
     bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
-    bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
-    bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
+    bool nonInitConstErrorCheck(int line, const TString& identifier, TPublicType& type, bool array);
+    bool nonInitErrorCheck(int line, const TString& identifier, const TPublicType& type, TVariable*& variable);
     bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
     bool extensionErrorCheck(int line, const TString&);
 
@@ -111,11 +111,14 @@
     bool containsSampler(TType& type);
     bool areAllChildConst(TIntermAggregate* aggrNode);
     const TFunction* findFunction(int line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0);
-    bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+    bool executeInitializer(TSourceLoc line, const TString& identifier, TPublicType& pType,
                             TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
     bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
 
     TPublicType addFullySpecifiedType(TQualifier qualifier, const TPublicType& typeSpecifier);
+    TIntermAggregate* parseSingleDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier);
+    TIntermAggregate* parseSingleArrayDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc indexLocation, TIntermTyped *indexExpression);
+    TIntermAggregate* parseSingleInitDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc initLocation, TIntermTyped *initializer);
     TFunction *addConstructorFunc(TPublicType publicType);
     TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
     TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
diff --git a/src/compiler/glslang.y b/src/compiler/glslang.y
index 072a884..f9713c2 100644
--- a/src/compiler/glslang.y
+++ b/src/compiler/glslang.y
@@ -1100,85 +1100,26 @@
 single_declaration
     : fully_specified_type {
         $$.type = $1;
-        $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
+        $$.intermAggregate = context->parseSingleDeclaration($$.type, $1.line, "");
     }
     | fully_specified_type identifier {
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
-        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
-        
-        if (context->structQualifierErrorCheck($2.line, $$.type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
-            context->recover();
-            
-            $$.type = $1;
-
-        TVariable* variable = 0;
-        if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
-            context->recover();
-        if (variable && symbol)
-            symbol->setId(variable->getUniqueId());
+        $$.type = $1;
+        $$.intermAggregate = context->parseSingleDeclaration($$.type, $2.line, *$2.string);
     }
     | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
         context->error($2.line, "unsized array declarations not supported", $2.string->c_str());
         context->recover();
 
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
-        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
         $$.type = $1;
+        $$.intermAggregate = context->parseSingleDeclaration($$.type, $2.line, *$2.string);
     }
     | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        TType type = TType($1);
-        int size;
-        if (context->arraySizeErrorCheck($2.line, $4, size))
-            context->recover();
-        type.setArraySize(size);
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
-        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
-        
-        if (context->structQualifierErrorCheck($2.line, $1))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
-            context->recover();
-
         $$.type = $1;
-
-        if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck($3.line, $4, size))
-                context->recover();
-
-            $1.setArray(true, size);
-            TVariable* variable = 0;
-            if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
-                context->recover();
-            if (variable && symbol)
-                symbol->setId(variable->getUniqueId());
-        }
+        $$.intermAggregate = context->parseSingleArrayDeclaration($$.type, $2.line, *$2.string, $3.line, $4);
     }
     | fully_specified_type identifier EQUAL initializer {
-        if (context->structQualifierErrorCheck($2.line, $1))
-            context->recover();
-
         $$.type = $1;
-
-        TIntermNode* intermNode;
-        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
-        //
-        // Build intermediate representation
-        //
-            if(intermNode)
-                $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line);
-            else
-                $$.intermAggregate = 0;
-        } else {
-            context->recover();
-            $$.intermAggregate = 0;
-        }
+        $$.intermAggregate = context->parseSingleInitDeclaration($$.type, $2.line, *$2.string, $3.line, $4);
     }
     | INVARIANT IDENTIFIER {
         VERTEX_ONLY("invariant declaration", $1.line);
diff --git a/src/compiler/glslang_tab.cpp b/src/compiler/glslang_tab.cpp
index dc85091..f60364d 100644
--- a/src/compiler/glslang_tab.cpp
+++ b/src/compiler/glslang_tab.cpp
@@ -751,20 +751,20 @@
      733,   736,   747,   755,   763,   790,   795,   806,   810,   814,
      821,   859,   862,   869,   877,   898,   919,   930,   959,   964,
      974,   979,   989,   992,   995,   998,  1004,  1011,  1014,  1036,
-    1054,  1078,  1101,  1105,  1123,  1131,  1163,  1183,  1272,  1281,
-    1287,  1291,  1298,  1304,  1311,  1320,  1329,  1332,  1368,  1375,
-    1379,  1386,  1390,  1395,  1400,  1410,  1420,  1429,  1439,  1446,
-    1449,  1452,  1458,  1465,  1468,  1474,  1477,  1480,  1486,  1489,
-    1504,  1508,  1512,  1516,  1520,  1524,  1529,  1534,  1539,  1544,
-    1549,  1554,  1559,  1564,  1569,  1574,  1579,  1584,  1590,  1596,
-    1602,  1607,  1612,  1617,  1622,  1627,  1632,  1637,  1642,  1651,
-    1660,  1665,  1678,  1678,  1681,  1681,  1687,  1690,  1705,  1708,
-    1716,  1720,  1726,  1734,  1750,  1754,  1758,  1759,  1765,  1766,
-    1767,  1768,  1769,  1773,  1774,  1774,  1774,  1784,  1785,  1789,
-    1789,  1790,  1790,  1795,  1798,  1808,  1811,  1817,  1818,  1822,
-    1830,  1834,  1844,  1849,  1866,  1866,  1871,  1871,  1878,  1878,
-    1886,  1889,  1895,  1898,  1904,  1908,  1915,  1922,  1929,  1936,
-    1947,  1956,  1960,  1967,  1970,  1976,  1976
+    1054,  1078,  1101,  1105,  1109,  1116,  1120,  1124,  1213,  1222,
+    1228,  1232,  1239,  1245,  1252,  1261,  1270,  1273,  1309,  1316,
+    1320,  1327,  1331,  1336,  1341,  1351,  1361,  1370,  1380,  1387,
+    1390,  1393,  1399,  1406,  1409,  1415,  1418,  1421,  1427,  1430,
+    1445,  1449,  1453,  1457,  1461,  1465,  1470,  1475,  1480,  1485,
+    1490,  1495,  1500,  1505,  1510,  1515,  1520,  1525,  1531,  1537,
+    1543,  1548,  1553,  1558,  1563,  1568,  1573,  1578,  1583,  1592,
+    1601,  1606,  1619,  1619,  1622,  1622,  1628,  1631,  1646,  1649,
+    1657,  1661,  1667,  1675,  1691,  1695,  1699,  1700,  1706,  1707,
+    1708,  1709,  1710,  1714,  1715,  1715,  1715,  1725,  1726,  1730,
+    1730,  1731,  1731,  1736,  1739,  1749,  1752,  1758,  1759,  1763,
+    1771,  1775,  1785,  1790,  1807,  1807,  1812,  1812,  1819,  1819,
+    1827,  1830,  1836,  1839,  1845,  1849,  1856,  1863,  1870,  1877,
+    1888,  1897,  1901,  1908,  1911,  1917,  1917
 };
 #endif
 
@@ -3470,29 +3470,15 @@
 
     {
         (yyval.interm).type = (yyvsp[(1) - (1)].interm.type);
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yyvsp[(1) - (1)].interm.type).line), (yyvsp[(1) - (1)].interm.type).line);
+        (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yyvsp[(1) - (1)].interm.type).line, "");
     }
     break;
 
   case 103:
 
     {
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line);
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line);
-        
-        if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false))
-            context->recover();
-            
-            (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
-
-        TVariable* variable = 0;
-        if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
-            context->recover();
-        if (variable && symbol)
-            symbol->setId(variable->getUniqueId());
+        (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
+        (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string);
     }
     break;
 
@@ -3502,69 +3488,24 @@
         context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str());
         context->recover();
 
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line);
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line);
         (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+        (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string);
     }
     break;
 
   case 105:
 
     {
-        TType type = TType((yyvsp[(1) - (5)].interm.type));
-        int size;
-        if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
-            context->recover();
-        type.setArraySize(size);
-        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line);
-        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line);
-        
-        if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
-            context->recover();
-
-        if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true))
-            context->recover();
-
         (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
-
-        if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
-            context->recover();
-        else {
-            int size;
-            if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
-                context->recover();
-
-            (yyvsp[(1) - (5)].interm.type).setArray(true, size);
-            TVariable* variable = 0;
-            if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
-                context->recover();
-            if (variable && symbol)
-                symbol->setId(variable->getUniqueId());
-        }
+        (yyval.interm).intermAggregate = context->parseSingleArrayDeclaration((yyval.interm).type, (yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode));
     }
     break;
 
   case 106:
 
     {
-        if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
-            context->recover();
-
         (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
-
-        TIntermNode* intermNode;
-        if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) {
-        //
-        // Build intermediate representation
-        //
-            if(intermNode)
-                (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yyvsp[(3) - (4)].lex).line);
-            else
-                (yyval.interm).intermAggregate = 0;
-        } else {
-            context->recover();
-            (yyval.interm).intermAggregate = 0;
-        }
+        (yyval.interm).intermAggregate = context->parseSingleInitDeclaration((yyval.interm).type, (yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(3) - (4)].lex).line, (yyvsp[(4) - (4)].interm.intermTypedNode));
     }
     break;