Fix latent bug in this() calls needing synthetic ctor args.

When processing a this() constructor invocation, the GWT compiler currently has a bug where it tries to reference a field that hasn't yet been assigned.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9659 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index 82dd29a..42bc89c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -841,9 +841,7 @@
         if (nestedBinding.enclosingInstances != null) {
           for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
             SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
-            if (arg.matchingField != null) {
-              createField(arg, type, Disposition.THIS_REF);
-            }
+            createField(arg, type, Disposition.THIS_REF);
           }
         }
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 38a03fd..1557dc4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -752,25 +752,25 @@
          * this constructor call, in which case the callee will assign them for
          * us.
          */
-        if (!hasExplicitThis) {
-          ReferenceBinding declaringClass = x.binding.declaringClass;
-          if (declaringClass instanceof NestedTypeBinding) {
-            Iterator<JParameter> paramIt = currentMethod.getParams().iterator();
-            NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
-            if (nestedBinding.enclosingInstances != null) {
-              for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
-                JParameter param = paramIt.next();
-                if (arg.matchingField != null) {
-                  JField field = (JField) typeMap.get(arg);
-                  block.addStmt(JProgram.createAssignmentStmt(info,
-                      createVariableRef(info, field),
-                      createVariableRef(info, param)));
-                  currentOuterThisRefParams = Maps.put(
-                      currentOuterThisRefParams, field, param);
-                }
+        ReferenceBinding declaringClass = x.binding.declaringClass;
+        if (declaringClass instanceof NestedTypeBinding) {
+          Iterator<JParameter> paramIt = currentMethod.getParams().iterator();
+          NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
+          if (nestedBinding.enclosingInstances != null) {
+            for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
+              JParameter param = paramIt.next();
+              JField field = (JField) typeMap.get(arg);
+              if (!hasExplicitThis) {
+                block.addStmt(JProgram.createAssignmentStmt(info,
+                    createVariableRef(info, field),
+                    createVariableRef(info, param)));
               }
+              currentOuterThisRefParams = Maps.put(currentOuterThisRefParams,
+                  field, param);
             }
+          }
 
+          if (!hasExplicitThis) {
             paramIt = getSyntheticLocalsIterator();
             if (nestedBinding.outerLocalVariables != null) {
               for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
@@ -2550,6 +2550,15 @@
 
           // now we have an updated variable that we can create our ref from
         }
+      } else {
+        assert variable instanceof JField;
+        // In a constructor, prefer the ctor arg rather than the field.
+        if (currentOuterThisRefParams != null) {
+          JParameter ctorArg = currentOuterThisRefParams.get(variable);
+          if (ctorArg != null) {
+            variable = ctorArg;
+          }
+        }
       }
       return variable;
     }
diff --git a/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java b/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java
index e38a869..072974a 100644
--- a/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/InnerClassTest.java
@@ -25,6 +25,12 @@
  */
 public class InnerClassTest extends GWTTestCase {
 
+  static class OuterRefFromSuperCtorBase {
+    OuterRefFromSuperCtorBase(Object o) {
+      o.toString();
+    }
+  }
+
   class InnerClass {
     {
       callInner();
@@ -45,12 +51,6 @@
     }
   }
 
-  class OuterRefFromSuperCtorBase {
-    OuterRefFromSuperCtorBase(Object o) {
-      o.toString();
-    }
-  }
-
   class OuterRefFromSuperCtorCall extends OuterRefFromSuperCtorBase {
     OuterRefFromSuperCtorCall() {
       super(new Object() {
@@ -63,6 +63,22 @@
     }
   }
 
+  class OuterRefFromThisCtorCall extends OuterRefFromSuperCtorBase {
+    public OuterRefFromThisCtorCall(Object object) {
+      super(object);
+    }
+
+    public OuterRefFromThisCtorCall() {
+      this(new Object() {
+        @Override
+        public String toString() {
+          testAppend.append("OuterRefFromThisCtorCall");
+          return "";
+        }
+      });
+    }
+  }
+
   static class P1<T1> {
     class P2<T2> extends P1<T1> {
       class P3<T3> extends P2<T2> {
@@ -150,4 +166,8 @@
     assertEquals("OuterRefFromSuperCtorCall", testAppend.toString());
   }
 
+  public void testOuterThisFromThisCall() {
+    new OuterRefFromThisCtorCall();
+    assertEquals("OuterRefFromThisCtorCall", testAppend.toString());
+  }
 }