compiler: ensure evaluation order in type hash/eq functions
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 11 Jul 2019 21:37:33 +0000 (21:37 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 11 Jul 2019 21:37:33 +0000 (21:37 +0000)
    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 CL 185818.

    Fixes golang/go#33062.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/185817

From-SVN: r273425

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/types.cc

index 7b3f874123da409f818dda759c0ebbcf2f775aa0..28fc22309dd92dca546255ab1910f951ab6ee7c8 100644 (file)
@@ -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 2c6a08094d102e51eed6098ed32dee992750d946..3b65e7a5f0c96ed40ce898d3900640a40a8b93d4 100644 (file)
@@ -1627,6 +1627,10 @@ class Set_and_use_temporary_expression : public Expression
                                      this->location());
   }
 
+  bool
+  do_must_eval_in_order() const
+  { return true; }
+
   bool
   do_is_addressable() const
   { return true; }
index 234a4f44a4bdcb2dd5f5e6b2f6d8bc2f93a34665..f9a18bc462771bd6ac7c6c05b9f1a89ec372857d 100644 (file)
@@ -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 cb8e25f446f926de499ed5d5a3ec4da14293e4ed..6ffdc59bebc524ec93729e92031dc6359e5f7d22 100644 (file)
@@ -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 cc65bd8d749e905239dd3f337889b620e0a29eba..b46525d78727122cb3c49e231a4696afadd9ab6f 100644 (file)
@@ -2098,6 +2098,8 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size,
   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* gogo, Named_type* name, int64_t size,
   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.