@@ -6174,7 +6174,7 @@
Expression* fn,
Expression_list* args,
source_location location)
- : Call_expression(fn, args, location),
+ : Call_expression(fn, args, false, location),
gogo_(gogo), code_(BUILTIN_INVALID)
{
Func_expression* fnexp = this->fn()->func_expression();
@@ -7772,8 +7772,10 @@
bool issued_error = false;
if (pa != old_args->end()
&& pa + 1 == old_args->end()
- && this->is_compatible_varargs_argument(function, *pa, varargs_type,
- &issued_error))
+ && (this->is_varargs_
+ || this->is_compatible_varargs_argument(function, *pa,
+ varargs_type,
+ &issued_error)))
new_args->push_back(*pa);
else if (pa == old_args->end())
push_empty_arg = true;
@@ -8350,10 +8352,10 @@
// Make a call expression.
Call_expression*
-Expression::make_call(Expression* fn, Expression_list* args,
+Expression::make_call(Expression* fn, Expression_list* args, bool is_varargs,
source_location location)
{
- return new Call_expression(fn, args, location);
+ return new Call_expression(fn, args, is_varargs, location);
}
// A single result from a call which returns multiple results.
@@ -9727,7 +9729,9 @@
}
}
- Call_expression* call = Expression::make_call(bm, args, location);
+ Call_expression* call = Expression::make_call(bm, args,
+ method_type->is_varargs(),
+ location);
size_t count = call->result_count();
Statement* s;
@@ -179,7 +179,8 @@
// Make a call expression.
static Call_expression*
- make_call(Expression* func, Expression_list* params, source_location);
+ make_call(Expression* func, Expression_list* args, bool is_varargs,
+ source_location);
// Make a reference to a specific result of a call expression which
// returns a tuple.
@@ -1157,10 +1158,10 @@
class Call_expression : public Expression
{
public:
- Call_expression(Expression* fn, Expression_list* args,
+ Call_expression(Expression* fn, Expression_list* args, bool is_varargs,
source_location location)
: Expression(EXPRESSION_CALL, location),
- fn_(fn), args_(args), type_(NULL), tree_(NULL),
+ fn_(fn), args_(args), type_(NULL), tree_(NULL), is_varargs_(is_varargs),
is_value_discarded_(false), varargs_are_lowered_(false),
is_deferred_(false)
{ }
@@ -1230,7 +1231,7 @@
do_copy()
{
return Expression::make_call(this->fn_->copy(), this->args_->copy(),
- this->location());
+ this->is_varargs_, this->location());
}
bool
@@ -1277,6 +1278,8 @@
Type* type_;
// The tree for the call, used for a call which returns a tuple.
tree tree_;
+ // True if the last argument is a varargs argument (f(a...)).
+ bool is_varargs_;
// True if the value is being discarded.
bool is_value_discarded_;
// True if varargs have already been lowered.
@@ -2074,7 +2074,7 @@
}
args->push_back(this->can_recover_arg(location));
- Expression* call = Expression::make_call(fn, args, location);
+ Expression* call = Expression::make_call(fn, args, false, location);
Statement* s;
if (orig_fntype->results() == NULL || orig_fntype->results()->empty())
@@ -2195,13 +2195,13 @@
Expression_list *args = new Expression_list();
args->push_back(zexpr);
- Expression* call = Expression::make_call(fn, args, location);
+ Expression* call = Expression::make_call(fn, args, false, location);
args = new Expression_list();
args->push_back(call);
fn = Expression::make_func_reference(can_recover, NULL, location);
- return Expression::make_call(fn, args, location);
+ return Expression::make_call(fn, args, false, location);
}
// Build thunks for functions which call recover. We build a new
@@ -2698,18 +2698,25 @@
return Expression::make_index(expr, start, end, location);
}
-// Call = "(" [ ExpressionList [ "," ] ] ")" .
+// Call = "(" [ ArgumentList [ "," ] ] ")" .
+// ArgumentList = ExpressionList [ "..." ] .
Expression*
Parse::call(Expression* func)
{
gcc_assert(this->peek_token()->is_op(OPERATOR_LPAREN));
Expression_list* args = NULL;
+ bool is_varargs = false;
const Token* token = this->advance_token();
if (!token->is_op(OPERATOR_RPAREN))
{
args = this->expression_list(NULL, false);
token = this->peek_token();
+ if (token->is_op(OPERATOR_ELLIPSIS))
+ {
+ is_varargs = true;
+ token = this->advance_token();
+ }
}
if (token->is_op(OPERATOR_COMMA))
token = this->advance_token();
@@ -2719,7 +2726,7 @@
this->advance_token();
if (func->is_error_expression())
return func;
- return Expression::make_call(func, args, func->location());
+ return Expression::make_call(func, args, is_varargs, func->location());
}
// Return an expression for a single unqualified identifier.
@@ -934,7 +934,7 @@
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
ref = Expression::make_temporary_reference(val_temp, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, loc);
+ Expression* call = Expression::make_call(func, params, false, loc);
ref = Expression::make_temporary_reference(present_temp, loc);
Statement* s = Statement::make_assignment(ref, call, loc);
@@ -1069,7 +1069,7 @@
ref = Expression::make_temporary_reference(val_temp, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
params->push_back(this->should_set_);
- Expression* call = Expression::make_call(func, params, loc);
+ Expression* call = Expression::make_call(func, params, false, loc);
Statement* s = Statement::make_statement(call);
b->add_statement(s);
@@ -1192,7 +1192,7 @@
params->push_back(this->channel_);
Expression* ref = Expression::make_temporary_reference(val_temp, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, loc);
+ Expression* call = Expression::make_call(func, params, false, loc);
ref = Expression::make_temporary_reference(success_temp, loc);
Statement* s = Statement::make_assignment(ref, call, loc);
b->add_statement(s);
@@ -1363,7 +1363,7 @@
Expression* func = Expression::make_func_reference(fn, NULL, loc);
Expression_list* params = new Expression_list();
params->push_back(this->expr_);
- return Expression::make_call(func, params, loc);
+ return Expression::make_call(func, params, false, loc);
}
// Lower a conversion to a non-empty interface type or a pointer type.
@@ -1396,7 +1396,7 @@
Expression_list* params = new Expression_list();
params->push_back(Expression::make_type_descriptor(this->type_, loc));
params->push_back(this->expr_);
- return Expression::make_call(func, params, loc);
+ return Expression::make_call(func, params, false, loc);
}
// Lower a conversion to a non-interface non-pointer type.
@@ -1438,7 +1438,7 @@
params->push_back(this->expr_);
Expression* ref = Expression::make_temporary_reference(val_temp, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, loc);
+ Expression* call = Expression::make_call(func, params, false, loc);
Statement* s = Statement::make_assignment(this->ok_, call, loc);
b->add_statement(s);
@@ -1886,7 +1886,7 @@
location);
Expression_list* params = new Expression_list();
params->push_back(constructor);
- Call_expression* call = Expression::make_call(func, params, location);
+ Call_expression* call = Expression::make_call(func, params, false, location);
// Build the simple go or defer statement.
Statement* s;
@@ -2080,7 +2080,7 @@
Expression* fn = Expression::make_func_reference(set_defer_retaddr,
NULL, location);
- Expression* call = Expression::make_call(fn, args, location);
+ Expression* call = Expression::make_call(fn, args, false, location);
// This is a hack to prevent the middle-end from deleting the
// label.
@@ -2163,7 +2163,8 @@
call_params->push_back(param);
}
- Expression* call = Expression::make_call(func_to_call, call_params, location);
+ Expression* call = Expression::make_call(func_to_call, call_params, false,
+ location);
// We need to lower in case this is a builtin function.
call = call->lower(gogo, function, -1);
if (may_call_recover)
@@ -3621,7 +3622,7 @@
Expression* ref =
Expression::make_temporary_reference(descriptor_temp, loc);
params->push_back(ref);
- cond = Expression::make_call(func, params, loc);
+ cond = Expression::make_call(func, params, false, loc);
}
Unnamed_label* dest;
@@ -3834,7 +3835,7 @@
else
ref = Expression::make_var_reference(this->var_, loc);
params->push_back(ref);
- Expression* call = Expression::make_call(func, params, loc);
+ Expression* call = Expression::make_call(func, params, false, loc);
Expression* lhs = Expression::make_temporary_reference(descriptor_temp,
loc);
Statement* s = Statement::make_assignment(lhs, call, loc);
@@ -4616,7 +4617,7 @@
Expression* func = Expression::make_func_reference(no, NULL, loc);
Expression_list* params = new Expression_list();
params->push_back(arg);
- return Expression::make_call(func, params, loc);
+ return Expression::make_call(func, params, false, loc);
}
// Lower a for range over an array or slice.
@@ -4830,7 +4831,7 @@
Expression_list* params = new Expression_list();
params->push_back(this->make_range_ref(range_object, range_temp, loc));
params->push_back(Expression::make_temporary_reference(index_temp, loc));
- Call_expression* call = Expression::make_call(func, params, loc);
+ Call_expression* call = Expression::make_call(func, params, false, loc);
if (value_temp == NULL)
{
@@ -4949,7 +4950,7 @@
params->push_back(this->make_range_ref(range_object, range_temp, loc));
Expression* ref = Expression::make_temporary_reference(hiter, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- Expression* call = Expression::make_call(func, params, loc);
+ Expression* call = Expression::make_call(func, params, false, loc);
init->add_statement(Statement::make_statement(call));
*pinit = init;
@@ -5006,7 +5007,7 @@
ref = Expression::make_temporary_reference(value_temp, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
}
- call = Expression::make_call(func, params, loc);
+ call = Expression::make_call(func, params, false, loc);
iter_init->add_statement(Statement::make_statement(call));
*piter_init = iter_init;
@@ -5033,7 +5034,7 @@
params = new Expression_list();
ref = Expression::make_temporary_reference(hiter, loc);
params->push_back(Expression::make_unary(OPERATOR_AND, ref, loc));
- call = Expression::make_call(func, params, loc);
+ call = Expression::make_call(func, params, false, loc);
post->add_statement(Statement::make_statement(call));
*ppost = post;
@@ -7296,7 +7296,8 @@
{
stub = gogo->start_function(name, stub_type, false,
fntype->location());
- Type::build_one_stub_method(gogo, m, buf, stub_params, location);
+ Type::build_one_stub_method(gogo, m, buf, stub_params,
+ fntype->is_varargs(), location);
gogo->finish_function(fntype->location());
}
@@ -7312,6 +7313,7 @@
Type::build_one_stub_method(Gogo* gogo, Method* method,
const char* receiver_name,
const Typed_identifier_list* params,
+ bool is_varargs,
source_location location)
{
Named_object* receiver_object = gogo->lookup(receiver_name, NULL);
@@ -7342,7 +7344,8 @@
Expression* func = method->bind_method(expr, location);
gcc_assert(func != NULL);
- Call_expression* call = Expression::make_call(func, arguments, location);
+ Call_expression* call = Expression::make_call(func, arguments, is_varargs,
+ location);
size_t count = call->result_count();
if (count == 0)
gogo->add_statement(Statement::make_statement(call));
@@ -1042,7 +1042,8 @@
static void
build_one_stub_method(Gogo*, Method*, const char* receiver_name,
- const Typed_identifier_list*, source_location);
+ const Typed_identifier_list*, bool is_varargs,
+ source_location);
static Expression*
apply_field_indexes(Expression*, const Method::Field_indexes*,