More test cases, more cases where the Go frontend needs to create a
temporary in the case of interface conversion.  This is for map index
expressions and map composite literals.  Also only flatten call
expressions once; they tend to appear in the tree multiple times.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian
diff -r 9753943fcd89 go/expressions.cc
--- a/go/expressions.cc Fri Dec 19 07:36:12 2014 -0800
+++ b/go/expressions.cc Fri Dec 19 14:17:00 2014 -0800
@@ -8786,6 +8786,10 @@
   if (this->classification() == EXPRESSION_ERROR)
     return this;
 
+  if (this->is_flattened_)
+    return this;
+  this->is_flattened_ = true;
+
   // Add temporary variables for all arguments that require type
   // conversion.
   Function_type* fntype = this->get_function_type();
@@ -10590,21 +10594,31 @@
 // recomputation.
 
 Expression*
-Map_index_expression::do_flatten(Gogo*, Named_object*,
+Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
                                 Statement_inserter* inserter)
 {
+  Location loc = this->location();
   Map_type* mt = this->get_map_type();
-  if (this->index_->type() != mt->key_type())
-    this->index_ = Expression::make_cast(mt->key_type(), this->index_,
-                                         this->location());
+  if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL))
+    {
+      if (this->index_->type()->interface_type() != NULL
+         && !this->index_->is_variable())
+       {
+         Temporary_statement* temp =
+           Statement::make_temporary(NULL, this->index_, loc);
+         inserter->insert(temp);
+         this->index_ = Expression::make_temporary_reference(temp, loc);
+       }
+      this->index_ = Expression::convert_for_assignment(gogo, mt->key_type(),
+                                                       this->index_, loc);
+    }
 
   if (!this->index_->is_variable())
     {
       Temporary_statement* temp = Statement::make_temporary(NULL, this->index_,
-                                                            this->location());
+                                                            loc);
       inserter->insert(temp);
-      this->index_ = Expression::make_temporary_reference(temp,
-                                                          this->location());
+      this->index_ = Expression::make_temporary_reference(temp, loc);
     }
 
   if (this->value_pointer_ == NULL)
@@ -10612,11 +10626,9 @@
   if (!this->value_pointer_->is_variable())
     {
       Temporary_statement* temp =
-          Statement::make_temporary(NULL, this->value_pointer_,
-                                    this->location());
+       Statement::make_temporary(NULL, this->value_pointer_, loc);
       inserter->insert(temp);
-      this->value_pointer_ =
-          Expression::make_temporary_reference(temp, this->location());
+      this->value_pointer_ = Expression::make_temporary_reference(temp, loc);
     }
 
   return this;
@@ -12540,12 +12552,26 @@
            ++pv, ++i)
         {
           Expression_list* key_value_pair = new Expression_list();
-          Expression* key =
-              Expression::convert_for_assignment(gogo, key_type, *pv, loc);
+          Expression* key = *pv;
+         if (key->type()->interface_type() != NULL && !key->is_variable())
+           {
+             Temporary_statement* temp =
+               Statement::make_temporary(NULL, key, loc);
+             inserter->insert(temp);
+             key = Expression::make_temporary_reference(temp, loc);
+           }
+         key = Expression::convert_for_assignment(gogo, key_type, key, loc);
 
           ++pv;
-          Expression* val =
-              Expression::convert_for_assignment(gogo, val_type, *pv, loc);
+          Expression* val = *pv;
+         if (val->type()->interface_type() != NULL && !val->is_variable())
+           {
+             Temporary_statement* temp =
+               Statement::make_temporary(NULL, val, loc);
+             inserter->insert(temp);
+             val = Expression::make_temporary_reference(temp, loc);
+           }
+         val = Expression::convert_for_assignment(gogo, val_type, val, loc);
 
           key_value_pair->push_back(key);
           key_value_pair->push_back(val);
diff -r 9753943fcd89 go/expressions.h
--- a/go/expressions.h  Fri Dec 19 07:36:12 2014 -0800
+++ b/go/expressions.h  Fri Dec 19 14:17:00 2014 -0800
@@ -1632,7 +1632,8 @@
       fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL),
       call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
       varargs_are_lowered_(false), types_are_determined_(false),
-      is_deferred_(false), issued_error_(false), is_multi_value_arg_(false)
+      is_deferred_(false), issued_error_(false), is_multi_value_arg_(false),
+      is_flattened_(false)
   { }
 
   // The function to call.
@@ -1817,6 +1818,8 @@
   bool issued_error_;
   // True if this call is used as an argument that returns multiple results.
   bool is_multi_value_arg_;
+  // True if this expression has already been flattened.
+  bool is_flattened_;
 };
 
 // An expression which represents a pointer to a function.

Reply via email to