diff mbox

Go patch committed: More temporaries for interface conversion

Message ID CAOyqgcXCs-H1m3thcdZx4a0RJeEWObmN64d+F9KckvJHxgfoLw@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Dec. 19, 2014, 4:14 p.m. UTC
Compiling more Go code revealed a couple more cases that need a
temporary for interface conversion.  The first is passing an interface
value to panic.  The second is when a temporary itself has a type that
forces conversion, which can happen in a return statement.  This patch
adds them.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian
diff mbox

Patch

diff -r bbc7cf8bad07 go/expressions.cc
--- a/go/expressions.cc	Thu Dec 18 20:04:18 2014 -0800
+++ b/go/expressions.cc	Fri Dec 19 07:34:33 2014 -0800
@@ -5142,6 +5142,9 @@ 
 Binary_expression::do_flatten(Gogo* gogo, Named_object*,
                               Statement_inserter* inserter)
 {
+  if (this->classification() == EXPRESSION_ERROR)
+    return this;
+
   Location loc = this->location();
   Temporary_statement* temp;
   if (this->left_->type()->is_string_type()
@@ -6877,30 +6880,53 @@ 
 Builtin_call_expression::do_flatten(Gogo*, Named_object*,
                                     Statement_inserter* inserter)
 {
-  if (this->code_ == BUILTIN_APPEND
-      || this->code_ == BUILTIN_COPY)
-    {
-      Location loc = this->location();
-      Type* at = this->args()->front()->type();
+  Location loc = this->location();
+
+  switch (this->code_)
+    {
+    default:
+      break;
+
+    case BUILTIN_APPEND:
+    case BUILTIN_COPY:
+      {
+	Type* at = this->args()->front()->type();
+	for (Expression_list::iterator pa = this->args()->begin();
+	     pa != this->args()->end();
+	     ++pa)
+	  {
+	    if ((*pa)->is_nil_expression())
+	      {
+		Expression* nil = Expression::make_nil(loc);
+		Expression* zero = Expression::make_integer_ul(0, NULL, loc);
+		*pa = Expression::make_slice_value(at, nil, zero, zero, loc);
+	      }
+	    if (!(*pa)->is_variable())
+	      {
+		Temporary_statement* temp =
+                  Statement::make_temporary(NULL, *pa, loc);
+		inserter->insert(temp);
+		*pa = Expression::make_temporary_reference(temp, loc);
+	      }
+	  }
+      }
+      break;
+
+    case BUILTIN_PANIC:
       for (Expression_list::iterator pa = this->args()->begin();
-           pa != this->args()->end();
-           ++pa)
-        {
-          if ((*pa)->is_nil_expression())
+	   pa != this->args()->end();
+	   ++pa)
+	{
+	  if (!(*pa)->is_variable() && (*pa)->type()->interface_type() != NULL)
 	    {
-	      Expression* nil = Expression::make_nil(loc);
-	      Expression* zero = Expression::make_integer_ul(0, NULL, loc);
-	      *pa = Expression::make_slice_value(at, nil, zero, zero, loc);
+	      Temporary_statement* temp =
+		Statement::make_temporary(NULL, *pa, loc);
+	      inserter->insert(temp);
+	      *pa = Expression::make_temporary_reference(temp, loc);
 	    }
-          if (!(*pa)->is_variable())
-            {
-              Temporary_statement* temp =
-                  Statement::make_temporary(NULL, *pa, loc);
-              inserter->insert(temp);
-              *pa = Expression::make_temporary_reference(temp, loc);
-            }
-        }
-    }
+	}
+    }
+
   return this;
 }
 
diff -r bbc7cf8bad07 go/statements.cc
--- a/go/statements.cc	Thu Dec 18 20:04:18 2014 -0800
+++ b/go/statements.cc	Fri Dec 19 07:34:33 2014 -0800
@@ -421,6 +421,28 @@ 
     }
 }
 
+// Flatten a temporary statement: add another temporary when it might
+// be needed for interface conversion.
+
+Statement*
+Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
+				Statement_inserter* inserter)
+{
+  if (this->type_ != NULL
+      && this->init_ != NULL
+      && !Type::are_identical(this->type_, this->init_->type(), false, NULL)
+      && this->init_->type()->interface_type() != NULL
+      && !this->init_->is_variable())
+    {
+      Temporary_statement *temp =
+	Statement::make_temporary(NULL, this->init_, this->location());
+      inserter->insert(temp);
+      this->init_ = Expression::make_temporary_reference(temp,
+							 this->location());
+    }
+  return this;
+}
+
 // Convert to backend representation.
 
 Bstatement*
@@ -440,9 +462,10 @@ 
     binit = this->init_->get_backend(context);
   else
     {
-      Expression* init = Expression::make_cast(this->type_, this->init_,
-					       this->location());
-      context->gogo()->lower_expression(context->function(), NULL, &init);
+      Expression* init = Expression::convert_for_assignment(context->gogo(),
+							    this->type_,
+							    this->init_,
+							    this->location());
       binit = init->get_backend(context);
     }
 
diff -r bbc7cf8bad07 go/statements.h
--- a/go/statements.h	Thu Dec 18 20:04:18 2014 -0800
+++ b/go/statements.h	Fri Dec 19 07:34:33 2014 -0800
@@ -550,6 +550,9 @@ 
   void
   do_check_types(Gogo*);
 
+  Statement*
+  do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
+
   Bstatement*
   do_get_backend(Translate_context*);