compiler: More cases that need a temporary for interface conversion.
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 19 Dec 2014 16:14:01 +0000 (16:14 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 19 Dec 2014 16:14:01 +0000 (16:14 +0000)
From-SVN: r218952

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/statements.h

index 6f5acc1f92e19c8c68c9c052d3bb444b7fcd6310..5b95b21b587915cc5b9e2ec3ff60f417b755fa79 100644 (file)
@@ -5142,6 +5142,9 @@ Expression*
 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 @@ Expression*
 Builtin_call_expression::do_flatten(Gogo*, Named_object*,
                                     Statement_inserter* inserter)
 {
-  if (this->code_ == BUILTIN_APPEND
-      || this->code_ == BUILTIN_COPY)
+  Location loc = this->location();
+
+  switch (this->code_)
     {
-      Location loc = this->location();
-      Type* at = this->args()->front()->type();
+    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;
 }
 
index c84df3b5a3e0a7b2d37c7db5867db80227aff407..5da04710e39f8102b6b04a58d6008d293c1628ed 100644 (file)
@@ -421,6 +421,28 @@ Temporary_statement::do_check_types(Gogo*)
     }
 }
 
+// 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 @@ Temporary_statement::do_get_backend(Translate_context* context)
     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);
     }
 
index aaad66e7fcab405d524f9df440ab75f9c518ebfa..5634b61f339e4844224d0f57e81d84d424776165 100644 (file)
@@ -550,6 +550,9 @@ class Temporary_statement : public Statement
   void
   do_check_types(Gogo*);
 
+  Statement*
+  do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
+
   Bstatement*
   do_get_backend(Translate_context*);