The way we were handling field references in PruneVisitor and CleanupRefsVisitor was all screwed up.  JDeclarationStatement actually got it right, so I'm copying its implementation to binary assignment.

Review by: knorton (desk check), spoon (postmortem)


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2247 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
index 3207c65..b58a5ce 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.jjs.impl;
 
+import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.jjs.ast.CanBeStatic;
 import com.google.gwt.dev.jjs.ast.Context;
 import com.google.gwt.dev.jjs.ast.HasEnclosingType;
@@ -44,7 +45,6 @@
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
 import com.google.gwt.dev.jjs.ast.JStringLiteral;
-import com.google.gwt.dev.jjs.ast.JThisRef;
 import com.google.gwt.dev.jjs.ast.JType;
 import com.google.gwt.dev.jjs.ast.JVariable;
 import com.google.gwt.dev.jjs.ast.JVariableRef;
@@ -99,15 +99,13 @@
       // The LHS of assignments may have been pruned.
       if (x.getOp() == JBinaryOperator.ASG) {
         JExpression lhs = x.getLhs();
-        if (lhs.hasSideEffects()) {
-          return;
-        }
-        if (lhs instanceof JFieldRef || lhs instanceof JLocalRef
-            || lhs instanceof JParameterRef) {
-          JVariable var = ((JVariableRef) lhs).getTarget();
-          if (!referencedNonTypes.contains(var)) {
-            // Just replace with my RHS
-            ctx.replaceMe(x.getRhs());
+        if (lhs instanceof JVariableRef) {
+          JVariableRef variableRef = (JVariableRef) lhs;
+          if (!referencedNonTypes.contains(variableRef.getTarget())) {
+            // TODO: better null tracking; we might be missing some NPEs here.
+            JExpression replacement = makeReplacementForAssignment(
+                x.getSourceInfo(), variableRef, x.getRhs());
+            ctx.replaceMe(replacement);
           }
         }
       }
@@ -116,27 +114,9 @@
     public void endVisit(JDeclarationStatement x, Context ctx) {
       // The variable may have been pruned.
       if (!referencedNonTypes.contains(x.getVariableRef().getTarget())) {
-        // Replace with a multi, which may wind up empty.
-        JMultiExpression multi = new JMultiExpression(program,
-            x.getSourceInfo());
-
-        // If the lhs is a field ref, evaluate it first.
-        JVariableRef variableRef = x.getVariableRef();
-        if (variableRef instanceof JFieldRef) {
-          JFieldRef fieldRef = (JFieldRef) variableRef;
-          JExpression instance = fieldRef.getInstance();
-          if (instance != null) {
-            multi.exprs.add(instance);
-          }
-        }
-
-        // If there is an initializer, evaluate it second.
-        JExpression initializer = x.getInitializer();
-        if (initializer != null) {
-          multi.exprs.add(initializer);
-        }
-
-        ctx.replaceMe(multi.makeStatement());
+        JExpression replacement = makeReplacementForAssignment(
+            x.getSourceInfo(), x.getVariableRef(), x.getInitializer());
+        ctx.replaceMe(replacement.makeStatement());
       }
     }
 
@@ -232,6 +212,31 @@
       return !node.isStatic() && enclosingType != null
           && !program.typeOracle.isInstantiatedType(enclosingType);
     }
+
+    private JExpression makeReplacementForAssignment(SourceInfo info,
+        JVariableRef variableRef, JExpression rhs) {
+      // Replace with a multi, which may wind up empty.
+      JMultiExpression multi = new JMultiExpression(program, info);
+
+      // If the lhs is a field ref, evaluate it first.
+      if (variableRef instanceof JFieldRef) {
+        JFieldRef fieldRef = (JFieldRef) variableRef;
+        JExpression instance = fieldRef.getInstance();
+        if (instance != null) {
+          multi.exprs.add(instance);
+        }
+      }
+
+      // If there is an initializer, evaluate it second.
+      if (rhs != null) {
+        multi.exprs.add(rhs);
+      }
+      if (multi.exprs.size() == 1) {
+        return multi.exprs.get(0);
+      } else {
+        return multi;
+      }
+    }
   }
 
   /**
@@ -487,21 +492,12 @@
           // parameters are ok to skip
           doSkip = true;
         } else if (lhs instanceof JFieldRef) {
+          // fields must rescue the qualifier
+          doSkip = true;
           JFieldRef fieldRef = (JFieldRef) lhs;
-          /*
-           * Whether we can skip depends on what the qualifier is; we have to be
-           * certain the qualifier cannot be a null pointer (in which case we'd
-           * fail to throw the appropriate exception.
-           * 
-           * TODO: better non-null tracking!
-           */
           JExpression instance = fieldRef.getInstance();
-          if (fieldRef.getField().isStatic()) {
-            // statics are always okay
-            doSkip = true;
-          } else if (instance instanceof JThisRef) {
-            // a this ref cannot be null
-            doSkip = true;
+          if (instance != null) {
+            accept(instance);
           }
         }