Program: 19185
Project: 19185
Buggy source:
/** 
 * Walk the AST from the call site to the expression root and verify that the portions of the expression that are evaluated before the call: 1) are unaffected by the side-effects, if any, of the call. 2) have no side-effects, that may influence the call. For example, if x has side-effects: a = 1 + x(); the call to x can be moved because the final value of "a" can not be influenced by x(), but in: a = b + x(); the call to x cannot be moved because the value of "b" may be modified by the call to x. If x is without side-effects in: a = b + x(); the call to x can be moved, but in: a = (b.foo = c) + x(); the call to x can not be moved because the value of b.foo may be referenced by x().  Note: this is true even if b is a local variable; the object that b refers to may have a global alias.
 * @return UNDECOMPOSABLE if the expression cannot be moved, DECOMPOSABLE ifdecomposition is required before the expression can be moved, otherwise MOVABLE.
 */
private DecompositionType isSubexpressionMovable(Node expressionRoot,Node subExpression){
  boolean requiresDecomposition=false;
  boolean seenSideEffects=NodeUtil.mayHaveSideEffects(subExpression,compiler);
  Node child=subExpression;
  for (  Node parent : child.getAncestors()) {
    if (parent == expressionRoot) {
      return requiresDecomposition ? DecompositionType.DECOMPOSABLE : DecompositionType.MOVABLE;
    }
    if (isConditionalOp(parent)) {
      if (child != parent.getFirstChild()) {
        requiresDecomposition=true;
      }
    }
 else {
      if (isSafeAssign(parent,seenSideEffects)) {
      }
 else {
        for (        Node n : parent.children()) {
          if (n == child) {
            break;
          }
          if (isExpressionTreeUnsafe(n,seenSideEffects)) {
            seenSideEffects=true;
            requiresDecomposition=true;
          }
        }
        Node first=parent.getFirstChild();
        if (requiresDecomposition && parent.isCall() && NodeUtil.isGet(first)) {
          if (allowMethodCallDecomposing) {
            return DecompositionType.DECOMPOSABLE;
          }
 else {
            return DecompositionType.UNDECOMPOSABLE;
          }
        }
      }
    }
    child=parent;
  }
  throw new IllegalStateException("String_Node_Str");
}

Fixed version (ground truth):
/** 
 * Walk the AST from the call site to the expression root and verify that the portions of the expression that are evaluated before the call: 1) are unaffected by the side-effects, if any, of the call. 2) have no side-effects, that may influence the call. For example, if x has side-effects: a = 1 + x(); the call to x can be moved because the final value of "a" can not be influenced by x(), but in: a = b + x(); the call to x cannot be moved because the value of "b" may be modified by the call to x. If x is without side-effects in: a = b + x(); the call to x can be moved, but in: a = (b.foo = c) + x(); the call to x can not be moved because the value of b.foo may be referenced by x().  Note: this is true even if b is a local variable; the object that b refers to may have a global alias.
 * @return UNDECOMPOSABLE if the expression cannot be moved, DECOMPOSABLE ifdecomposition is required before the expression can be moved, otherwise MOVABLE.
 */
private DecompositionType isSubexpressionMovable(Node expressionRoot,Node subExpression){
  boolean requiresDecomposition=false;
  boolean seenSideEffects=NodeUtil.mayHaveSideEffects(subExpression,compiler);
  Node child=subExpression;
  for (  Node parent : child.getAncestors()) {
    if (parent == expressionRoot) {
      return requiresDecomposition ? DecompositionType.DECOMPOSABLE : DecompositionType.MOVABLE;
    }
    if (isConditionalOp(parent)) {
      if (child != parent.getFirstChild()) {
        requiresDecomposition=true;
      }
    }
 else {
      if (isSafeAssign(parent,seenSideEffects)) {
      }
 else {
        EvaluationDirection direction=getEvaluationDirection(parent);
        for (Node n=getFirstEvaluatedChild(parent,direction); n != null; n=getNextEvaluatedSibling(n,direction)) {
          if (n == child) {
            break;
          }
          if (isExpressionTreeUnsafe(n,seenSideEffects)) {
            seenSideEffects=true;
            requiresDecomposition=true;
          }
        }
        Node first=parent.getFirstChild();
        if (requiresDecomposition && parent.isCall() && NodeUtil.isGet(first)) {
          if (allowMethodCallDecomposing) {
            return DecompositionType.DECOMPOSABLE;
          }
 else {
            return DecompositionType.UNDECOMPOSABLE;
          }
        }
      }
    }
    child=parent;
  }
  throw new IllegalStateException("String_Node_Str");
}