Commit 7bacbe5c by Ian Lance Taylor

compiler: expand arguments with multiple results for built-in functions.

Fixed https://code.google.com/p/go/issues/detail?id=5796. Official fixedbug will be added with change to gc.

From-SVN: r202239
parent 13ed1c03
...@@ -9138,35 +9138,27 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, ...@@ -9138,35 +9138,27 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
// Because do_type will return an error type and thus prevent future // Because do_type will return an error type and thus prevent future
// errors, check for that case now to ensure that the error gets // errors, check for that case now to ensure that the error gets
// reported. // reported.
if (this->get_function_type() == NULL) Function_type* fntype = this->get_function_type();
if (fntype == NULL)
{ {
if (!this->fn_->type()->is_error()) if (!this->fn_->type()->is_error())
this->report_error(_("expected function")); this->report_error(_("expected function"));
return Expression::make_error(loc); 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 // Handle an argument which is a call to a function which returns
// multiple results. // multiple results.
if (this->args_ != NULL if (this->args_ != NULL
&& this->args_->size() == 1 && this->args_->size() == 1
&& this->args_->front()->call_expression() != NULL && this->args_->front()->call_expression() != NULL)
&& this->fn_->type()->function_type() != NULL)
{ {
Function_type* fntype = this->fn_->type()->function_type();
size_t rc = this->args_->front()->call_expression()->result_count(); size_t rc = this->args_->front()->call_expression()->result_count();
if (rc > 1 if (rc > 1
&& fntype->parameters() != NULL && ((fntype->parameters() != NULL
&& (fntype->parameters()->size() == rc && (fntype->parameters()->size() == rc
|| (fntype->is_varargs() || (fntype->is_varargs()
&& fntype->parameters()->size() - 1 <= rc))) && fntype->parameters()->size() - 1 <= rc)))
|| fntype->is_builtin()))
{ {
Call_expression* call = this->args_->front()->call_expression(); Call_expression* call = this->args_->front()->call_expression();
Expression_list* args = new Expression_list; Expression_list* args = new Expression_list;
...@@ -9180,6 +9172,11 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, ...@@ -9180,6 +9172,11 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
} }
} }
// 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 // If this call returns multiple results, create a temporary
// variable for each result. // variable for each result.
size_t rc = this->result_count(); size_t rc = this->result_count();
...@@ -9188,8 +9185,7 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, ...@@ -9188,8 +9185,7 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
std::vector<Temporary_statement*>* temps = std::vector<Temporary_statement*>* temps =
new std::vector<Temporary_statement*>; new std::vector<Temporary_statement*>;
temps->reserve(rc); temps->reserve(rc);
const Typed_identifier_list* results = const Typed_identifier_list* results = fntype->results();
this->fn_->type()->function_type()->results();
for (Typed_identifier_list::const_iterator p = results->begin(); for (Typed_identifier_list::const_iterator p = results->begin();
p != results->end(); p != results->end();
++p) ++p)
...@@ -9204,10 +9200,8 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, ...@@ -9204,10 +9200,8 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
// Handle a call to a varargs function by packaging up the extra // Handle a call to a varargs function by packaging up the extra
// parameters. // parameters.
if (this->fn_->type()->function_type() != NULL if (fntype->is_varargs())
&& this->fn_->type()->function_type()->is_varargs())
{ {
Function_type* fntype = this->fn_->type()->function_type();
const Typed_identifier_list* parameters = fntype->parameters(); const Typed_identifier_list* parameters = fntype->parameters();
go_assert(parameters != NULL && !parameters->empty()); go_assert(parameters != NULL && !parameters->empty());
Type* varargs_type = parameters->back().type(); Type* varargs_type = parameters->back().type();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment