Move binary op array check to ParseContext
Also piece together an addAssign function in ParseContext that uses the
binary op array check. This will make it easier to change the
array-related checks in the future to use shaderVersion. Moving
validation out from IntermBinary::promote also makes the architecture
clearer, promote()'s role should be mainly to determine the type of the
return value of the binary operation, not to do validation.
BUG=angleproject:941
TEST=angle_unittests, WebGL conformance tests
Change-Id: If1de33ea250893527be7f0d7930d4678a0864684
Reviewed-on: https://chromium-review.googlesource.com/260571
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index bf4d105..15fa778 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1198,7 +1198,7 @@
if (qualifier != EvqConst) {
TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
- intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
+ intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
if (intermNode == 0) {
assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
return true;
@@ -2716,21 +2716,34 @@
return addUnaryMath(op, child, loc);
}
+bool TParseContext::binaryOpArrayCheck(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ if (left->isArray() || right->isArray())
+ {
+ error(loc, "Invalid operation for arrays", GetOperatorString(op));
+ return false;
+ }
+ return true;
+}
+
TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
+ if (!binaryOpArrayCheck(op, left, right, loc))
+ return nullptr;
+
switch (op)
{
case EOpEqual:
case EOpNotEqual:
- if (left->isArray())
- return nullptr;
break;
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- if (left->isMatrix() || left->isArray() || left->isVector() ||
+ ASSERT(!left->isArray() && !right->isArray());
+ if (left->isMatrix() || left->isVector() ||
left->getBasicType() == EbtStruct)
{
return nullptr;
@@ -2739,8 +2752,9 @@
case EOpLogicalOr:
case EOpLogicalXor:
case EOpLogicalAnd:
+ ASSERT(!left->isArray() && !right->isArray());
if (left->getBasicType() != EbtBool ||
- left->isMatrix() || left->isArray() || left->isVector())
+ left->isMatrix() || left->isVector())
{
return nullptr;
}
@@ -2749,12 +2763,14 @@
case EOpSub:
case EOpDiv:
case EOpMul:
+ ASSERT(!left->isArray() && !right->isArray());
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
{
return nullptr;
}
break;
case EOpIMod:
+ ASSERT(!left->isArray() && !right->isArray());
// Note that this is only for the % operator, not for mod()
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
{
@@ -2804,6 +2820,29 @@
return node;
}
+TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ if (binaryOpArrayCheck(op, left, right, loc))
+ {
+ return intermediate.addAssign(op, left, right, loc);
+ }
+ return nullptr;
+}
+
+TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ TIntermTyped *node = createAssign(op, left, right, loc);
+ if (node == nullptr)
+ {
+ assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
+ recover();
+ return left;
+ }
+ return node;
+}
+
TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
{
switch (op)