This patch to the Go frontend sorts array constructors by index. That is what the middle-end expects. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline and 4.7 branch.
Ian
diff -r b4118d35075b go/expressions.cc --- a/go/expressions.cc Tue May 15 12:58:54 2012 -0700 +++ b/go/expressions.cc Tue May 15 15:28:14 2012 -0700 @@ -11794,8 +11794,7 @@ if (this->indexes() == NULL) max_index = this->vals()->size() - 1; else - max_index = *std::max_element(this->indexes()->begin(), - this->indexes()->end()); + max_index = this->indexes()->back(); tree max_tree = size_int(max_index); tree constructor_type = build_array_type(element_type_tree, build_index_type(max_tree)); @@ -12546,6 +12545,17 @@ return ret; } +// Used to sort an index/value array. + +class Index_value_compare +{ + public: + bool + operator()(const std::pair<unsigned long, Expression*>& a, + const std::pair<unsigned long, Expression*>& b) + { return a.first < b.first; } +}; + // Lower an array composite literal. Expression* @@ -12557,6 +12567,7 @@ std::vector<unsigned long>* indexes = new std::vector<unsigned long>; indexes->reserve(this->vals_->size()); + bool indexes_out_of_order = false; Expression_list* vals = new Expression_list(); vals->reserve(this->vals_->size()); unsigned long index = 0; @@ -12627,6 +12638,9 @@ return Expression::make_error(location); } + if (!indexes->empty() && index < indexes->back()) + indexes_out_of_order = true; + indexes->push_back(index); } @@ -12641,6 +12655,34 @@ indexes = NULL; } + if (indexes_out_of_order) + { + typedef std::vector<std::pair<unsigned long, Expression*> > V; + + V v; + v.reserve(indexes->size()); + std::vector<unsigned long>::const_iterator pi = indexes->begin(); + for (Expression_list::const_iterator pe = vals->begin(); + pe != vals->end(); + ++pe, ++pi) + v.push_back(std::make_pair(*pi, *pe)); + + std::sort(v.begin(), v.end(), Index_value_compare()); + + delete indexes; + delete vals; + indexes = new std::vector<unsigned long>(); + indexes->reserve(v.size()); + vals = new Expression_list(); + vals->reserve(v.size()); + + for (V::const_iterator p = v.begin(); p != v.end(); ++p) + { + indexes->push_back(p->first); + vals->push_back(p->second); + } + } + return this->make_array(type, indexes, vals); } @@ -12661,7 +12703,9 @@ size_t size; if (vals == NULL) size = 0; - else if (indexes == NULL) + else if (indexes != NULL) + size = indexes->back() + 1; + else { size = vals->size(); Integer_type* it = Type::lookup_integer_type("int")->integer_type(); @@ -12672,11 +12716,6 @@ return Expression::make_error(location); } } - else - { - size = *std::max_element(indexes->begin(), indexes->end()); - ++size; - } mpz_t vlen; mpz_init_set_ui(vlen, size); @@ -12704,8 +12743,7 @@ } else { - unsigned long max = *std::max_element(indexes->begin(), - indexes->end()); + unsigned long max = indexes->back(); if (max >= val) { error_at(location,