summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/parse.cc')
-rw-r--r--gcc/go/gofrontend/parse.cc49
1 files changed, 36 insertions, 13 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 9d112850fee..6e56f835699 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -213,7 +213,7 @@ Parse::qualified_ident(std::string* pname, Named_object** ppackage)
if (name == "_")
{
error_at(this->location(), "invalid use of %<_%>");
- name = "blank";
+ name = Gogo::erroneous_name();
}
if (package->name() == this->gogo_->package_name())
@@ -744,6 +744,8 @@ Parse::signature(Typed_identifier* receiver, Location location)
return NULL;
Parse::Names names;
+ if (receiver != NULL)
+ names[receiver->name()] = receiver;
if (params != NULL)
this->check_signature_names(params, &names);
if (results != NULL)
@@ -1940,12 +1942,9 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
{
if (this->gogo_->in_global_scope())
return this->create_dummy_global(type, init, location);
- else if (type == NULL)
- this->gogo_->add_statement(Statement::make_statement(init, true));
else
{
- // With both a type and an initializer, create a dummy
- // variable so that we will check whether the
+ // Create a dummy variable so that we will check whether the
// initializer can be assigned to the type.
Variable* var = new Variable(type, init, false, false, false,
location);
@@ -2693,15 +2692,17 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
this->advance_token();
return Expression::make_composite_literal(type, depth, false, NULL,
- location);
+ false, location);
}
bool has_keys = false;
+ bool all_are_names = true;
Expression_list* vals = new Expression_list;
while (true)
{
Expression* val;
bool is_type_omitted = false;
+ bool is_name = false;
const Token* token = this->peek_token();
@@ -2722,6 +2723,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
val = this->id_to_expression(gogo->pack_hidden_name(identifier,
is_exported),
location);
+ is_name = true;
}
else
{
@@ -2747,6 +2749,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
if (has_keys)
vals->push_back(NULL);
+ is_name = false;
}
else
{
@@ -2793,6 +2796,9 @@ Parse::composite_lit(Type* type, int depth, Location location)
vals->push_back(val);
+ if (!is_name)
+ all_are_names = false;
+
if (token->is_op(OPERATOR_COMMA))
{
if (this->advance_token()->is_op(OPERATOR_RCURLY))
@@ -2833,7 +2839,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
}
return Expression::make_composite_literal(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// FunctionLit = "func" Signature Block .
@@ -3107,7 +3113,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
if (token->identifier() == "_")
{
error_at(this->location(), "invalid use of %<_%>");
- name = this->gogo_->pack_hidden_name("blank", false);
+ name = Gogo::erroneous_name();
}
this->advance_token();
return Expression::make_selector(left, name, location);
@@ -3146,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
}
// Index = "[" Expression "]" .
-// Slice = "[" Expression ":" [ Expression ] "]" .
+// Slice = "[" Expression ":" [ Expression ] [ ":" Expression ] "]" .
Expression*
Parse::index(Expression* expr)
@@ -3172,14 +3178,31 @@ Parse::index(Expression* expr)
// We use nil to indicate a missing high expression.
if (this->advance_token()->is_op(OPERATOR_RSQUARE))
end = Expression::make_nil(this->location());
+ else if (this->peek_token()->is_op(OPERATOR_COLON))
+ {
+ error_at(this->location(), "middle index required in 3-index slice");
+ end = Expression::make_error(this->location());
+ }
else
end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
}
+
+ Expression* cap = NULL;
+ if (this->peek_token()->is_op(OPERATOR_COLON))
+ {
+ if (this->advance_token()->is_op(OPERATOR_RSQUARE))
+ {
+ error_at(this->location(), "final index required in 3-index slice");
+ cap = Expression::make_error(this->location());
+ }
+ else
+ cap = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
+ }
if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
error_at(this->location(), "missing %<]%>");
else
this->advance_token();
- return Expression::make_index(expr, start, end, location);
+ return Expression::make_index(expr, start, end, cap, location);
}
// Call = "(" [ ArgumentList [ "," ] ] ")" .
@@ -4932,7 +4955,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
- recv_var = "blank";
+ recv_var = Gogo::erroneous_name();
}
*is_send = false;
*varname = gogo->pack_hidden_name(recv_var, is_rv_exported);
@@ -4968,7 +4991,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
- recv_var = "blank";
+ recv_var = Gogo::erroneous_name();
}
*is_send = false;
if (recv_var != "_")
@@ -5505,7 +5528,7 @@ Parse::package_clause()
if (name == "_")
{
error_at(this->location(), "invalid package name _");
- name = "blank";
+ name = Gogo::erroneous_name();
}
this->advance_token();
}