compiler: Correct test for whether go/defer arg is parenthesized.

From-SVN: r194240
This commit is contained in:
Ian Lance Taylor 2012-12-06 04:11:54 +00:00
parent 4d901dd735
commit cb0a70cac9
2 changed files with 87 additions and 46 deletions

View File

@ -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);
Expression* ret = this->operand(may_be_sink, &operand_is_parenthesized);
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)

View File

@ -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);