aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-09-27 21:25:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-09-27 21:25:42 +0000
commitc7ff137489343e20405473156ed589ad791149d2 (patch)
treefd11b50b0605169cf1d4f1d098f40291ef7e6100 /gcc
parent437018ea2b6dc966ce40cd5dd684054126ddda6b (diff)
downloadgcc-c7ff137489343e20405473156ed589ad791149d2.zip
gcc-c7ff137489343e20405473156ed589ad791149d2.tar.gz
gcc-c7ff137489343e20405473156ed589ad791149d2.tar.bz2
compiler: avoid call duplication during order eval.
During the compiler's order_evaluations() pass, duplicate call statements were being created and inserted into block statement lists in situations where there were calls returning multiple arguments. These duplicates were benign in that they were ignored during backend code generation, however they did cause duplicate calls in AST dumps. Tweak the order evaluation code to handle this case better and avoid inserting these duplicates. Fixes golang/go#17237 Reviewed-on: https://go-review.googlesource.com/29857 From-SVN: r240559
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/gogo.cc25
2 files changed, 19 insertions, 8 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index e80ed9f..1b53f8c 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-1d8d834b5eb9f683cc06529145b353bb5b08e7ea
+8aca265d317059ae6d9721a4a231895d80d0a82c
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 7617815..587ebd4 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -3616,11 +3616,21 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
// be handled specially. We can't create a temporary
// because there is no type to give it. Any actual uses of
// the values will be done via Call_result_expressions.
- s = Statement::make_statement(*pexpr, true);
- }
+ //
+ // Since a given call expression can be shared by multiple
+ // Call_result_expressions, avoid hoisting the call the
+ // second time we see it here.
+ if (this->remember_expression(*pexpr))
+ s = NULL;
+ else
+ s = Statement::make_statement(*pexpr, true);
+ }
- block->insert_statement_before(*pindex, s);
- ++*pindex;
+ if (s != NULL)
+ {
+ block->insert_statement_before(*pindex, s);
+ ++*pindex;
+ }
}
if (init != orig_init)
@@ -7949,13 +7959,14 @@ Traverse::remember_type(const Type* type)
}
// Record that we are looking at an expression, and return true if we
-// have already seen it.
+// have already seen it. NB: this routine used to assert if the traverse
+// mask did not include expressions/types -- this is no longer the case,
+// since it can be useful to remember specific expressions during
+// walks that only cover statements.
bool
Traverse::remember_expression(const Expression* expression)
{
- go_assert((this->traverse_mask() & traverse_types) != 0
- || (this->traverse_mask() & traverse_expressions) != 0);
if (this->expressions_seen_ == NULL)
this->expressions_seen_ = new Expressions_seen();
std::pair<Expressions_seen::iterator, bool> ins =