Cherrypick r11332 into 2.5 release branch
Fix for Issue tracker issue #5739

Review by: rdayal@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.5@11341 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
index aeb0cf7..2de8465 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
@@ -22,6 +22,7 @@
 import com.google.gwt.dev.jjs.ast.JBlock;
 import com.google.gwt.dev.jjs.ast.JBreakStatement;
 import com.google.gwt.dev.jjs.ast.JCaseStatement;
+import com.google.gwt.dev.jjs.ast.JCastOperation;
 import com.google.gwt.dev.jjs.ast.JClassType;
 import com.google.gwt.dev.jjs.ast.JConditional;
 import com.google.gwt.dev.jjs.ast.JContinueStatement;
@@ -35,6 +36,7 @@
 import com.google.gwt.dev.jjs.ast.JIfStatement;
 import com.google.gwt.dev.jjs.ast.JLabeledStatement;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JNode;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReboundEntryPoint;
 import com.google.gwt.dev.jjs.ast.JReturnStatement;
@@ -406,6 +408,26 @@
       return false;
     }
 
+      /**
+       * Each cast operation generates optional throw.
+       * Fixes http://code.google.com/p/google-web-toolkit/issues/detail?id=5739
+       */
+      @Override
+      public boolean visit(JCastOperation x, Context ctx) {
+          accept(x.getExpr());
+
+          CfgOptionalThrowNode node = addNode(new CfgOptionalThrowNode(parent, x));
+          addNormalExit(node, CfgOptionalThrowNode.NO_THROW);
+          JDeclaredType runtimeExceptionType =
+                  program.getFromTypeMap("java.lang.RuntimeException");
+          if (runtimeExceptionType != null) {
+              addExit(Exit.createThrow(node, runtimeExceptionType,
+                      CfgOptionalThrowNode.RUNTIME_EXCEPTION));
+          }
+          addNode(new CfgCastOperationNode(parent, x));
+          return false;
+      }
+
     @Override
     public boolean visit(JConditional x, Context ctx) {
       accept(x.getIfTest());
@@ -1186,6 +1208,23 @@
     }
   }
 
+  private static class CfgCastOperationNode extends CfgSimpleNode<JNode> {
+
+    public CfgCastOperationNode(CfgNode<?> parent, JNode jNode) {
+      super(parent, jNode);
+    }
+
+    @Override
+    public void accept(CfgVisitor visitor) {
+      visitor.visitSimpleNode(this);
+    }
+
+    @Override
+    protected CfgNode<?> cloneImpl() {
+      return new CfgCastOperationNode(getParent(), getJNode());
+    }
+  }
+
   /**
    * Special exception which is thrown when we encounter some syntactic 
    * construction which is not yet supported by CfgBuilder. 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgOptionalThrowNode.java b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgOptionalThrowNode.java
index 3c52d0f..33a0372 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgOptionalThrowNode.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgOptionalThrowNode.java
@@ -15,12 +15,13 @@
  */
 package com.google.gwt.dev.jjs.impl.gflow.cfg;
 
+import com.google.gwt.dev.jjs.ast.JExpression;
 import com.google.gwt.dev.jjs.ast.JMethodCall;
 
 /**
  * Node which might throw exception.
  */
-public class CfgOptionalThrowNode extends CfgNode<JMethodCall> {
+public class CfgOptionalThrowNode extends CfgNode<JExpression> {
   /**
    * Edge role for normal, no-throwing execution.
    */
@@ -34,7 +35,7 @@
    */
   public static final String ERROR = "E";
   
-  public CfgOptionalThrowNode(CfgNode<?> parent, JMethodCall node) {
+  public CfgOptionalThrowNode(CfgNode<?> parent, JExpression node) {
     super(parent, node);
   }
 
@@ -45,7 +46,10 @@
 
   @Override
   public String toDebugString() {
-    return "OPTTHROW(" + getJNode().getTarget().getName() + "())";
+      if (getJNode() instanceof JMethodCall) {
+          return "OPTTHROW(" + ((JMethodCall) getJNode()).getTarget().getName() + "())";
+      }
+      return "OPTTHROW(" +  getJNode().toSource() + ")";
   }
 
   @Override
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java
index 60a1a00..9ee6e0d 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/DataflowOptimizerTest.java
@@ -301,6 +301,35 @@
       );
   }
 
+  /**
+   * Test fix for http://code.google.com/p/google-web-toolkit/issues/detail?id=5739
+   */
+  public void testExceptionInitializerFlow() throws Exception {
+    addSnippetClassDecl("static int foo() { return 0; }");
+    optimize("boolean", " int size = -1;\n" +
+            "  try {\n" +
+            "    size = ((Object[]) (Object)\"aaa\").length;\n" +
+            "  } catch (final Exception ex) {\n" +
+            "  }\n" +
+            "  if (size < 0) {\n" +
+            "    try {\n" +
+            "      size = 3;\n" +
+            "    } catch (final Exception ex) {\n" +
+            "    }\n" +
+            "  }\n" +
+            "  return size > 0;").into("int size = -1;\n" +
+            "  try {\n" +
+            "    size = ((Object[]) (Object)\"aaa\").length;\n" +
+            "  } catch (final Exception ex) {\n" +
+            "  }\n" +
+            "  if (size < 0) {\n" +
+            "    try {\n" +
+            "      size = 3;\n" +
+            "    } catch (final Exception ex) {\n" +
+            "    }\n" +
+            "  } return size > 0;");
+  }
+
   public void testImplicitConversion() throws Exception {
     optimize("long", 
         "int bar = 0x12345678;",