private Set<TreeNode> getAncestors(TreeNode node) {
   Set<TreeNode> ancestors = Sets.newHashSet();
   while (node != currentTopNode) {
     ancestors.add(node);
     node = node.getParent();
   }
   return ancestors;
 }
 private Expression getConditionChild(TreeNode conditional) {
   if (conditional instanceof InfixExpression) {
     return ((InfixExpression) conditional).getOperands().get(0);
   } else if (conditional instanceof ConditionalExpression) {
     return ((ConditionalExpression) conditional).getExpression();
   } else {
     throw new AssertionError(
         "Unexpected conditional node type: " + conditional.getClass().toString());
   }
 }
 private boolean isWithinConditionalBranch(TreeNode node, TreeNode limit) {
   while (node != limit) {
     TreeNode parent = node.getParent();
     if (isConditional(parent) && getConditionChild(parent) != node) {
       return true;
     }
     node = parent;
   }
   return false;
 }
 private TreeNode getTopConditional(TreeNode node, TreeNode limit) {
   TreeNode topConditional = null;
   while (node != limit) {
     node = node.getParent();
     if (isConditional(node)) {
       topConditional = node;
     }
   }
   return topConditional;
 }
 private void extractOrderedAccesses(
     List<Statement> stmtList, TreeNode subExpr, List<VariableAccess> toExtract) {
   for (int i = 0; i < toExtract.size(); i++) {
     VariableAccess access = toExtract.get(i);
     TreeNode topConditional = getTopConditional(access.expression, subExpr);
     if (topConditional != null) {
       // Conditional expressions require special handling when extracting the
       // access because execution of the access may not be guaranteed.
       // Here we collect all accesses that are decendant of the conditional
       // expression and pass them to an appropriate extraction method.
       int j = i + 1;
       for (; j < toExtract.size(); j++) {
         if (getTopConditional(toExtract.get(j).expression, subExpr) != topConditional) {
           break;
         }
       }
       if (topConditional instanceof InfixExpression) {
         extractInfixConditional(
             stmtList, (InfixExpression) topConditional, toExtract.subList(i, j));
       } else if (topConditional instanceof ConditionalExpression) {
         extractConditionalExpression(
             stmtList, (ConditionalExpression) topConditional, toExtract.subList(i, j));
       } else {
         throw new AssertionError(
             "Unexpected conditional node type: " + topConditional.getClass().toString());
       }
       i = j - 1;
     } else {
       IVariableBinding newVar =
           new GeneratedVariableBinding(
               "unseq$" + count++,
               0,
               access.expression.getTypeBinding(),
               false,
               false,
               null,
               currentMethod);
       stmtList.add(new VariableDeclarationStatement(newVar, access.expression.copy()));
       access.expression.replaceWith(new SimpleName(newVar));
     }
   }
 }
 private boolean isUnsequenced(
     VariableAccess modification, Set<TreeNode> modificationAncestors, VariableAccess access) {
   TreeNode commonAncestor = currentTopNode;
   TreeNode node = access.expression;
   while (node != currentTopNode) {
     if (modificationAncestors.contains(node)) {
       commonAncestor = node;
       break;
     }
     node = node.getParent();
   }
   // If either access is executed in a conditional branch that does not
   // contain the other access, then they are not unsequenced.
   if (isWithinConditionalBranch(modification.expression, commonAncestor)
       || isWithinConditionalBranch(access.expression, commonAncestor)) {
     return false;
   } else if (commonAncestor instanceof Assignment && modification.expression == commonAncestor) {
     // "i = 1 + (i = 2);" is not unsequenced.
     // "i = 1 + i++;" is unsequenced (according to clang).
     return access.expression instanceof PrefixExpression
         || access.expression instanceof PostfixExpression;
   }
   return true;
 }
  private void extractInfixConditional(
      List<Statement> stmtList, InfixExpression conditional, List<VariableAccess> toExtract) {
    InfixExpression.Operator op = conditional.getOperator();
    List<Expression> branches = conditional.getOperands();
    int lastIfExtractIdx = 0;
    IVariableBinding conditionalVar = null;
    int lastExtracted = 0;
    Expression lastBranch = null;
    for (int i = 0; i < toExtract.size(); i++) {
      VariableAccess access = toExtract.get(i);
      TreeNode node = access.expression;
      while (node.getParent() != conditional) {
        node = node.getParent();
      }
      assert node instanceof Expression;
      Expression branch = (Expression) node;

      // Extract all accesses from the previous branch.
      if (lastBranch != null && branch != lastBranch) {
        extractOrderedAccesses(stmtList, lastBranch, toExtract.subList(lastExtracted, i));
        lastExtracted = i;
      }
      lastBranch = branch;

      // If there's a new modification in a new branch, then we extract an if-statement.
      if (access.isModification && branch != branches.get(lastIfExtractIdx)) {
        ITypeBinding boolType = typeEnv.resolveJavaType("boolean");
        if (conditionalVar == null) {
          conditionalVar =
              new GeneratedVariableBinding(
                  "unseq$" + count++, 0, boolType, false, false, null, currentMethod);
          conditional.replaceWith(new SimpleName(conditionalVar));
          stmtList.add(new VariableDeclarationStatement(conditionalVar, null));
        }
        List<Expression> subBranches = branches.subList(lastIfExtractIdx, branches.indexOf(branch));
        IfStatement newIf = new IfStatement();
        Expression ifExpr =
            new Assignment(
                new SimpleName(conditionalVar), conditionalFromSubBranches(subBranches, op));
        if (op == InfixExpression.Operator.CONDITIONAL_OR) {
          ifExpr =
              new PrefixExpression(
                  boolType,
                  PrefixExpression.Operator.NOT,
                  ParenthesizedExpression.parenthesize(ifExpr));
        }
        newIf.setExpression(ifExpr);
        stmtList.add(newIf);
        Block thenBlock = new Block();
        stmtList = thenBlock.getStatements();
        newIf.setThenStatement(thenBlock);
        lastIfExtractIdx = branches.indexOf(branch);
      }
    }
    extractOrderedAccesses(
        stmtList, lastBranch, toExtract.subList(lastExtracted, toExtract.size()));
    if (conditionalVar != null) {
      List<Expression> remainingBranches = Lists.newArrayList();
      remainingBranches.add(new SimpleName(conditionalVar));
      remainingBranches.addAll(branches.subList(lastIfExtractIdx, branches.size()));
      stmtList.add(
          new ExpressionStatement(
              new Assignment(
                  new SimpleName(conditionalVar),
                  conditionalFromSubBranches(remainingBranches, op))));
    }
  }
 private void extractConditionalExpression(
     List<Statement> stmtList, ConditionalExpression conditional, List<VariableAccess> toExtract) {
   Expression condition = conditional.getExpression();
   Expression thenExpr = conditional.getThenExpression();
   Expression elseExpr = conditional.getElseExpression();
   List<VariableAccess> conditionAccesses = Lists.newArrayList();
   List<VariableAccess> thenAccesses = Lists.newArrayList();
   List<VariableAccess> elseAccesses = Lists.newArrayList();
   boolean needsExtraction = false;
   for (VariableAccess access : toExtract) {
     TreeNode node = access.expression;
     while (node.getParent() != conditional) {
       node = node.getParent();
     }
     if (node == condition) {
       conditionAccesses.add(access);
     } else if (node == thenExpr) {
       thenAccesses.add(access);
     } else if (node == elseExpr) {
       elseAccesses.add(access);
     } else {
       throw new AssertionError();
     }
     if (node != condition && access.isModification) {
       // We only need to extract an if-statement if there is a modification
       // that executes conditionally.
       needsExtraction = true;
     }
   }
   extractOrderedAccesses(stmtList, condition, conditionAccesses);
   // The recursive call might replace the condition child.
   condition = conditional.getExpression();
   if (needsExtraction) {
     IVariableBinding resultVar =
         new GeneratedVariableBinding(
             "unseq$" + count++,
             0,
             conditional.getTypeBinding(),
             false,
             false,
             null,
             currentMethod);
     conditional.replaceWith(new SimpleName(resultVar));
     stmtList.add(new VariableDeclarationStatement(resultVar, null));
     IfStatement newIf = new IfStatement();
     newIf.setExpression(condition.copy());
     stmtList.add(newIf);
     Block thenBlock = new Block();
     newIf.setThenStatement(thenBlock);
     List<Statement> thenStmts = thenBlock.getStatements();
     extractOrderedAccesses(thenStmts, thenExpr, thenAccesses);
     // The recursive call might replace the then expression child.
     thenExpr = conditional.getThenExpression();
     thenStmts.add(
         new ExpressionStatement(new Assignment(new SimpleName(resultVar), thenExpr.copy())));
     Block elseBlock = new Block();
     newIf.setElseStatement(elseBlock);
     List<Statement> elseStmts = elseBlock.getStatements();
     extractOrderedAccesses(elseStmts, elseExpr, elseAccesses);
     // The recursive call might replace the else expression child.
     elseExpr = conditional.getElseExpression();
     elseStmts.add(
         new ExpressionStatement(new Assignment(new SimpleName(resultVar), elseExpr.copy())));
   } else {
     extractOrderedAccesses(stmtList, thenExpr, thenAccesses);
     extractOrderedAccesses(stmtList, elseExpr, elseAccesses);
   }
 }