Go patch committed: Ensure evaluation order in type hash/eq functions
diff mbox series

Message ID CAOyqgcWCdRzn=SXTO7EF_w6O_L6aoZ-5xUDjymqwGFSqwxdcXQ@mail.gmail.com
State New
Headers show
Series
  • Go patch committed: Ensure evaluation order in type hash/eq functions
Related show

Commit Message

Ian Lance Taylor July 11, 2019, 9:37 p.m. UTC
This Go frontend patch by Cherry Zhang ensures correct evaluation
order in type hash/equality functions.  The type hash and equality
functions are generated after the order_evaluations pass.  They may
contain shortcut operators and Set_and_use_temporary_expressions (e.g.
from lowering a Binary_exprssion) that need to be ordered.  Run
order_evaluations and remove_shortcuts on these functions.  (The hash
functions may be fine, but to be on the safe side we run on them
anyway.  We do need to run on the equality functions.)

A Set_and_use_temporary_expression is effectively an assignment, so it
needs to be ordered.  Otherwise if we insert a temporary statement
before it, we may get wrong evaluation order.

A test case is https://golang.org/cl/185818.

This fixes https://golang.org/issue/33062.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

Patch
diff mbox series

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 273364)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-ec754ff4617d564d3dc377121ea9ac5e55f6535a
+70ceba5e95716653b9f829a457a44a829175d4da
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 273307)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -1628,6 +1628,10 @@  class Set_and_use_temporary_expression :
   }
 
   bool
+  do_must_eval_in_order() const
+  { return true; }
+
+  bool
   do_is_addressable() const
   { return true; }
 
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 273364)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -4097,6 +4097,15 @@  Gogo::order_evaluations()
   this->traverse(&order_eval);
 }
 
+// Order evaluations in a block.
+
+void
+Gogo::order_block(Block* block)
+{
+  Order_eval order_eval(this);
+  block->traverse(&order_eval);
+}
+
 // A traversal class used to find a single shortcut operator within an
 // expression.
 
@@ -4306,6 +4315,15 @@  Gogo::remove_shortcuts()
   this->traverse(&shortcuts);
 }
 
+// Turn shortcut operators into explicit if statements in a block.
+
+void
+Gogo::remove_shortcuts_in_block(Block* block)
+{
+  Shortcuts shortcuts(this);
+  block->traverse(&shortcuts);
+}
+
 // Traversal to flatten parse tree after order of evaluation rules are applied.
 
 class Flatten : public Traverse
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 273364)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -749,10 +749,18 @@  class Gogo
   void
   remove_shortcuts();
 
+  // Turn short-cut operators into explicit if statements in a block.
+  void
+  remove_shortcuts_in_block(Block*);
+
   // Use temporary variables to force order of evaluation.
   void
   order_evaluations();
 
+  // Order evaluations in a block.
+  void
+  order_block(Block*);
+
   // Add write barriers as needed.
   void
   add_write_barriers();
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 273307)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -2098,6 +2098,8 @@  Type::write_specific_type_functions(Gogo
   Block* b = gogo->finish_block(bloc);
   gogo->add_block(b, bloc);
   gogo->lower_block(hash_fn, b);
+  gogo->order_block(b);
+  gogo->remove_shortcuts_in_block(b);
   gogo->finish_function(bloc);
 
   Named_object *equal_fn = gogo->start_function(equal_name, equal_fntype,
@@ -2119,6 +2121,8 @@  Type::write_specific_type_functions(Gogo
   b = gogo->finish_block(bloc);
   gogo->add_block(b, bloc);
   gogo->lower_block(equal_fn, b);
+  gogo->order_block(b);
+  gogo->remove_shortcuts_in_block(b);
   gogo->finish_function(bloc);
 
   // Build the function descriptors for the type descriptor to refer to.