Refactor type_specifier_nonarray parsing to reduce code repetition

When type_specifier_nonarray gets parsed the scope gets saved into
TType and the code becomes repetitive. Setting of the scope is moved
to type_specifier_no_prec as it occurs less times.

BUG=angleproject:911

TEST=angle_unittests
TEST=angle_end2end_tests

Change-Id: I6da5fe7bc2d60ba2996221af71b719b818f5e9b1
Reviewed-on: https://chromium-review.googlesource.com/380535
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 2e95725..aba357c 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -445,15 +445,13 @@
     symbolTable.push();   // ESSL3_1_BUILTINS
 
     TPublicType integer;
-    integer.type = EbtInt;
-    integer.primarySize = 1;
-    integer.secondarySize = 1;
+    integer.setBasicType(EbtInt);
+    integer.initializeSizeForScalarTypes();
     integer.array = false;
 
     TPublicType floatingPoint;
-    floatingPoint.type = EbtFloat;
-    floatingPoint.primarySize = 1;
-    floatingPoint.secondarySize = 1;
+    floatingPoint.setBasicType(EbtFloat);
+    floatingPoint.initializeSizeForScalarTypes();
     floatingPoint.array = false;
 
     switch(shaderType)
@@ -493,10 +491,9 @@
 {
     ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
     TPublicType sampler;
-    sampler.primarySize   = 1;
-    sampler.secondarySize = 1;
+    sampler.initializeSizeForScalarTypes();
+    sampler.setBasicType(samplerType);
     sampler.array         = false;
-    sampler.type          = samplerType;
     symbolTable.setDefaultPrecision(sampler, EbpLow);
 }
 
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index c405cea..663012e 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -662,14 +662,14 @@
 // or not.
 void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
 {
-    if (pType.type != EbtBool || pType.isAggregate())
+    if (pType.getBasicType() != EbtBool || pType.isAggregate())
     {
         error(line, "boolean expression expected", "");
     }
 }
 
 bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
-                                      const TPublicType &pType,
+                                      const TTypeSpecifierNonArray &pType,
                                       const char *reason)
 {
     if (pType.type == EbtStruct)
@@ -824,7 +824,7 @@
     // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
     // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
     // 4.3.4).
-    if (mShaderVersion >= 300 && elementType.type == EbtStruct &&
+    if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
         sh::IsVarying(elementType.qualifier))
     {
         error(line, "cannot declare arrays of structs of this qualifier",
@@ -986,7 +986,7 @@
         case EvqVertexIn:
         case EvqFragmentOut:
         case EvqComputeIn:
-            if (publicType.type == EbtStruct)
+            if (publicType.getBasicType() == EbtStruct)
             {
                 error(identifierLocation, "cannot be used with a structure",
                       getQualifierString(publicType.qualifier));
@@ -998,7 +998,8 @@
     }
 
     if (publicType.qualifier != EvqUniform &&
-        !checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform"))
+        !checkIsNotSampler(identifierLocation, publicType.typeSpecifierNonArray,
+                           "samplers must be uniform"))
     {
         return;
     }
@@ -1414,31 +1415,33 @@
         returnType.precision = typeQualifier.precision;
     }
 
-    checkPrecisionSpecified(typeSpecifier.line, returnType.precision, typeSpecifier.type);
+    checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
+                            typeSpecifier.getBasicType());
 
-    checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier, typeSpecifier.line);
+    checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
+                                    typeSpecifier.getLine());
 
-    checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, returnType.layoutQualifier);
+    checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
 
     if (mShaderVersion < 300)
     {
         if (typeSpecifier.array)
         {
-            error(typeSpecifier.line, "not supported", "first-class array");
+            error(typeSpecifier.getLine(), "not supported", "first-class array");
             returnType.clearArrayness();
         }
 
         if (returnType.qualifier == EvqAttribute &&
-            (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
+            (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
         {
-            error(typeSpecifier.line, "cannot be bool or int",
+            error(typeSpecifier.getLine(), "cannot be bool or int",
                   getQualifierString(returnType.qualifier));
         }
 
         if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
-            (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
+            (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
         {
-            error(typeSpecifier.line, "cannot be bool or int",
+            error(typeSpecifier.getLine(), "cannot be bool or int",
                   getQualifierString(returnType.qualifier));
         }
     }
@@ -1446,16 +1449,17 @@
     {
         if (!returnType.layoutQualifier.isEmpty())
         {
-            checkIsAtGlobalLevel(typeSpecifier.line, "layout");
+            checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
         }
         if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
             returnType.qualifier == EvqFragmentOut)
         {
-            checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, typeSpecifier.line);
+            checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
+                                           typeSpecifier.getLine());
         }
         if (returnType.qualifier == EvqComputeIn)
         {
-            error(typeSpecifier.line, "'in' can be only used to specify the local group size",
+            error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
                   "in");
         }
     }
@@ -1468,7 +1472,7 @@
                                                    const TSourceLoc &qualifierLocation)
 {
     // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
-    if (type.type == EbtBool)
+    if (type.getBasicType() == EbtBool)
     {
         error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
     }
@@ -1486,7 +1490,7 @@
             return;
         case EvqFragmentOut:
             // ESSL 3.00 section 4.3.6
-            if (type.isMatrix())
+            if (type.typeSpecifierNonArray.isMatrix())
             {
                 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
             }
@@ -1499,15 +1503,15 @@
     // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
     // restrictions.
     bool typeContainsIntegers =
-        (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
-         type.isStructureContainingType(EbtUInt));
+        (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
+         type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
     if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
     {
         error(qualifierLocation, "must use 'flat' interpolation here",
               getQualifierString(qualifier));
     }
 
-    if (type.type == EbtStruct)
+    if (type.getBasicType() == EbtStruct)
     {
         // ESSL 3.00 sections 4.3.4 and 4.3.6.
         // These restrictions are only implied by the ESSL 3.00 spec, but
@@ -2269,7 +2273,8 @@
         error(location, "no qualifiers allowed for function return", "layout");
     }
     // make sure a sampler is not involved as well...
-    checkIsNotSampler(location, type, "samplers can't be function return values");
+    checkIsNotSampler(location, type.typeSpecifierNonArray,
+                      "samplers can't be function return values");
     if (mShaderVersion < 300)
     {
         // Array return values are forbidden, but there's also no valid syntax for declaring array
@@ -2291,14 +2296,14 @@
 TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
 {
     TPublicType publicType = publicTypeIn;
-    if (publicType.isStructSpecifier)
+    if (publicType.isStructSpecifier())
     {
-        error(publicType.line, "constructor can't be a structure definition",
-              getBasicString(publicType.type));
+        error(publicType.getLine(), "constructor can't be a structure definition",
+              getBasicString(publicType.getBasicType()));
     }
 
     TOperator op = EOpNull;
-    if (publicType.userDef)
+    if (publicType.getUserDef())
     {
         op = EOpConstructStruct;
     }
@@ -2307,8 +2312,9 @@
         op = sh::TypeToConstructorOperator(TType(publicType));
         if (op == EOpNull)
         {
-            error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
-            publicType.type = EbtFloat;
+            error(publicType.getLine(), "cannot construct this type",
+                  getBasicString(publicType.getBasicType()));
+            publicType.setBasicType(EbtFloat);
             op              = EOpConstructFloat;
         }
     }
@@ -3226,11 +3232,12 @@
 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
                                                    TFieldList *fieldList)
 {
-    checkPrecisionSpecified(typeSpecifier.line, typeSpecifier.precision, typeSpecifier.type);
+    checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
+                            typeSpecifier.getBasicType());
 
-    checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
+    checkIsNonVoid(typeSpecifier.getLine(), (*fieldList)[0]->name(), typeSpecifier.getBasicType());
 
-    checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
+    checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
 
     for (unsigned int i = 0; i < fieldList->size(); ++i)
     {
@@ -3238,9 +3245,9 @@
         // Careful not to replace already known aspects of type, like array-ness
         //
         TType *type = (*fieldList)[i]->type();
-        type->setBasicType(typeSpecifier.type);
-        type->setPrimarySize(typeSpecifier.primarySize);
-        type->setSecondarySize(typeSpecifier.secondarySize);
+        type->setBasicType(typeSpecifier.getBasicType());
+        type->setPrimarySize(typeSpecifier.getPrimarySize());
+        type->setSecondarySize(typeSpecifier.getSecondarySize());
         type->setPrecision(typeSpecifier.precision);
         type->setQualifier(typeSpecifier.qualifier);
         type->setLayoutQualifier(typeSpecifier.layoutQualifier);
@@ -3249,25 +3256,25 @@
         // don't allow arrays of arrays
         if (type->isArray())
         {
-            checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
+            checkIsValidTypeForArray(typeSpecifier.getLine(), typeSpecifier);
         }
         if (typeSpecifier.array)
             type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
-        if (typeSpecifier.userDef)
+        if (typeSpecifier.getUserDef())
         {
-            type->setStruct(typeSpecifier.userDef->getStruct());
+            type->setStruct(typeSpecifier.getUserDef()->getStruct());
         }
 
-        checkIsBelowStructNestingLimit(typeSpecifier.line, *(*fieldList)[i]);
+        checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *(*fieldList)[i]);
     }
 
     return fieldList;
 }
 
-TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
-                                        const TSourceLoc &nameLine,
-                                        const TString *structName,
-                                        TFieldList *fieldList)
+TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
+                                                   const TSourceLoc &nameLine,
+                                                   const TString *structName,
+                                                   TFieldList *fieldList)
 {
     TStructure *structure = new TStructure(structName, fieldList);
     TType *structureType  = new TType(structure);
@@ -3310,13 +3317,13 @@
         checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
     }
 
-    TPublicType publicType;
-    publicType.setBasic(EbtStruct, EvqTemporary, structLine);
-    publicType.userDef = structureType;
-    publicType.isStructSpecifier = true;
+    TTypeSpecifierNonArray typeSpecifierNonArray;
+    typeSpecifierNonArray.initialize(EbtStruct, structLine);
+    typeSpecifierNonArray.userDef           = structureType;
+    typeSpecifierNonArray.isStructSpecifier = true;
     exitStructDeclaration();
 
-    return publicType;
+    return typeSpecifierNonArray;
 }
 
 TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index aadc881..aa8619c 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -160,7 +160,9 @@
     bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type);
     void checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type);
     void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType);
-    bool checkIsNotSampler(const TSourceLoc &line, const TPublicType &pType, const char *reason);
+    bool checkIsNotSampler(const TSourceLoc &line,
+                           const TTypeSpecifierNonArray &pType,
+                           const char *reason);
     void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType);
     void checkLocationIsNotSpecified(const TSourceLoc &location,
                                      const TLayoutQualifier &layoutQualifier);
@@ -298,10 +300,10 @@
         TPublicType *typeSpecifier,
         TFieldList *fieldList);
     TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
-    TPublicType addStructure(const TSourceLoc &structLine,
-                             const TSourceLoc &nameLine,
-                             const TString *structName,
-                             TFieldList *fieldList);
+    TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine,
+                                        const TSourceLoc &nameLine,
+                                        const TString *structName,
+                                        TFieldList *fieldList);
 
     TIntermAggregate *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
                                         const TSourceLoc &nameLine,
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 60e0b99..f092412 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -471,15 +471,15 @@
 
     bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
     {
-        if (!SupportsPrecision(type.type))
+        if (!SupportsPrecision(type.getBasicType()))
             return false;
-        if (type.type == EbtUInt)
+        if (type.getBasicType() == EbtUInt)
             return false;  // ESSL 3.00.4 section 4.5.4
         if (type.isAggregate())
             return false; // Not allowed to set for aggregate types
         int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
         // Uses map operator [], overwrites the current value
-        (*precisionStack[indexOfLastElement])[type.type] = prec;
+        (*precisionStack[indexOfLastElement])[type.getBasicType()] = prec;
         return true;
     }
 
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index be1f982..0f0b097 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -48,12 +48,20 @@
 }
 
 TType::TType(const TPublicType &p)
-    : type(p.type), precision(p.precision), qualifier(p.qualifier), invariant(p.invariant),
-      layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize),
-      array(p.array), arraySize(p.arraySize), interfaceBlock(0), structure(0)
+    : type(p.getBasicType()),
+      precision(p.precision),
+      qualifier(p.qualifier),
+      invariant(p.invariant),
+      layoutQualifier(p.layoutQualifier),
+      primarySize(p.getPrimarySize()),
+      secondarySize(p.getSecondarySize()),
+      array(p.array),
+      arraySize(p.arraySize),
+      interfaceBlock(0),
+      structure(0)
 {
-    if (p.userDef)
-        structure = p.userDef->getStruct();
+    if (p.getUserDef())
+        structure = p.getUserDef()->getStruct();
 }
 
 bool TStructure::equals(const TStructure &other) const
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index 2a85e01..43d2c46 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -594,6 +594,46 @@
     mutable TString mangled;
 };
 
+// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
+// grammar
+struct TTypeSpecifierNonArray
+{
+    TBasicType type;
+    unsigned char primarySize;          // size of vector or cols of matrix
+    unsigned char secondarySize;        // rows of matrix
+    TType *userDef;
+    TSourceLoc line;
+
+    // true if the type was defined by a struct specifier rather than a reference to a type name.
+    bool isStructSpecifier;
+
+    void initialize(TBasicType bt, const TSourceLoc &ln)
+    {
+        type = bt;
+        primarySize = 1;
+        secondarySize = 1;
+        userDef           = nullptr;
+        line = ln;
+        isStructSpecifier = false;
+    }
+
+    void setAggregate(unsigned char size)
+    {
+        primarySize = size;
+    }
+
+    void setMatrix(unsigned char columns, unsigned char rows)
+    {
+        ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
+        primarySize   = columns;
+        secondarySize = rows;
+    }
+
+    bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
+
+    bool isVector() const { return primarySize > 1 && secondarySize == 1; }
+};
+
 //
 // This is a workaround for a problem with the yacc stack,  It can't have
 // types that it thinks have non-trivial constructors.  It should
@@ -605,114 +645,76 @@
 //
 struct TPublicType
 {
-    TBasicType type;
+    TTypeSpecifierNonArray typeSpecifierNonArray;
     TLayoutQualifier layoutQualifier;
     TQualifier qualifier;
     bool invariant;
     TPrecision precision;
-    unsigned char primarySize;          // size of vector or cols of matrix
-    unsigned char secondarySize;        // rows of matrix
     bool array;
     int arraySize;
-    TType *userDef;
-    TSourceLoc line;
 
-    // true if the type was defined by a struct specifier rather than a reference to a type name.
-    bool isStructSpecifier;
-
-    void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln)
+    void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
     {
-        type = bt;
-        layoutQualifier = TLayoutQualifier::create();
-        qualifier = q;
-        invariant = false;
-        precision = EbpUndefined;
-        primarySize = 1;
-        secondarySize = 1;
-        array = false;
-        arraySize = 0;
-        userDef = 0;
-        line = ln;
-        isStructSpecifier = false;
+        typeSpecifierNonArray = typeSpecifier;
+        layoutQualifier       = TLayoutQualifier::create();
+        qualifier             = q;
+        invariant             = false;
+        precision             = EbpUndefined;
+        array                 = false;
+        arraySize             = 0;
     }
 
-    void setAggregate(unsigned char size)
+    TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
+    void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
+
+    unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
+    unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
+    void initializeSizeForScalarTypes()
     {
-        primarySize = size;
+        typeSpecifierNonArray.primarySize   = 1;
+        typeSpecifierNonArray.secondarySize = 1;
     }
 
-    void setMatrix(unsigned char c, unsigned char r)
-    {
-        ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4);
-        primarySize = c;
-        secondarySize = r;
-    }
+    const TType *getUserDef() const { return typeSpecifierNonArray.userDef; }
+    const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
 
-    bool isUnsizedArray() const
-    {
-        return array && arraySize == 0;
-    }
-    void setArraySize(int s)
-    {
-        array = true;
-        arraySize = s;
-    }
-    void clearArrayness()
-    {
-        array = false;
-        arraySize = 0;
-    }
+    bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
 
     bool isStructureContainingArrays() const
     {
-        if (!userDef)
+        if (!typeSpecifierNonArray.userDef)
         {
             return false;
         }
 
-        return userDef->isStructureContainingArrays();
+        return typeSpecifierNonArray.userDef->isStructureContainingArrays();
     }
 
     bool isStructureContainingType(TBasicType t) const
     {
-        if (!userDef)
+        if (!typeSpecifierNonArray.userDef)
         {
             return false;
         }
 
-        return userDef->isStructureContainingType(t);
+        return typeSpecifierNonArray.userDef->isStructureContainingType(t);
     }
 
-    bool isMatrix() const
+    bool isUnsizedArray() const { return array && arraySize == 0; }
+    void setArraySize(int s)
     {
-        return primarySize > 1 && secondarySize > 1;
+        array     = true;
+        arraySize = s;
     }
-
-    bool isVector() const
+    void clearArrayness()
     {
-        return primarySize > 1 && secondarySize == 1;
-    }
-
-    int getCols() const
-    {
-        ASSERT(isMatrix());
-        return primarySize;
-    }
-
-    int getRows() const
-    {
-        ASSERT(isMatrix());
-        return secondarySize;
-    }
-
-    int getNominalSize() const
-    {
-        return primarySize;
+        array     = false;
+        arraySize = 0;
     }
 
     bool isAggregate() const
     {
-        return array || isMatrix() || isVector();
+        return array || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
     }
 };
 
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 2126bcf..dd73dd1 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -80,6 +80,7 @@
             TIntermCase* intermCase;
         };
         union {
+            TTypeSpecifierNonArray typeSpecifierNonArray;
             TPublicType type;
             TPrecision precision;
             TLayoutQualifier layoutQualifier;
@@ -217,8 +218,8 @@
 %type <interm.qualifierWrapper> single_type_qualifier invariant_qualifier
 %type <interm.typeQualifierBuilder> type_qualifier
 
-%type <interm.type> type_specifier_no_prec type_specifier_nonarray
-%type <interm.type> struct_specifier
+%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier
+%type <interm.type> type_specifier_no_prec
 %type <interm.field> struct_declarator
 %type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
 %type <interm.function> function_header function_declarator function_identifier
@@ -611,7 +612,7 @@
             context->error(@1, "precision is not supported in fragment shader", "highp");
         }
         if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
-            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
+            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.getBasicType()));
         }
         $$ = 0;
     }
@@ -694,7 +695,7 @@
 parameter_declarator
     // Type + name
     : type_specifier identifier {
-        if ($1.type == EbtVoid) {
+        if ($1.getBasicType() == EbtVoid) {
             context->error(@2, "illegal use of type 'void'", $2.string->c_str());
         }
         context->checkIsNotReserved(@2, *$2.string);
@@ -955,7 +956,7 @@
         $$ = $1;
 
         if ($$.precision == EbpUndefined) {
-            $$.precision = context->symbolTable.getDefaultPrecision($1.type);
+            $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType());
         }
     }
     ;
@@ -1002,17 +1003,16 @@
 
 type_specifier_no_prec
     : type_specifier_nonarray {
-        $$ = $1;
+        $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
     }
     | type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET {
         ES3_OR_NEWER("[]", @2, "implicitly sized array");
-        $$ = $1;
+        $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
         $$.setArraySize(0);
     }
     | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        $$ = $1;
-
-        if (context->checkIsValidTypeForArray(@2, $1))
+        $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+        if (context->checkIsValidTypeForArray(@2, $$))
         {
             unsigned int size = context->checkIsValidArraySize(@2, $3);
             $$.setArraySize(size);
@@ -1022,208 +1022,164 @@
 
 type_specifier_nonarray
     : VOID_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtVoid, qual, @1);
+        $$.initialize(EbtVoid, @1);
     }
     | FLOAT_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
     }
     | INT_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
+        $$.initialize(EbtInt, @1);
     }
     | UINT_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUInt, qual, @1);
+        $$.initialize(EbtUInt, @1);
     }
     | BOOL_TYPE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
+        $$.initialize(EbtBool, @1);
     }
     | VEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setAggregate(2);
     }
     | VEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setAggregate(3);
     }
     | VEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setAggregate(4);
     }
     | BVEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
+        $$.initialize(EbtBool, @1);
         $$.setAggregate(2);
     }
     | BVEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
+        $$.initialize(EbtBool, @1);
         $$.setAggregate(3);
     }
     | BVEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtBool, qual, @1);
+        $$.initialize(EbtBool, @1);
         $$.setAggregate(4);
     }
     | IVEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
+        $$.initialize(EbtInt, @1);
         $$.setAggregate(2);
     }
     | IVEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
+        $$.initialize(EbtInt, @1);
         $$.setAggregate(3);
     }
     | IVEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtInt, qual, @1);
+        $$.initialize(EbtInt, @1);
         $$.setAggregate(4);
     }
     | UVEC2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUInt, qual, @1);
+        $$.initialize(EbtUInt, @1);
         $$.setAggregate(2);
     }
     | UVEC3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUInt, qual, @1);
+        $$.initialize(EbtUInt, @1);
         $$.setAggregate(3);
     }
     | UVEC4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUInt, qual, @1);
+        $$.initialize(EbtUInt, @1);
         $$.setAggregate(4);
     }
     | MATRIX2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(2, 2);
     }
     | MATRIX3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(3, 3);
     }
     | MATRIX4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(4, 4);
     }
     | MATRIX2x3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(2, 3);
     }
     | MATRIX3x2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(3, 2);
     }
     | MATRIX2x4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(2, 4);
     }
     | MATRIX4x2 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(4, 2);
     }
     | MATRIX3x4 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(3, 4);
     }
     | MATRIX4x3 {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtFloat, qual, @1);
+        $$.initialize(EbtFloat, @1);
         $$.setMatrix(4, 3);
     }
     | SAMPLER2D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2D, qual, @1);
+        $$.initialize(EbtSampler2D, @1);
     }
     | SAMPLER3D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler3D, qual, @1);
+        $$.initialize(EbtSampler3D, @1);
     }
     | SAMPLERCUBE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSamplerCube, qual, @1);
+        $$.initialize(EbtSamplerCube, @1);
     }
     | SAMPLER2DARRAY {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2DArray, qual, @1);
+        $$.initialize(EbtSampler2DArray, @1);
     }
     | ISAMPLER2D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtISampler2D, qual, @1);
+        $$.initialize(EbtISampler2D, @1);
     }
     | ISAMPLER3D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtISampler3D, qual, @1);
+        $$.initialize(EbtISampler3D, @1);
     }
     | ISAMPLERCUBE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtISamplerCube, qual, @1);
+        $$.initialize(EbtISamplerCube, @1);
     }
     | ISAMPLER2DARRAY {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtISampler2DArray, qual, @1);
+        $$.initialize(EbtISampler2DArray, @1);
     }
     | USAMPLER2D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUSampler2D, qual, @1);
+        $$.initialize(EbtUSampler2D, @1);
     }
     | USAMPLER3D {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUSampler3D, qual, @1);
+        $$.initialize(EbtUSampler3D, @1);
     }
     | USAMPLERCUBE {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUSamplerCube, qual, @1);
+        $$.initialize(EbtUSamplerCube, @1);
     }
     | USAMPLER2DARRAY {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtUSampler2DArray, qual, @1);
+        $$.initialize(EbtUSampler2DArray, @1);
     }
     | SAMPLER2DSHADOW {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2DShadow, qual, @1);
+        $$.initialize(EbtSampler2DShadow, @1);
     }
     | SAMPLERCUBESHADOW {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSamplerCubeShadow, qual, @1);
+        $$.initialize(EbtSamplerCubeShadow, @1);
     }
     | SAMPLER2DARRAYSHADOW {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2DArrayShadow, qual, @1);
+        $$.initialize(EbtSampler2DArrayShadow, @1);
     }
     | SAMPLER_EXTERNAL_OES {
         if (!context->supportsExtension("GL_OES_EGL_image_external") &&
             !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) {
             context->error(@1, "unsupported type", "samplerExternalOES");
         }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSamplerExternalOES, qual, @1);
+        $$.initialize(EbtSamplerExternalOES, @1);
     }
     | SAMPLER2DRECT {
         if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
             context->error(@1, "unsupported type", "sampler2DRect");
         }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtSampler2DRect, qual, @1);
+        $$.initialize(EbtSampler2DRect, @1);
     }
     | struct_specifier {
         $$ = $1;
-        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
     }
     | TYPE_NAME {
         //
@@ -1231,8 +1187,7 @@
         // type.
         //
         TType& structure = static_cast<TVariable*>($1.symbol)->getType();
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        $$.setBasic(EbtStruct, qual, @1);
+        $$.initialize(EbtStruct, @1);
         $$.userDef = &structure;
     }
     ;
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 176128e..ecc30f1 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -295,6 +295,7 @@
             TIntermCase* intermCase;
         };
         union {
+            TTypeSpecifierNonArray typeSpecifierNonArray;
             TPublicType type;
             TPrecision precision;
             TLayoutQualifier layoutQualifier;
@@ -712,33 +713,33 @@
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   235,   235,   236,   239,   249,   252,   257,   262,   267,
-     272,   278,   281,   284,   287,   290,   293,   299,   306,   317,
-     321,   329,   332,   338,   342,   349,   355,   364,   372,   378,
-     384,   393,   396,   399,   402,   412,   413,   414,   415,   423,
-     424,   427,   430,   437,   438,   441,   447,   448,   452,   459,
-     460,   463,   466,   469,   475,   476,   479,   485,   486,   493,
-     494,   501,   502,   509,   510,   516,   517,   523,   524,   530,
-     531,   537,   538,   545,   546,   547,   548,   552,   553,   554,
-     558,   562,   566,   570,   577,   580,   586,   593,   600,   603,
-     609,   618,   622,   626,   630,   634,   641,   648,   651,   658,
-     666,   686,   696,   704,   729,   733,   737,   741,   748,   755,
-     758,   762,   766,   771,   776,   783,   787,   791,   795,   800,
-     805,   812,   822,   828,   831,   837,   841,   848,   854,   861,
-     865,   868,   871,   880,   886,   894,   897,   917,   936,   943,
-     947,   954,   964,   967,   970,   976,   983,   986,   992,   995,
-     998,  1004,  1007,  1012,  1024,  1028,  1032,  1036,  1040,  1044,
-    1049,  1054,  1059,  1064,  1069,  1074,  1079,  1084,  1089,  1094,
-    1099,  1104,  1109,  1114,  1119,  1124,  1129,  1134,  1139,  1144,
-    1149,  1153,  1157,  1161,  1165,  1169,  1173,  1177,  1181,  1185,
-    1189,  1193,  1197,  1201,  1205,  1209,  1217,  1224,  1228,  1241,
-    1241,  1244,  1244,  1250,  1253,  1268,  1271,  1278,  1282,  1288,
-    1294,  1306,  1310,  1314,  1315,  1321,  1322,  1323,  1324,  1325,
-    1326,  1327,  1331,  1332,  1332,  1332,  1342,  1343,  1347,  1347,
-    1348,  1348,  1353,  1356,  1366,  1369,  1375,  1376,  1380,  1387,
-    1391,  1398,  1398,  1405,  1408,  1415,  1419,  1432,  1432,  1437,
-    1437,  1443,  1443,  1451,  1454,  1460,  1463,  1469,  1473,  1480,
-    1483,  1486,  1489,  1492,  1501,  1505,  1512,  1515,  1521,  1521
+       0,   236,   236,   237,   240,   250,   253,   258,   263,   268,
+     273,   279,   282,   285,   288,   291,   294,   300,   307,   318,
+     322,   330,   333,   339,   343,   350,   356,   365,   373,   379,
+     385,   394,   397,   400,   403,   413,   414,   415,   416,   424,
+     425,   428,   431,   438,   439,   442,   448,   449,   453,   460,
+     461,   464,   467,   470,   476,   477,   480,   486,   487,   494,
+     495,   502,   503,   510,   511,   517,   518,   524,   525,   531,
+     532,   538,   539,   546,   547,   548,   549,   553,   554,   555,
+     559,   563,   567,   571,   578,   581,   587,   594,   601,   604,
+     610,   619,   623,   627,   631,   635,   642,   649,   652,   659,
+     667,   687,   697,   705,   730,   734,   738,   742,   749,   756,
+     759,   763,   767,   772,   777,   784,   788,   792,   796,   801,
+     806,   813,   823,   829,   832,   838,   842,   849,   855,   862,
+     866,   869,   872,   881,   887,   895,   898,   918,   937,   944,
+     948,   955,   965,   968,   971,   977,   984,   987,   993,   996,
+     999,  1005,  1008,  1013,  1024,  1027,  1030,  1033,  1036,  1039,
+    1043,  1047,  1051,  1055,  1059,  1063,  1067,  1071,  1075,  1079,
+    1083,  1087,  1091,  1095,  1099,  1103,  1107,  1111,  1115,  1119,
+    1123,  1126,  1129,  1132,  1135,  1138,  1141,  1144,  1147,  1150,
+    1153,  1156,  1159,  1162,  1165,  1168,  1175,  1181,  1184,  1196,
+    1196,  1199,  1199,  1205,  1208,  1223,  1226,  1233,  1237,  1243,
+    1249,  1261,  1265,  1269,  1270,  1276,  1277,  1278,  1279,  1280,
+    1281,  1282,  1286,  1287,  1287,  1287,  1297,  1298,  1302,  1302,
+    1303,  1303,  1308,  1311,  1321,  1324,  1330,  1331,  1335,  1342,
+    1346,  1353,  1353,  1360,  1363,  1370,  1374,  1387,  1387,  1392,
+    1392,  1398,  1398,  1406,  1409,  1415,  1418,  1424,  1428,  1435,
+    1438,  1441,  1444,  1447,  1456,  1460,  1467,  1470,  1476,  1476
 };
 #endif
 
@@ -3061,7 +3062,7 @@
             context->error((yylsp[-3]), "precision is not supported in fragment shader", "highp");
         }
         if (!context->symbolTable.setDefaultPrecision( (yyvsp[-1].interm.type), (yyvsp[-2].interm.precision) )) {
-            context->error((yylsp[-3]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[-1].interm.type).type));
+            context->error((yylsp[-3]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[-1].interm.type).getBasicType()));
         }
         (yyval.interm.intermNode) = 0;
     }
@@ -3186,7 +3187,7 @@
   case 102:
 
     {
-        if ((yyvsp[-1].interm.type).type == EbtVoid) {
+        if ((yyvsp[-1].interm.type).getBasicType() == EbtVoid) {
             context->error((yylsp[0]), "illegal use of type 'void'", (yyvsp[0].lex).string->c_str());
         }
         context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
@@ -3599,7 +3600,7 @@
         (yyval.interm.type) = (yyvsp[0].interm.type);
 
         if ((yyval.interm.type).precision == EbpUndefined) {
-            (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).type);
+            (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).getBasicType());
         }
     }
 
@@ -3681,7 +3682,7 @@
   case 151:
 
     {
-        (yyval.interm.type) = (yyvsp[0].interm.type);
+        (yyval.interm.type).initialize((yyvsp[0].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
     }
 
     break;
@@ -3690,7 +3691,7 @@
 
     {
         ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array");
-        (yyval.interm.type) = (yyvsp[-2].interm.type);
+        (yyval.interm.type).initialize((yyvsp[-2].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
         (yyval.interm.type).setArraySize(0);
     }
 
@@ -3699,9 +3700,8 @@
   case 153:
 
     {
-        (yyval.interm.type) = (yyvsp[-3].interm.type);
-
-        if (context->checkIsValidTypeForArray((yylsp[-2]), (yyvsp[-3].interm.type)))
+        (yyval.interm.type).initialize((yyvsp[-3].interm.typeSpecifierNonArray), (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+        if (context->checkIsValidTypeForArray((yylsp[-2]), (yyval.interm.type)))
         {
             unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
             (yyval.interm.type).setArraySize(size);
@@ -3713,8 +3713,7 @@
   case 154:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtVoid, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtVoid, (yylsp[0]));
     }
 
     break;
@@ -3722,8 +3721,7 @@
   case 155:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
     }
 
     break;
@@ -3731,8 +3729,7 @@
   case 156:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
     }
 
     break;
@@ -3740,8 +3737,7 @@
   case 157:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
     }
 
     break;
@@ -3749,8 +3745,7 @@
   case 158:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
     }
 
     break;
@@ -3758,9 +3753,8 @@
   case 159:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
     }
 
     break;
@@ -3768,9 +3762,8 @@
   case 160:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
     }
 
     break;
@@ -3778,9 +3771,8 @@
   case 161:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
     }
 
     break;
@@ -3788,9 +3780,8 @@
   case 162:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
     }
 
     break;
@@ -3798,9 +3789,8 @@
   case 163:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
     }
 
     break;
@@ -3808,9 +3798,8 @@
   case 164:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
     }
 
     break;
@@ -3818,9 +3807,8 @@
   case 165:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
     }
 
     break;
@@ -3828,9 +3816,8 @@
   case 166:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
     }
 
     break;
@@ -3838,9 +3825,8 @@
   case 167:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
     }
 
     break;
@@ -3848,9 +3834,8 @@
   case 168:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(2);
     }
 
     break;
@@ -3858,9 +3843,8 @@
   case 169:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(3);
     }
 
     break;
@@ -3868,9 +3852,8 @@
   case 170:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUInt, qual, (yylsp[0]));
-        (yyval.interm.type).setAggregate(4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setAggregate(4);
     }
 
     break;
@@ -3878,9 +3861,8 @@
   case 171:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(2, 2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2);
     }
 
     break;
@@ -3888,9 +3870,8 @@
   case 172:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(3, 3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3);
     }
 
     break;
@@ -3898,9 +3879,8 @@
   case 173:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(4, 4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4);
     }
 
     break;
@@ -3908,9 +3888,8 @@
   case 174:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(2, 3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3);
     }
 
     break;
@@ -3918,9 +3897,8 @@
   case 175:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(3, 2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2);
     }
 
     break;
@@ -3928,9 +3906,8 @@
   case 176:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(2, 4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4);
     }
 
     break;
@@ -3938,9 +3915,8 @@
   case 177:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(4, 2);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2);
     }
 
     break;
@@ -3948,9 +3924,8 @@
   case 178:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(3, 4);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4);
     }
 
     break;
@@ -3958,9 +3933,8 @@
   case 179:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[0]));
-        (yyval.interm.type).setMatrix(4, 3);
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3);
     }
 
     break;
@@ -3968,8 +3942,7 @@
   case 180:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2D, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2D, (yylsp[0]));
     }
 
     break;
@@ -3977,8 +3950,7 @@
   case 181:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler3D, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler3D, (yylsp[0]));
     }
 
     break;
@@ -3986,8 +3958,7 @@
   case 182:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCube, (yylsp[0]));
     }
 
     break;
@@ -3995,8 +3966,7 @@
   case 183:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2DArray, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArray, (yylsp[0]));
     }
 
     break;
@@ -4004,8 +3974,7 @@
   case 184:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtISampler2D, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2D, (yylsp[0]));
     }
 
     break;
@@ -4013,8 +3982,7 @@
   case 185:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtISampler3D, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler3D, (yylsp[0]));
     }
 
     break;
@@ -4022,8 +3990,7 @@
   case 186:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtISamplerCube, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCube, (yylsp[0]));
     }
 
     break;
@@ -4031,8 +3998,7 @@
   case 187:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtISampler2DArray, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DArray, (yylsp[0]));
     }
 
     break;
@@ -4040,8 +4006,7 @@
   case 188:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUSampler2D, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2D, (yylsp[0]));
     }
 
     break;
@@ -4049,8 +4014,7 @@
   case 189:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUSampler3D, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler3D, (yylsp[0]));
     }
 
     break;
@@ -4058,8 +4022,7 @@
   case 190:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUSamplerCube, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCube, (yylsp[0]));
     }
 
     break;
@@ -4067,8 +4030,7 @@
   case 191:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtUSampler2DArray, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DArray, (yylsp[0]));
     }
 
     break;
@@ -4076,8 +4038,7 @@
   case 192:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2DShadow, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DShadow, (yylsp[0]));
     }
 
     break;
@@ -4085,8 +4046,7 @@
   case 193:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSamplerCubeShadow, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeShadow, (yylsp[0]));
     }
 
     break;
@@ -4094,8 +4054,7 @@
   case 194:
 
     {
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2DArrayShadow, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArrayShadow, (yylsp[0]));
     }
 
     break;
@@ -4107,8 +4066,7 @@
             !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) {
             context->error((yylsp[0]), "unsupported type", "samplerExternalOES");
         }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0]));
     }
 
     break;
@@ -4119,8 +4077,7 @@
         if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
             context->error((yylsp[0]), "unsupported type", "sampler2DRect");
         }
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0]));
     }
 
     break;
@@ -4128,8 +4085,7 @@
   case 197:
 
     {
-        (yyval.interm.type) = (yyvsp[0].interm.type);
-        (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray);
     }
 
     break;
@@ -4142,9 +4098,8 @@
         // type.
         //
         TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType();
-        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-        (yyval.interm.type).setBasic(EbtStruct, qual, (yylsp[0]));
-        (yyval.interm.type).userDef = &structure;
+        (yyval.interm.typeSpecifierNonArray).initialize(EbtStruct, (yylsp[0]));
+        (yyval.interm.typeSpecifierNonArray).userDef = &structure;
     }
 
     break;
@@ -4158,7 +4113,7 @@
   case 200:
 
     {
-        (yyval.interm.type) = context->addStructure((yylsp[-5]), (yylsp[-4]), (yyvsp[-4].lex).string, (yyvsp[-1].interm.fieldList));
+        (yyval.interm.typeSpecifierNonArray) = context->addStructure((yylsp[-5]), (yylsp[-4]), (yyvsp[-4].lex).string, (yyvsp[-1].interm.fieldList));
     }
 
     break;
@@ -4172,7 +4127,7 @@
   case 202:
 
     {
-        (yyval.interm.type) = context->addStructure((yylsp[-4]), (yyloc), NewPoolTString(""), (yyvsp[-1].interm.fieldList));
+        (yyval.interm.typeSpecifierNonArray) = context->addStructure((yylsp[-4]), (yyloc), NewPoolTString(""), (yyvsp[-1].interm.fieldList));
     }
 
     break;
diff --git a/src/compiler/translator/glslang_tab.h b/src/compiler/translator/glslang_tab.h
index 5e63dd1..d0e691d 100644
--- a/src/compiler/translator/glslang_tab.h
+++ b/src/compiler/translator/glslang_tab.h
@@ -208,6 +208,7 @@
             TIntermCase* intermCase;
         };
         union {
+            TTypeSpecifierNonArray typeSpecifierNonArray;
             TPublicType type;
             TPrecision precision;
             TLayoutQualifier layoutQualifier;