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())
{