Commit a8b9ee6f by Ian Lance Taylor

compiler: ensure evaluation order in type hash/eq 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 CL 185818.
    
    Fixes golang/go#33062.
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/185817

From-SVN: r273425
parent bee60edc
ec754ff4617d564d3dc377121ea9ac5e55f6535a 70ceba5e95716653b9f829a457a44a829175d4da
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -1628,6 +1628,10 @@ class Set_and_use_temporary_expression : public Expression ...@@ -1628,6 +1628,10 @@ class Set_and_use_temporary_expression : public Expression
} }
bool bool
do_must_eval_in_order() const
{ return true; }
bool
do_is_addressable() const do_is_addressable() const
{ return true; } { return true; }
......
...@@ -4097,6 +4097,15 @@ Gogo::order_evaluations() ...@@ -4097,6 +4097,15 @@ Gogo::order_evaluations()
this->traverse(&order_eval); 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 // A traversal class used to find a single shortcut operator within an
// expression. // expression.
...@@ -4306,6 +4315,15 @@ Gogo::remove_shortcuts() ...@@ -4306,6 +4315,15 @@ Gogo::remove_shortcuts()
this->traverse(&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. // Traversal to flatten parse tree after order of evaluation rules are applied.
class Flatten : public Traverse class Flatten : public Traverse
......
...@@ -749,10 +749,18 @@ class Gogo ...@@ -749,10 +749,18 @@ class Gogo
void void
remove_shortcuts(); 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. // Use temporary variables to force order of evaluation.
void void
order_evaluations(); order_evaluations();
// Order evaluations in a block.
void
order_block(Block*);
// Add write barriers as needed. // Add write barriers as needed.
void void
add_write_barriers(); add_write_barriers();
......
...@@ -2098,6 +2098,8 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size, ...@@ -2098,6 +2098,8 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size,
Block* b = gogo->finish_block(bloc); Block* b = gogo->finish_block(bloc);
gogo->add_block(b, bloc); gogo->add_block(b, bloc);
gogo->lower_block(hash_fn, b); gogo->lower_block(hash_fn, b);
gogo->order_block(b);
gogo->remove_shortcuts_in_block(b);
gogo->finish_function(bloc); gogo->finish_function(bloc);
Named_object *equal_fn = gogo->start_function(equal_name, equal_fntype, 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, ...@@ -2119,6 +2121,8 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size,
b = gogo->finish_block(bloc); b = gogo->finish_block(bloc);
gogo->add_block(b, bloc); gogo->add_block(b, bloc);
gogo->lower_block(equal_fn, b); gogo->lower_block(equal_fn, b);
gogo->order_block(b);
gogo->remove_shortcuts_in_block(b);
gogo->finish_function(bloc); gogo->finish_function(bloc);
// Build the function descriptors for the type descriptor to refer to. // Build the function descriptors for the type descriptor to refer to.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment