OSDN Git Service

compiler: Fix order of evalation for m[0] = len(m) when m is a map.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Apr 2012 16:25:06 +0000 (16:25 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Apr 2012 16:25:06 +0000 (16:25 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@186773 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/gogo.cc

index ee68b69..7bc0b55 100644 (file)
@@ -2216,12 +2216,18 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
       Expression::traverse(&init, &find_eval_ordering);
     }
 
-  if (find_eval_ordering.size() <= 1)
-    {
-      // If there is only one expression with a side-effect, we can
-      // leave it in place.
-      return TRAVERSE_CONTINUE;
-    }
+  size_t c = find_eval_ordering.size();
+  if (c == 0)
+    return TRAVERSE_CONTINUE;
+
+  // If there is only one expression with a side-effect, we can
+  // usually leave it in place.  However, for an assignment statement,
+  // we need to evaluate an expression on the right hand side before
+  // we evaluate any index expression on the left hand side, so for
+  // that case we always move the expression.  Otherwise we mishandle
+  // m[0] = len(m) where m is a map.
+  if (c == 1 && s->classification() != Statement::STATEMENT_ASSIGNMENT)
+    return TRAVERSE_CONTINUE;
 
   bool is_thunk = s->thunk_statement() != NULL;
   for (Find_eval_ordering::const_iterator p = find_eval_ordering.begin();