From cb0a70cac9da5235bb5e6978eb6d62e4d2c6ed7d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 6 Dec 2012 04:11:54 +0000 Subject: [PATCH] compiler: Correct test for whether go/defer arg is parenthesized. From-SVN: r194240 --- gcc/go/gofrontend/parse.cc | 124 ++++++++++++++++++++++++------------- gcc/go/gofrontend/parse.h | 9 +-- 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); + 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) 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);