Fix struct compound assignment being allowed in GLSL parsing

The shader translator used to accept some invalid struct operations,
like struct += struct and struct == struct with a different type. Fix
this.

BUG=angleproject:1476
TEST=angle_unittests

Change-Id: Ia2303fc1f740da4d78242e094ee6004b07364973
Reviewed-on: https://chromium-review.googlesource.com/372718
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index db64758..9a2e1c5 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -73,14 +73,6 @@
 TIntermTyped *TIntermediate::addAssign(
     TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
 {
-    if (left->getType().getStruct() || right->getType().getStruct())
-    {
-        if (left->getType() != right->getType())
-        {
-            return NULL;
-        }
-    }
-
     TIntermBinary *node = new TIntermBinary(op);
     node->setLine(line);
 
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 3476d88..1c0a871 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -3441,6 +3441,28 @@
                                         TIntermTyped *right,
                                         const TSourceLoc &loc)
 {
+    if (left->getType().getStruct() || right->getType().getStruct())
+    {
+        switch (op)
+        {
+            case EOpIndexDirectStruct:
+                ASSERT(left->getType().getStruct());
+                break;
+            case EOpEqual:
+            case EOpNotEqual:
+            case EOpAssign:
+            case EOpInitialize:
+                if (left->getType() != right->getType())
+                {
+                    return false;
+                }
+                break;
+            default:
+                error(loc, "Invalid operation for structs", GetOperatorString(op));
+                return false;
+        }
+    }
+
     if (left->isArray() || right->isArray())
     {
         if (mShaderVersion < 300)
@@ -3572,8 +3594,9 @@
         case EOpGreaterThan:
         case EOpLessThanEqual:
         case EOpGreaterThanEqual:
-            ASSERT(!left->isArray() && !right->isArray());
-            if (left->isMatrix() || left->isVector() || left->getBasicType() == EbtStruct)
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
+            if (left->isMatrix() || left->isVector())
             {
                 return nullptr;
             }
@@ -3581,7 +3604,8 @@
         case EOpLogicalOr:
         case EOpLogicalXor:
         case EOpLogicalAnd:
-            ASSERT(!left->isArray() && !right->isArray());
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
             if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
             {
                 return nullptr;
@@ -3591,17 +3615,18 @@
         case EOpSub:
         case EOpDiv:
         case EOpMul:
-            ASSERT(!left->isArray() && !right->isArray());
-            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
+            if (left->getBasicType() == EbtBool)
             {
                 return nullptr;
             }
             break;
         case EOpIMod:
-            ASSERT(!left->isArray() && !right->isArray());
+            ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+                   !right->getType().getStruct());
             // Note that this is only for the % operator, not for mod()
-            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool ||
-                left->getBasicType() == EbtFloat)
+            if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
             {
                 return nullptr;
             }