aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-10-16 17:17:16 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-10-16 17:17:16 +0000
commit01e4aecea8435f75dfb69c3b5fee1c309a9715b0 (patch)
tree10738cbff22a4b15a8c518f73ad342c74d67753b
parentd13fc1ed98037f25d3f1af9718e28ef8b22f1ac5 (diff)
downloadgcc-01e4aecea8435f75dfb69c3b5fee1c309a9715b0.zip
gcc-01e4aecea8435f75dfb69c3b5fee1c309a9715b0.tar.gz
gcc-01e4aecea8435f75dfb69c3b5fee1c309a9715b0.tar.bz2
compiler: Parse receiver as a single parameter.
Fixes issue 8288. From-SVN: r216340
-rw-r--r--gcc/go/gofrontend/parse.cc119
-rw-r--r--gcc/go/gofrontend/parse.h2
2 files changed, 28 insertions, 93 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index d77f462..b24de60 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -974,7 +974,8 @@ Parse::parameter_list(bool* is_varargs)
}
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))
{
if (this->advance_token()->is_op(OPERATOR_RPAREN))
@@ -984,7 +985,8 @@ Parse::parameter_list(bool* is_varargs)
error_at(this->location(), "%<...%> must be last parameter");
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)
{
@@ -1005,7 +1007,8 @@ void
Parse::parameter_decl(bool parameters_have_names,
Typed_identifier_list* til,
bool* is_varargs,
- bool* mix_error)
+ bool* mix_error,
+ bool* saw_error)
{
if (!parameters_have_names)
{
@@ -1047,6 +1050,8 @@ Parse::parameter_decl(bool parameters_have_names,
}
if (!type->is_error_type())
til->push_back(Typed_identifier("", type, location));
+ else
+ *saw_error = true;
}
else
{
@@ -1063,9 +1068,15 @@ Parse::parameter_decl(bool parameters_have_names,
else
{
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)
- error_at(this->location(), "%<...%> only permits one name");
+ {
+ error_at(this->location(), "%<...%> only permits one name");
+ *saw_error = true;
+ }
else
*is_varargs = true;
this->advance_token();
@@ -2310,103 +2321,27 @@ Parse::function_decl(bool saw_nointerface)
}
}
-// Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" .
-// BaseTypeName = identifier .
+// Receiver = Parameters .
Typed_identifier*
Parse::receiver()
{
- go_assert(this->peek_token()->is_op(OPERATOR_LPAREN));
-
- std::string name;
- const Token* token = this->advance_token();
- Location location = token->location();
- 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())
+ Location location = this->location();
+ Typed_identifier_list* til;
+ if (!this->parameters(&til, NULL))
+ return NULL;
+ else if (til == NULL || til->empty())
{
- error_at(this->location(), "expected receiver name or type");
- 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();
+ error_at(location, "method has no receiver");
return NULL;
}
-
- 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
+ else if (til->size() > 1)
{
- if (this->peek_token()->is_op(OPERATOR_COMMA))
- 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();
+ error_at(location, "method has multiple receivers");
return NULL;
}
-
- return new Typed_identifier(name, type, location);
+ else
+ return &til->front();
}
// Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index 3a7bbd5..86698a1 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -179,7 +179,7 @@ class Parse
Function_type* signature(Typed_identifier*, Location);
bool parameters(Typed_identifier_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**);
Location block();
Type* interface_type();