Fix HLSL compiler error with else-rewriting in functions.

In functions with return types where we would use if-else rewriting,
we would potentially generate a spurious HLSL error that warned of
branches with no return value in the function.

This was causing a maps regression where overlays would not draw
in Earth mode.

BUG=346463
BUG=391697

Change-Id: I9f4fa959057a3a2dab6cdd98f8381b5871cabf03
Reviewed-on: https://chromium-review.googlesource.com/206824
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/207834
diff --git a/src/compiler/translator/RewriteElseBlocks.cpp b/src/compiler/translator/RewriteElseBlocks.cpp
index 8a9e29e..46e510c 100644
--- a/src/compiler/translator/RewriteElseBlocks.cpp
+++ b/src/compiler/translator/RewriteElseBlocks.cpp
@@ -36,11 +36,18 @@
     return unary;
 }
 
+ElseBlockRewriter::ElseBlockRewriter()
+    : TIntermTraverser(true, false, true, false),
+      mTemporaryIndex(0),
+      mFunctionType(NULL)
+{}
+
 bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
 {
     switch (node->getOp())
     {
       case EOpSequence:
+        if (visit == PostVisit)
         {
             for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
             {
@@ -63,6 +70,11 @@
         }
         break;
 
+      case EOpFunction:
+        // Store the current function context (see comment below)
+        mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
+        break;
+
       default: break;
     }
 
@@ -82,8 +94,22 @@
     TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
                                                   typedCondition, resultType);
     TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
+    TIntermNode *negatedElse = NULL;
+
+    // crbug.com/346463
+    // D3D generates error messages claiming a function has no return value, when rewriting
+    // an if-else clause that returns something non-void in a function. By appending dummy
+    // returns (that are unreachable) we can silence this compile error.
+    if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
+    {
+        TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
+            mFunctionType->getBasicString();
+        TString rawText = "return (" + typeString + ")0";
+        negatedElse = new TIntermRaw(*mFunctionType, rawText);
+    }
+
     TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
-                                                        selection->getFalseBlock(), NULL);
+                                                        selection->getFalseBlock(), negatedElse);
     TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
                                                        selection->getTrueBlock(), falseBlock);
 
diff --git a/src/compiler/translator/RewriteElseBlocks.h b/src/compiler/translator/RewriteElseBlocks.h
index 1022133..172928f 100644
--- a/src/compiler/translator/RewriteElseBlocks.h
+++ b/src/compiler/translator/RewriteElseBlocks.h
@@ -18,16 +18,14 @@
 class ElseBlockRewriter : public TIntermTraverser
 {
   public:
-      ElseBlockRewriter()
-          : TIntermTraverser(false, false, true, false)
-          , mTemporaryIndex(0)
-      {}
+    ElseBlockRewriter();
 
   protected:
     bool visitAggregate(Visit visit, TIntermAggregate *aggregate);
 
   private:
     int mTemporaryIndex;
+    const TType *mFunctionType;
 
     TIntermNode *rewriteSelection(TIntermSelection *selection);
 };