This patch by Chris Manghane fixes a bug in the escape analysis pass of the Go frontend. The slice created to hold the values passed to a varargs parameter would always escape. This also fixes a bug in which a stack-allocated varargs parameter was incorrectly initialized in some cases. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline.
Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 240755) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -325f8074c5224ae537f8e00aede5c780b70f914c +60b84be3fa146d821dcd3939dad6336c89432cff The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/escape.cc =================================================================== --- gcc/go/gofrontend/escape.cc (revision 240755) +++ gcc/go/gofrontend/escape.cc (working copy) @@ -1215,7 +1215,7 @@ Escape_analysis_assign::expression(Expre "special treatment of append(slice1, slice2...)"); // The content of the original slice leaks as well. - Node* appendee = Node::make_node(call->args()->back()); + Node* appendee = Node::make_node(call->args()->front()); this->assign_deref(this->context_->sink(), appendee); } break; @@ -2088,6 +2088,36 @@ Escape_analysis_assign::assign_deref(Nod // or numeric constants. return; + case Expression::EXPRESSION_FIXED_ARRAY_CONSTRUCTION: + case Expression::EXPRESSION_SLICE_CONSTRUCTION: + case Expression::EXPRESSION_STRUCT_CONSTRUCTION: + { + // Dereferencing an array, slice, or struct is like accessing each + // of its values. In this situation, we model the flow from src to + // dst where src is one of the above as a flow from each of src's + // values to dst. + Expression* e = src->expr(); + Expression_list* vals = NULL; + if (e->slice_literal() != NULL) + vals = e->slice_literal()->vals(); + else if (e->array_literal() != NULL) + vals = e->array_literal()->vals(); + else + vals = e->struct_literal()->vals(); + + if (vals != NULL) + { + for (Expression_list::const_iterator p = vals->begin(); + p != vals->end(); + ++p) + { + if ((*p) != NULL) + this->assign(dst, Node::make_node(*p)); + } + } + } + return; + default: break; }