compiler: do order_evaluations before remove_shortcuts

In remove_shortcuts, the shortcut expressions (&&, ||) are
rewritten to if statements, which are lifted out before the
statement containing the shortcut expression. If the containing
statement has other (sub)expressions that should be evaluated
before the shortcut expression, which has not been lifted out,
this will result in wrong evaluation order.

For example, F() + G(A() && B()), the evaluation order per spec
is F, A, B (if A returns true), G. If we lift A() and B() out
first, they will be called before F, which is wrong.

To fix this, we split order_evaluations to two phases. The first
phase, which runs before remove_shortcuts, skips shortcut
expressions' components. So it won't lift out subexpressions that
are evaluated conditionally. The shortcut expression itself is
ordered, since it may have side effects. Then we run
remove_shortcuts. At this point the subexpressions that should be
evaluated before the shortcut expression are already lifted out.
remove_shortcuts also runs the second phase of order_evaluations
to order the components of shortcut expressions, which were
skipped during the first phase.

Reorder the code blocks of remove_shortcuts and order_evaluations,
since remove_shortcuts now calls Order_eval.

Fixes golang/go#26495.

Change-Id: Ifabd6b69c7d23e711a810d6bd36dc815a8023ebc
Reviewed-on: https://go-review.googlesource.com/125299
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2 files changed