Implement support of unary operator "+" in translator.

BUG=angle:779
TEST=conformance/glsl/misc/struct-unary-operators.html

Change-Id: Ia827e07dcfc8ad3bbbc078e54336815be9027945
Reviewed-on: https://chromium-review.googlesource.com/222720
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Tested-by: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index b155545..bf8649c 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -336,6 +336,7 @@
             return false;
         break;
       case EOpNegative:
+      case EOpPositive:
       case EOpPostIncrement:
       case EOpPostDecrement:
       case EOpPreIncrement:
@@ -1068,6 +1069,27 @@
                 }
                 break;
 
+              case EOpPositive:
+                switch (getType().getBasicType())
+                {
+                  case EbtFloat:
+                    tempConstArray[i].setFConst(unionArray[i].getFConst());
+                    break;
+                  case EbtInt:
+                    tempConstArray[i].setIConst(unionArray[i].getIConst());
+                    break;
+                  case EbtUInt:
+                    tempConstArray[i].setUConst(static_cast<unsigned int>(
+                        static_cast<int>(unionArray[i].getUConst())));
+                    break;
+                  default:
+                    infoSink.info.message(
+                        EPrefixInternalError, getLine(),
+                        "Unary operation not folded into constant");
+                    return NULL;
+                }
+                break;
+
               case EOpLogicalNot:
                 // this code is written for possible future use,
                 // will not get executed currently
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index ec440da..0f2fec5 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -45,6 +45,7 @@
     //
 
     EOpNegative,
+    EOpPositive,
     EOpLogicalNot,
     EOpVectorLogicalNot,
 
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index ef4f833..e558683 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -198,6 +198,7 @@
       case EOpPostDecrement:
       case EOpPreDecrement:
       case EOpNegative:
+      case EOpPositive:
         if (child->getType().getBasicType() == EbtStruct ||
             child->getType().isArray())
         {
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 6d07ccc..d03abb8 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -395,6 +395,7 @@
     switch (node->getOp())
     {
       case EOpNegative: preString = "(-"; break;
+      case EOpPositive: preString = "(+"; break;
       case EOpVectorLogicalNot: preString = "not("; break;
       case EOpLogicalNot: preString = "(!"; break;
 
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index cc758e1..bded1fa 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1747,6 +1747,7 @@
     switch (node->getOp())
     {
       case EOpNegative:         outputTriplet(visit, "(-", "", ")");         break;
+      case EOpPositive:         outputTriplet(visit, "(+", "", ")");         break;
       case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");         break;
       case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");         break;
       case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)");        break;
diff --git a/src/compiler/translator/ValidateLimitations.cpp b/src/compiler/translator/ValidateLimitations.cpp
index c1a7b75..896e1cd 100644
--- a/src/compiler/translator/ValidateLimitations.cpp
+++ b/src/compiler/translator/ValidateLimitations.cpp
@@ -94,6 +94,7 @@
       case EOpLogicalXor: return "^^";
       case EOpLogicalAnd: return "&&";
       case EOpNegative: return "-";
+      case EOpPositive: return "+";
       case EOpVectorLogicalNot: return "not";
       case EOpLogicalNot: return "!";
       case EOpPostIncrement: return "++";
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 5c945ad..f8c4115 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -500,6 +500,7 @@
                 const char* errorOp = "";
                 switch($1.op) {
                 case EOpNegative:   errorOp = "-"; break;
+                case EOpPositive:   errorOp = "+"; break;
                 case EOpLogicalNot: errorOp = "!"; break;
                 default: break;
                 }
@@ -514,7 +515,7 @@
 // Grammar Note:  No traditional style type casts.
 
 unary_operator
-    : PLUS  { $$.op = EOpNull; }
+    : PLUS  { $$.op = EOpPositive; }
     | DASH  { $$.op = EOpNegative; }
     | BANG  { $$.op = EOpLogicalNot; }
     ;
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 6d483b1..567ba43 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -2919,6 +2919,7 @@
                 const char* errorOp = "";
                 switch((yyvsp[(1) - (2)].interm).op) {
                 case EOpNegative:   errorOp = "-"; break;
+                case EOpPositive:   errorOp = "+"; break;
                 case EOpLogicalNot: errorOp = "!"; break;
                 default: break;
                 }
@@ -2933,7 +2934,7 @@
 
   case 34:
 
-    { (yyval.interm).op = EOpNull; }
+    { (yyval.interm).op = EOpPositive; }
     break;
 
   case 35:
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index 56340c6..03ce5be 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -221,6 +221,7 @@
     switch (node->getOp())
     {
       case EOpNegative:       out << "Negate value";         break;
+      case EOpPositive:       out << "Positive sign";        break;
       case EOpVectorLogicalNot:
       case EOpLogicalNot:     out << "Negate conditional";   break;