This patch from Chris Manghane fixes passing a function that returns
multiple results to a builtin function, as in append(F()) if F returns
two values.  That should work since append can take two arguments.  This
patch actually makes it work.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline and 4.8 branch.

Ian

diff -r f711f44d1105 go/expressions.cc
--- a/go/expressions.cc	Tue Sep 03 14:50:27 2013 -0700
+++ b/go/expressions.cc	Tue Sep 03 21:29:03 2013 -0700
@@ -9138,35 +9138,27 @@
   // Because do_type will return an error type and thus prevent future
   // errors, check for that case now to ensure that the error gets
   // reported.
-  if (this->get_function_type() == NULL)
+  Function_type* fntype = this->get_function_type();
+  if (fntype == NULL)
     {
       if (!this->fn_->type()->is_error())
 	this->report_error(_("expected function"));
       return Expression::make_error(loc);
     }
 
-  // Recognize a call to a builtin function.
-  Func_expression* fne = this->fn_->func_expression();
-  if (fne != NULL
-      && fne->named_object()->is_function_declaration()
-      && fne->named_object()->func_declaration_value()->type()->is_builtin())
-    return new Builtin_call_expression(gogo, this->fn_, this->args_,
-				       this->is_varargs_, loc);
-
   // Handle an argument which is a call to a function which returns
   // multiple results.
   if (this->args_ != NULL
       && this->args_->size() == 1
-      && this->args_->front()->call_expression() != NULL
-      && this->fn_->type()->function_type() != NULL)
-    {
-      Function_type* fntype = this->fn_->type()->function_type();
+      && this->args_->front()->call_expression() != NULL)
+    {
       size_t rc = this->args_->front()->call_expression()->result_count();
       if (rc > 1
-	  && fntype->parameters() != NULL
-	  && (fntype->parameters()->size() == rc
-	      || (fntype->is_varargs()
-		  && fntype->parameters()->size() - 1 <= rc)))
+	  && ((fntype->parameters() != NULL
+               && (fntype->parameters()->size() == rc
+                   || (fntype->is_varargs()
+                       && fntype->parameters()->size() - 1 <= rc)))
+              || fntype->is_builtin()))
 	{
 	  Call_expression* call = this->args_->front()->call_expression();
 	  Expression_list* args = new Expression_list;
@@ -9180,6 +9172,11 @@
 	}
     }
 
+  // Recognize a call to a builtin function.
+  if (fntype->is_builtin())
+    return new Builtin_call_expression(gogo, this->fn_, this->args_,
+				       this->is_varargs_, loc);
+
   // If this call returns multiple results, create a temporary
   // variable for each result.
   size_t rc = this->result_count();
@@ -9188,8 +9185,7 @@
       std::vector<Temporary_statement*>* temps =
 	new std::vector<Temporary_statement*>;
       temps->reserve(rc);
-      const Typed_identifier_list* results =
-	this->fn_->type()->function_type()->results();
+      const Typed_identifier_list* results = fntype->results();
       for (Typed_identifier_list::const_iterator p = results->begin();
 	   p != results->end();
 	   ++p)
@@ -9204,10 +9200,8 @@
 
   // Handle a call to a varargs function by packaging up the extra
   // parameters.
-  if (this->fn_->type()->function_type() != NULL
-      && this->fn_->type()->function_type()->is_varargs())
-    {
-      Function_type* fntype = this->fn_->type()->function_type();
+  if (fntype->is_varargs())
+    {
       const Typed_identifier_list* parameters = fntype->parameters();
       go_assert(parameters != NULL && !parameters->empty());
       Type* varargs_type = parameters->back().type();

Reply via email to