Remove TIntermediate::addConstantUnion

This includes asserts in TConstantUnion to reveal incorrect usage of
union - reading a different field of an union that has last been set
is undefined behavior in C++.

Existing issues with accessing incorrect fields of constant unions
are fixed.

BUG=angleproject:1490
TEST=angle_unittests

Change-Id: Idd6b7a871d73e2928f117a9348c92043612fab82
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 8b04ae2..7c7e360 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -128,8 +128,7 @@
                              bool checksPrecErrors,
                              TDiagnostics *diagnostics,
                              const ShBuiltInResources &resources)
-    : intermediate(),
-      symbolTable(symt),
+    : symbolTable(symt),
       mDeferredNonEmptyDeclarationErrorCheck(false),
       mShaderType(type),
       mShaderSpec(spec),
@@ -764,12 +763,14 @@
 
 // This function checks to see if the node (for the expression) contains a scalar boolean expression
 // or not.
-void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
+bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
 {
     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
     {
         error(line, "boolean expression expected", "");
+        return false;
     }
+    return true;
 }
 
 // This function checks to see if the node (for the expression) contains a scalar boolean expression
@@ -1558,6 +1559,15 @@
     return result;
 }
 
+TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
+                                                      const TSourceLoc &line)
+{
+    TIntermConstantUnion *node = new TIntermConstantUnion(
+        constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
+    node->setLine(line);
+    return node;
+}
+
 /////////////////////////////////////////////////////////////////////////////////
 //
 // Non-Errors.
@@ -1654,10 +1664,12 @@
               "gl_ViewID_OVR");
     }
 
+    TIntermTyped *node = nullptr;
+
     if (variable->getConstPointer())
     {
         const TConstantUnion *constArray = variable->getConstPointer();
-        return intermediate.addConstantUnion(constArray, variable->getType(), location);
+        node = new TIntermConstantUnion(constArray, variable->getType());
     }
     else if (variable->getType().getQualifier() == EvqWorkGroupSize &&
              mComputeShaderLocalSizeDeclared)
@@ -1676,15 +1688,15 @@
 
         TType type(variable->getType());
         type.setQualifier(EvqConst);
-        return intermediate.addConstantUnion(constArray, type, location);
+        node = new TIntermConstantUnion(constArray, type);
     }
     else
     {
-        TIntermSymbol *symbolNode =
-            new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
-        symbolNode->setLine(location);
-        return symbolNode;
+        node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
     }
+    ASSERT(node != nullptr);
+    node->setLine(location);
+    return node;
 }
 
 // Initializers show up in several places in the grammar.  Have one set of
@@ -1898,10 +1910,10 @@
                                       TIntermNodePair code,
                                       const TSourceLoc &loc)
 {
-    checkIsScalarBool(loc, cond);
+    bool isScalarBool = checkIsScalarBool(loc, cond);
 
     // For compile time constant conditions, prune the code now.
-    if (cond->getAsConstantUnion())
+    if (isScalarBool && cond->getAsConstantUnion())
     {
         if (cond->getAsConstantUnion()->getBConst(0) == true)
         {
@@ -3338,10 +3350,7 @@
             error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
         }
 
-        TConstantUnion *unionArray = new TConstantUnion[1];
-        unionArray->setFConst(0.0f);
-        return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
-                                             location);
+        return TIntermTyped::CreateZero(TType(EbtFloat, EbpHigh, EvqConst));
     }
 
     TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
@@ -3377,7 +3386,15 @@
         // handle this case is to report a warning instead of an error and force the index to be in
         // the correct range.
         bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
-        int index                   = indexConstantUnion->getIConst(0);
+        int index                   = 0;
+        if (indexConstantUnion->getBasicType() == EbtInt)
+        {
+            index = indexConstantUnion->getIConst(0);
+        }
+        else if (indexConstantUnion->getBasicType() == EbtUInt)
+        {
+            index = static_cast<int>(indexConstantUnion->getUConst(0));
+        }
 
         int safeIndex = -1;
 
@@ -3428,11 +3445,12 @@
         // Data of constant unions can't be changed, because it may be shared with other
         // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
         // sanitized object.
-        if (safeIndex != index)
+        if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
         {
             TConstantUnion *safeConstantUnion = new TConstantUnion();
             safeConstantUnion->setIConst(safeIndex);
             indexConstantUnion->replaceConstantUnion(safeConstantUnion);
+            indexConstantUnion->getTypePointer()->setBasicType(EbtInt);
         }
 
         TIntermBinary *node = new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
@@ -4555,14 +4573,12 @@
                                                         const TSourceLoc &loc)
 {
     TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
-    if (node == 0)
+    if (node == nullptr)
     {
         binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
                       right->getCompleteString());
-        TConstantUnion *unionArray = new TConstantUnion[1];
-        unionArray->setBConst(false);
-        return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
-                                             loc);
+        node = TIntermTyped::CreateZero(TType(EbtBool, EbpUndefined, EvqConst));
+        node->setLine(loc);
     }
     return node;
 }
@@ -4894,7 +4910,10 @@
         }
     }
     unionArray->setIConst(arraySize);
-    return intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
+    TIntermConstantUnion *node =
+        new TIntermConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst));
+    node->setLine(loc);
+    return node;
 }
 
 TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
@@ -5000,7 +5019,10 @@
                                                  TIntermTyped *falseExpression,
                                                  const TSourceLoc &loc)
 {
-    checkIsScalarBool(loc, cond);
+    if (!checkIsScalarBool(loc, cond))
+    {
+        return falseExpression;
+    }
 
     if (trueExpression->getType() != falseExpression->getType())
     {