Commit 01e4aece by Ian Lance Taylor

compiler: Parse receiver as a single parameter.

Fixes issue 8288.

From-SVN: r216340
parent d13fc1ed
...@@ -974,7 +974,8 @@ Parse::parameter_list(bool* is_varargs) ...@@ -974,7 +974,8 @@ Parse::parameter_list(bool* is_varargs)
} }
bool mix_error = false; bool mix_error = false;
this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error); this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error,
&saw_error);
while (this->peek_token()->is_op(OPERATOR_COMMA)) while (this->peek_token()->is_op(OPERATOR_COMMA))
{ {
if (this->advance_token()->is_op(OPERATOR_RPAREN)) if (this->advance_token()->is_op(OPERATOR_RPAREN))
...@@ -984,7 +985,8 @@ Parse::parameter_list(bool* is_varargs) ...@@ -984,7 +985,8 @@ Parse::parameter_list(bool* is_varargs)
error_at(this->location(), "%<...%> must be last parameter"); error_at(this->location(), "%<...%> must be last parameter");
saw_error = true; saw_error = true;
} }
this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error); this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error,
&saw_error);
} }
if (mix_error) if (mix_error)
{ {
...@@ -1005,7 +1007,8 @@ void ...@@ -1005,7 +1007,8 @@ void
Parse::parameter_decl(bool parameters_have_names, Parse::parameter_decl(bool parameters_have_names,
Typed_identifier_list* til, Typed_identifier_list* til,
bool* is_varargs, bool* is_varargs,
bool* mix_error) bool* mix_error,
bool* saw_error)
{ {
if (!parameters_have_names) if (!parameters_have_names)
{ {
...@@ -1047,6 +1050,8 @@ Parse::parameter_decl(bool parameters_have_names, ...@@ -1047,6 +1050,8 @@ Parse::parameter_decl(bool parameters_have_names,
} }
if (!type->is_error_type()) if (!type->is_error_type())
til->push_back(Typed_identifier("", type, location)); til->push_back(Typed_identifier("", type, location));
else
*saw_error = true;
} }
else else
{ {
...@@ -1063,9 +1068,15 @@ Parse::parameter_decl(bool parameters_have_names, ...@@ -1063,9 +1068,15 @@ Parse::parameter_decl(bool parameters_have_names,
else else
{ {
if (is_varargs == NULL) if (is_varargs == NULL)
error_at(this->location(), "invalid use of %<...%>"); {
error_at(this->location(), "invalid use of %<...%>");
*saw_error = true;
}
else if (new_count > orig_count + 1) else if (new_count > orig_count + 1)
error_at(this->location(), "%<...%> only permits one name"); {
error_at(this->location(), "%<...%> only permits one name");
*saw_error = true;
}
else else
*is_varargs = true; *is_varargs = true;
this->advance_token(); this->advance_token();
...@@ -2310,103 +2321,27 @@ Parse::function_decl(bool saw_nointerface) ...@@ -2310,103 +2321,27 @@ Parse::function_decl(bool saw_nointerface)
} }
} }
// Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . // Receiver = Parameters .
// BaseTypeName = identifier .
Typed_identifier* Typed_identifier*
Parse::receiver() Parse::receiver()
{ {
go_assert(this->peek_token()->is_op(OPERATOR_LPAREN)); Location location = this->location();
Typed_identifier_list* til;
std::string name; if (!this->parameters(&til, NULL))
const Token* token = this->advance_token(); return NULL;
Location location = token->location(); else if (til == NULL || til->empty())
if (!token->is_op(OPERATOR_MULT))
{
if (!token->is_identifier())
{
error_at(this->location(), "method has no receiver");
this->gogo_->mark_locals_used();
while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN))
token = this->advance_token();
if (!token->is_eof())
this->advance_token();
return NULL;
}
name = token->identifier();
bool is_exported = token->is_identifier_exported();
token = this->advance_token();
if (!token->is_op(OPERATOR_DOT) && !token->is_op(OPERATOR_RPAREN))
{
// An identifier followed by something other than a dot or a
// right parenthesis must be a receiver name followed by a
// type.
name = this->gogo_->pack_hidden_name(name, is_exported);
}
else
{
// This must be a type name.
this->unget_token(Token::make_identifier_token(name, is_exported,
location));
token = this->peek_token();
name.clear();
}
}
// Here the receiver name is in NAME (it is empty if the receiver is
// unnamed) and TOKEN is the first token in the type.
bool is_pointer = false;
if (token->is_op(OPERATOR_MULT))
{
is_pointer = true;
token = this->advance_token();
}
if (!token->is_identifier())
{ {
error_at(this->location(), "expected receiver name or type"); error_at(location, "method has no receiver");
this->gogo_->mark_locals_used();
int c = token->is_op(OPERATOR_LPAREN) ? 1 : 0;
while (!token->is_eof())
{
token = this->advance_token();
if (token->is_op(OPERATOR_LPAREN))
++c;
else if (token->is_op(OPERATOR_RPAREN))
{
if (c == 0)
break;
--c;
}
}
if (!token->is_eof())
this->advance_token();
return NULL; return NULL;
} }
else if (til->size() > 1)
Type* type = this->type_name(true);
if (is_pointer && !type->is_error_type())
type = Type::make_pointer_type(type);
if (this->peek_token()->is_op(OPERATOR_RPAREN))
this->advance_token();
else
{ {
if (this->peek_token()->is_op(OPERATOR_COMMA)) error_at(location, "method has multiple receivers");
error_at(this->location(), "method has multiple receivers");
else
error_at(this->location(), "expected %<)%>");
this->gogo_->mark_locals_used();
while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN))
token = this->advance_token();
if (!token->is_eof())
this->advance_token();
return NULL; return NULL;
} }
else
return new Typed_identifier(name, type, location); return &til->front();
} }
// Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" . // Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
......
...@@ -179,7 +179,7 @@ class Parse ...@@ -179,7 +179,7 @@ class Parse
Function_type* signature(Typed_identifier*, Location); Function_type* signature(Typed_identifier*, Location);
bool parameters(Typed_identifier_list**, bool* is_varargs); bool parameters(Typed_identifier_list**, bool* is_varargs);
Typed_identifier_list* parameter_list(bool* is_varargs); Typed_identifier_list* parameter_list(bool* is_varargs);
void parameter_decl(bool, Typed_identifier_list*, bool*, bool*); void parameter_decl(bool, Typed_identifier_list*, bool*, bool*, bool*);
bool result(Typed_identifier_list**); bool result(Typed_identifier_list**);
Location block(); Location block();
Type* interface_type(); Type* interface_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