aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2012-12-06 04:11:54 +0000
committerIan Lance Taylor <iant@google.com>2012-12-06 04:11:54 +0000
commit299edef44ef8f0d804d9e33310f489b77264cdf0 (patch)
tree8f69bc11f0b091bc74c2bd1b72af32d81af764d5 /gcc/go
parentb161fd8ef4918e7ee7a1dce5d313359046d81ad5 (diff)
compiler: Correct test for whether go/defer arg is parenthesized.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@194240 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/parse.cc124
-rw-r--r--gcc/go/gofrontend/parse.h9
2 files changed, 87 insertions, 46 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 28737554d91..8c00fa31da4 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -141,7 +141,7 @@ Parse::expression_list(Expression* first, bool may_be_sink,
while (true)
{
ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink,
- may_be_composite_lit, NULL));
+ may_be_composite_lit, NULL, NULL));
const Token* token = this->peek_token();
if (!token->is_op(OPERATOR_COMMA))
@@ -394,7 +394,7 @@ Parse::array_type(bool may_use_ellipsis)
else
{
if (!token->is_op(OPERATOR_ELLIPSIS))
- length = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ length = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
else if (may_use_ellipsis)
{
// An ellipsis is used in composite literals to represent a
@@ -2137,7 +2137,7 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
bool is_type_switch = false;
Expression* expr = this->expression(PRECEDENCE_NORMAL, false,
may_be_composite_lit,
- &is_type_switch);
+ &is_type_switch, NULL);
if (is_type_switch)
{
p_type_switch->found = true;
@@ -2404,8 +2404,11 @@ Parse::receiver()
// If MAY_BE_SINK is true, this operand may be "_".
+// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
+// if the entire expression is in parentheses.
+
Expression*
-Parse::operand(bool may_be_sink)
+Parse::operand(bool may_be_sink, bool* is_parenthesized)
{
const Token* token = this->peek_token();
Expression* ret;
@@ -2581,11 +2584,14 @@ Parse::operand(bool may_be_sink)
if (token->is_op(OPERATOR_LPAREN))
{
this->advance_token();
- ret = this->expression(PRECEDENCE_NORMAL, may_be_sink, true, NULL);
+ ret = this->expression(PRECEDENCE_NORMAL, may_be_sink, true, NULL,
+ NULL);
if (!this->peek_token()->is_op(OPERATOR_RPAREN))
error_at(this->location(), "missing %<)%>");
else
this->advance_token();
+ if (is_parenthesized != NULL)
+ *is_parenthesized = true;
return ret;
}
else if (token->is_op(OPERATOR_LSQUARE))
@@ -2708,11 +2714,12 @@ Parse::composite_lit(Type* type, int depth, Location location)
this->unget_token(Token::make_identifier_token(identifier,
is_exported,
location));
- val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ val = this->expression(PRECEDENCE_NORMAL, false, true, NULL,
+ NULL);
}
}
else if (!token->is_op(OPERATOR_LCURLY))
- val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ val = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
else
{
// This must be a composite literal inside another composite
@@ -2758,7 +2765,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
vals->push_back(val);
if (!token->is_op(OPERATOR_LCURLY))
- val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ val = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
else
{
// This must be a composite literal inside another
@@ -2931,19 +2938,25 @@ Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").
+// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
+// if the entire expression is in parentheses.
+
Expression*
Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
- bool* is_type_switch)
+ bool* is_type_switch, bool* is_parenthesized)
{
Location start_loc = this->location();
- bool is_parenthesized = this->peek_token()->is_op(OPERATOR_LPAREN);
+ bool operand_is_parenthesized = false;
+ bool whole_is_parenthesized = false;
+
+ Expression* ret = this->operand(may_be_sink, &operand_is_parenthesized);
- Expression* ret = this->operand(may_be_sink);
+ whole_is_parenthesized = operand_is_parenthesized;
// An unknown name followed by a curly brace must be a composite
// literal, and the unknown name must be a type.
if (may_be_composite_lit
- && !is_parenthesized
+ && !operand_is_parenthesized
&& ret->unknown_expression() != NULL
&& this->peek_token()->is_op(OPERATOR_LCURLY))
{
@@ -2959,6 +2972,7 @@ Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
{
if (this->peek_token()->is_op(OPERATOR_LCURLY))
{
+ whole_is_parenthesized = false;
if (!may_be_composite_lit)
{
Type* t = ret->type();
@@ -2968,17 +2982,18 @@ Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
_("parentheses required around this composite literal "
"to avoid parsing ambiguity"));
}
- else if (is_parenthesized)
+ else if (operand_is_parenthesized)
error_at(start_loc,
"cannot parenthesize type in composite literal");
ret = this->composite_lit(ret->type(), 0, ret->location());
}
else if (this->peek_token()->is_op(OPERATOR_LPAREN))
{
+ whole_is_parenthesized = false;
Location loc = this->location();
this->advance_token();
Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true,
- NULL);
+ NULL, NULL);
if (this->peek_token()->is_op(OPERATOR_COMMA))
this->advance_token();
if (this->peek_token()->is_op(OPERATOR_ELLIPSIS))
@@ -3014,19 +3029,29 @@ Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
{
const Token* token = this->peek_token();
if (token->is_op(OPERATOR_LPAREN))
- ret = this->call(this->verify_not_sink(ret));
+ {
+ whole_is_parenthesized = false;
+ ret = this->call(this->verify_not_sink(ret));
+ }
else if (token->is_op(OPERATOR_DOT))
{
+ whole_is_parenthesized = false;
ret = this->selector(this->verify_not_sink(ret), is_type_switch);
if (is_type_switch != NULL && *is_type_switch)
break;
}
else if (token->is_op(OPERATOR_LSQUARE))
- ret = this->index(this->verify_not_sink(ret));
+ {
+ whole_is_parenthesized = false;
+ ret = this->index(this->verify_not_sink(ret));
+ }
else
break;
}
+ if (whole_is_parenthesized && is_parenthesized != NULL)
+ *is_parenthesized = true;
+
return ret;
}
@@ -3108,7 +3133,7 @@ Parse::index(Expression* expr)
Expression* start;
if (!this->peek_token()->is_op(OPERATOR_COLON))
- start = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ start = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
else
{
mpz_t zero;
@@ -3124,7 +3149,7 @@ Parse::index(Expression* expr)
if (this->advance_token()->is_op(OPERATOR_RSQUARE))
end = Expression::make_nil(this->location());
else
- end = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
}
if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
error_at(this->location(), "missing %<]%>");
@@ -3233,12 +3258,16 @@ Parse::id_to_expression(const std::string& name, Location location)
// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").
+// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
+// if the entire expression is in parentheses.
+
Expression*
Parse::expression(Precedence precedence, bool may_be_sink,
- bool may_be_composite_lit, bool* is_type_switch)
+ bool may_be_composite_lit, bool* is_type_switch,
+ bool *is_parenthesized)
{
Expression* left = this->unary_expr(may_be_sink, may_be_composite_lit,
- is_type_switch);
+ is_type_switch, is_parenthesized);
while (true)
{
@@ -3295,6 +3324,9 @@ Parse::expression(Precedence precedence, bool may_be_sink,
return left;
}
+ if (is_parenthesized != NULL)
+ *is_parenthesized = false;
+
Operator op = token->op();
Location binop_location = token->location();
@@ -3310,7 +3342,7 @@ Parse::expression(Precedence precedence, bool may_be_sink,
left = this->verify_not_sink(left);
Expression* right = this->expression(right_precedence, false,
may_be_composite_lit,
- NULL);
+ NULL, NULL);
left = Expression::make_binary(op, left, right, binop_location);
}
}
@@ -3376,9 +3408,12 @@ Parse::expression_may_start_here()
// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").
+// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
+// if the entire expression is in parentheses.
+
Expression*
Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
- bool* is_type_switch)
+ bool* is_type_switch, bool* is_parenthesized)
{
const Token* token = this->peek_token();
@@ -3395,7 +3430,7 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
if (this->advance_token()->is_keyword(KEYWORD_CHAN))
{
Expression* expr = this->primary_expr(false, may_be_composite_lit,
- NULL);
+ NULL, NULL);
if (expr->is_error_expression())
return expr;
else if (!expr->is_type_expression())
@@ -3448,7 +3483,8 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
Operator op = token->op();
this->advance_token();
- Expression* expr = this->unary_expr(false, may_be_composite_lit, NULL);
+ Expression* expr = this->unary_expr(false, may_be_composite_lit, NULL,
+ NULL);
if (expr->is_error_expression())
;
else if (op == OPERATOR_MULT && expr->is_type_expression())
@@ -3464,7 +3500,7 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
}
else
return this->primary_expr(may_be_sink, may_be_composite_lit,
- is_type_switch);
+ is_type_switch, is_parenthesized);
}
// This is called for the obscure case of
@@ -3747,7 +3783,8 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
may_be_composite_lit,
(p_type_switch == NULL
? NULL
- : &p_type_switch->found));
+ : &p_type_switch->found),
+ NULL);
if (p_type_switch != NULL && p_type_switch->found)
{
p_type_switch->name.clear();
@@ -3857,7 +3894,8 @@ Parse::send_stmt(Expression* channel)
go_assert(this->peek_token()->is_op(OPERATOR_CHANOP));
Location loc = this->location();
this->advance_token();
- Expression* val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ Expression* val = this->expression(PRECEDENCE_NORMAL, false, true, NULL,
+ NULL);
Statement* s = Statement::make_send_statement(channel, val, loc);
this->gogo_->add_statement(s);
}
@@ -4092,11 +4130,12 @@ Parse::go_or_defer_stat()
bool is_go = this->peek_token()->is_keyword(KEYWORD_GO);
Location stat_location = this->location();
- const Token* token = this->advance_token();
+ this->advance_token();
Location expr_location = this->location();
- bool is_parenthesized = token->is_op(OPERATOR_LPAREN);
- Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ bool is_parenthesized = false;
+ Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, NULL,
+ &is_parenthesized);
Call_expression* call_expr = expr->call_expression();
if (is_parenthesized || call_expr == NULL)
{
@@ -4198,7 +4237,7 @@ Parse::if_stat()
cond = Expression::make_error(this->location());
}
if (cond == NULL)
- cond = this->expression(PRECEDENCE_NORMAL, false, false, NULL);
+ cond = this->expression(PRECEDENCE_NORMAL, false, false, NULL, NULL);
}
this->gogo_->start_block(this->location());
@@ -4329,7 +4368,7 @@ Parse::switch_stat(Label* label)
if (switch_val == NULL && !type_switch.found)
{
switch_val = this->expression(PRECEDENCE_NORMAL, false, false,
- &type_switch.found);
+ &type_switch.found, NULL);
if (type_switch.found)
{
type_switch.name.clear();
@@ -4351,7 +4390,7 @@ Parse::switch_stat(Label* label)
error_at(token_loc, "invalid variable name");
this->advance_token();
this->expression(PRECEDENCE_NORMAL, false, false,
- &type_switch.found);
+ &type_switch.found, NULL);
if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
this->advance_token();
if (!this->peek_token()->is_op(OPERATOR_LCURLY))
@@ -4854,7 +4893,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
// case rv := <-c:
this->advance_token();
Expression* e = this->expression(PRECEDENCE_NORMAL, false, false,
- NULL);
+ NULL, NULL);
Receive_expression* re = e->receive_expression();
if (re == NULL)
{
@@ -4889,7 +4928,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
// case rv, rc := <-c:
this->advance_token();
Expression* e = this->expression(PRECEDENCE_NORMAL, false,
- false, NULL);
+ false, NULL, NULL);
Receive_expression* re = e->receive_expression();
if (re == NULL)
{
@@ -4937,13 +4976,13 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
Expression* e;
if (saw_comma || !this->peek_token()->is_op(OPERATOR_CHANOP))
- e = this->expression(PRECEDENCE_NORMAL, true, true, NULL);
+ e = this->expression(PRECEDENCE_NORMAL, true, true, NULL, NULL);
else
{
// case <-c:
*is_send = false;
this->advance_token();
- *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
// The next token should be ':'. If it is '<-', then we have
// case <-c <- v:
@@ -4963,7 +5002,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
}
*is_send = false;
this->advance_token();
- *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
if (saw_comma)
{
// case v, e = <-c:
@@ -4995,7 +5034,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
*is_send = true;
*channel = this->verify_not_sink(e);
this->advance_token();
- *val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ *val = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
return true;
}
@@ -5142,7 +5181,7 @@ Parse::for_clause(Expression** cond, Block** post)
return;
}
else
- *cond = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ *cond = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
error_at(this->location(), "expected semicolon");
else
@@ -5176,7 +5215,8 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
error_at(this->location(), "too many variables for range clause");
this->advance_token();
- Expression* expr = this->expression(PRECEDENCE_NORMAL, false, false, NULL);
+ Expression* expr = this->expression(PRECEDENCE_NORMAL, false, false, NULL,
+ NULL);
p_range_clause->range = expr;
bool any_new = false;
@@ -5223,7 +5263,7 @@ Parse::range_clause_expr(const Expression_list* vals,
this->advance_token();
p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false,
- NULL);
+ NULL, NULL);
p_range_clause->index = vals->front();
if (vals->size() == 1)
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index 9743bb52ebf..99e0eeebc24 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -216,7 +216,7 @@ class Parse
Range_clause*, Type_switch*);
void function_decl(bool saw_nointerface);
Typed_identifier* receiver();
- Expression* operand(bool may_be_sink);
+ Expression* operand(bool may_be_sink, bool *is_parenthesized);
Expression* enclosing_var_reference(Named_object*, Named_object*,
Location);
Expression* composite_lit(Type*, int depth, Location);
@@ -224,15 +224,16 @@ class Parse
Expression* create_closure(Named_object* function, Enclosing_vars*,
Location);
Expression* primary_expr(bool may_be_sink, bool may_be_composite_lit,
- bool* is_type_switch);
+ bool* is_type_switch, bool* is_parenthesized);
Expression* selector(Expression*, bool* is_type_switch);
Expression* index(Expression*);
Expression* call(Expression*);
Expression* expression(Precedence, bool may_be_sink,
- bool may_be_composite_lit, bool* is_type_switch);
+ bool may_be_composite_lit, bool* is_type_switch,
+ bool *is_parenthesized);
bool expression_may_start_here();
Expression* unary_expr(bool may_be_sink, bool may_be_composite_lit,
- bool* is_type_switch);
+ bool* is_type_switch, bool* is_parenthesized);
Type* reassociate_chan_direction(Channel_type*, Location);
Expression* qualified_expr(Expression*, Location);
Expression* id_to_expression(const std::string&, Location);