Commit 780140d3 by Ian Lance Taylor

compiler: Correct parse of for with possible composite literal.

Fixes, e.g., "for first := true; first; first = false {".

From-SVN: r187176
parent ed4639a9
...@@ -126,18 +126,22 @@ Parse::identifier_list(Typed_identifier_list* til) ...@@ -126,18 +126,22 @@ Parse::identifier_list(Typed_identifier_list* til)
// ExpressionList = Expression { "," Expression } . // ExpressionList = Expression { "," Expression } .
// If MAY_BE_COMPOSITE_LIT is true, an expression may be a composite
// literal.
// If MAY_BE_SINK is true, the expressions in the list may be "_". // If MAY_BE_SINK is true, the expressions in the list may be "_".
Expression_list* Expression_list*
Parse::expression_list(Expression* first, bool may_be_sink) Parse::expression_list(Expression* first, bool may_be_sink,
bool may_be_composite_lit)
{ {
Expression_list* ret = new Expression_list(); Expression_list* ret = new Expression_list();
if (first != NULL) if (first != NULL)
ret->push_back(first); ret->push_back(first);
while (true) while (true)
{ {
ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink, true, ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink,
NULL)); may_be_composite_lit, NULL));
const Token* token = this->peek_token(); const Token* token = this->peek_token();
if (!token->is_op(OPERATOR_COMMA)) if (!token->is_op(OPERATOR_COMMA))
...@@ -1425,7 +1429,7 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list) ...@@ -1425,7 +1429,7 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
else else
{ {
this->advance_token(); this->advance_token();
expr_list = this->expression_list(NULL, false); expr_list = this->expression_list(NULL, false, true);
*last_type = type; *last_type = type;
if (*last_expr_list != NULL) if (*last_expr_list != NULL)
delete *last_expr_list; delete *last_expr_list;
...@@ -1575,13 +1579,13 @@ Parse::var_spec(void*) ...@@ -1575,13 +1579,13 @@ Parse::var_spec(void*)
if (this->peek_token()->is_op(OPERATOR_EQ)) if (this->peek_token()->is_op(OPERATOR_EQ))
{ {
this->advance_token(); this->advance_token();
init = this->expression_list(NULL, false); init = this->expression_list(NULL, false, true);
} }
} }
else else
{ {
this->advance_token(); this->advance_token();
init = this->expression_list(NULL, false); init = this->expression_list(NULL, false, true);
} }
this->init_vars(&til, type, init, false, location); this->init_vars(&til, type, init, false, location);
...@@ -1988,6 +1992,9 @@ Parse::create_dummy_global(Type* type, Expression* init, ...@@ -1988,6 +1992,9 @@ Parse::create_dummy_global(Type* type, Expression* init,
// In order to support both "a, b := 1, 0" and "a, b = 1, 0" we accept // In order to support both "a, b := 1, 0" and "a, b = 1, 0" we accept
// tuple assignments here as well. // tuple assignments here as well.
// If MAY_BE_COMPOSITE_LIT is true, the expression on the right hand
// side may be a composite literal.
// If P_RANGE_CLAUSE is not NULL, then this will recognize a // If P_RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause. // RangeClause.
...@@ -1997,6 +2004,7 @@ Parse::create_dummy_global(Type* type, Expression* init, ...@@ -1997,6 +2004,7 @@ Parse::create_dummy_global(Type* type, Expression* init,
void void
Parse::simple_var_decl_or_assignment(const std::string& name, Parse::simple_var_decl_or_assignment(const std::string& name,
Location location, Location location,
bool may_be_composite_lit,
Range_clause* p_range_clause, Range_clause* p_range_clause,
Type_switch* p_type_switch) Type_switch* p_type_switch)
{ {
...@@ -2053,14 +2061,15 @@ Parse::simple_var_decl_or_assignment(const std::string& name, ...@@ -2053,14 +2061,15 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
exprs->push_back(this->id_to_expression(p->name(), exprs->push_back(this->id_to_expression(p->name(),
p->location())); p->location()));
Expression_list* more_exprs = this->expression_list(NULL, true); Expression_list* more_exprs =
this->expression_list(NULL, true, may_be_composite_lit);
for (Expression_list::const_iterator p = more_exprs->begin(); for (Expression_list::const_iterator p = more_exprs->begin();
p != more_exprs->end(); p != more_exprs->end();
++p) ++p)
exprs->push_back(*p); exprs->push_back(*p);
delete more_exprs; delete more_exprs;
this->tuple_assignment(exprs, p_range_clause); this->tuple_assignment(exprs, may_be_composite_lit, p_range_clause);
return; return;
} }
} }
...@@ -2076,11 +2085,12 @@ Parse::simple_var_decl_or_assignment(const std::string& name, ...@@ -2076,11 +2085,12 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
Expression_list* init; Expression_list* init;
if (p_type_switch == NULL) if (p_type_switch == NULL)
init = this->expression_list(NULL, false); init = this->expression_list(NULL, false, may_be_composite_lit);
else else
{ {
bool is_type_switch = false; bool is_type_switch = false;
Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, Expression* expr = this->expression(PRECEDENCE_NORMAL, false,
may_be_composite_lit,
&is_type_switch); &is_type_switch);
if (is_type_switch) if (is_type_switch)
{ {
...@@ -2099,7 +2109,7 @@ Parse::simple_var_decl_or_assignment(const std::string& name, ...@@ -2099,7 +2109,7 @@ Parse::simple_var_decl_or_assignment(const std::string& name,
else else
{ {
this->advance_token(); this->advance_token();
init = this->expression_list(expr, false); init = this->expression_list(expr, false, may_be_composite_lit);
} }
} }
...@@ -3065,7 +3075,7 @@ Parse::call(Expression* func) ...@@ -3065,7 +3075,7 @@ Parse::call(Expression* func)
const Token* token = this->advance_token(); const Token* token = this->advance_token();
if (!token->is_op(OPERATOR_RPAREN)) if (!token->is_op(OPERATOR_RPAREN))
{ {
args = this->expression_list(NULL, false); args = this->expression_list(NULL, false, true);
token = this->peek_token(); token = this->peek_token();
if (token->is_op(OPERATOR_ELLIPSIS)) if (token->is_op(OPERATOR_ELLIPSIS))
{ {
...@@ -3578,6 +3588,7 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp, ...@@ -3578,6 +3588,7 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
{ {
identifier = this->gogo_->pack_hidden_name(identifier, is_exported); identifier = this->gogo_->pack_hidden_name(identifier, is_exported);
this->simple_var_decl_or_assignment(identifier, location, this->simple_var_decl_or_assignment(identifier, location,
may_be_composite_lit,
p_range_clause, p_range_clause,
(token->is_op(OPERATOR_COLONEQ) (token->is_op(OPERATOR_COLONEQ)
? p_type_switch ? p_type_switch
...@@ -3613,7 +3624,7 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp, ...@@ -3613,7 +3624,7 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
this->inc_dec_stat(this->verify_not_sink(exp)); this->inc_dec_stat(this->verify_not_sink(exp));
else if (token->is_op(OPERATOR_COMMA) else if (token->is_op(OPERATOR_COMMA)
|| token->is_op(OPERATOR_EQ)) || token->is_op(OPERATOR_EQ))
this->assignment(exp, p_range_clause); this->assignment(exp, may_be_composite_lit, p_range_clause);
else if (token->is_op(OPERATOR_PLUSEQ) else if (token->is_op(OPERATOR_PLUSEQ)
|| token->is_op(OPERATOR_MINUSEQ) || token->is_op(OPERATOR_MINUSEQ)
|| token->is_op(OPERATOR_OREQ) || token->is_op(OPERATOR_OREQ)
...@@ -3625,7 +3636,8 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp, ...@@ -3625,7 +3636,8 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
|| token->is_op(OPERATOR_RSHIFTEQ) || token->is_op(OPERATOR_RSHIFTEQ)
|| token->is_op(OPERATOR_ANDEQ) || token->is_op(OPERATOR_ANDEQ)
|| token->is_op(OPERATOR_BITCLEAREQ)) || token->is_op(OPERATOR_BITCLEAREQ))
this->assignment(this->verify_not_sink(exp), p_range_clause); this->assignment(this->verify_not_sink(exp), may_be_composite_lit,
p_range_clause);
else if (return_exp != NULL) else if (return_exp != NULL)
return this->verify_not_sink(exp); return this->verify_not_sink(exp);
else else
...@@ -3731,11 +3743,15 @@ Parse::inc_dec_stat(Expression* exp) ...@@ -3731,11 +3743,15 @@ Parse::inc_dec_stat(Expression* exp)
// EXP is an expression that we have already parsed. // EXP is an expression that we have already parsed.
// If MAY_BE_COMPOSITE_LIT is true, an expression on the right hand
// side may be a composite literal.
// If RANGE_CLAUSE is not NULL, then this will recognize a // If RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause. // RangeClause.
void void
Parse::assignment(Expression* expr, Range_clause* p_range_clause) Parse::assignment(Expression* expr, bool may_be_composite_lit,
Range_clause* p_range_clause)
{ {
Expression_list* vars; Expression_list* vars;
if (!this->peek_token()->is_op(OPERATOR_COMMA)) if (!this->peek_token()->is_op(OPERATOR_COMMA))
...@@ -3746,20 +3762,24 @@ Parse::assignment(Expression* expr, Range_clause* p_range_clause) ...@@ -3746,20 +3762,24 @@ Parse::assignment(Expression* expr, Range_clause* p_range_clause)
else else
{ {
this->advance_token(); this->advance_token();
vars = this->expression_list(expr, true); vars = this->expression_list(expr, true, may_be_composite_lit);
} }
this->tuple_assignment(vars, p_range_clause); this->tuple_assignment(vars, may_be_composite_lit, p_range_clause);
} }
// An assignment statement. LHS is the list of expressions which // An assignment statement. LHS is the list of expressions which
// appear on the left hand side. // appear on the left hand side.
// If MAY_BE_COMPOSITE_LIT is true, an expression on the right hand
// side may be a composite literal.
// If RANGE_CLAUSE is not NULL, then this will recognize a // If RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause. // RangeClause.
void void
Parse::tuple_assignment(Expression_list* lhs, Range_clause* p_range_clause) Parse::tuple_assignment(Expression_list* lhs, bool may_be_composite_lit,
Range_clause* p_range_clause)
{ {
const Token* token = this->peek_token(); const Token* token = this->peek_token();
if (!token->is_op(OPERATOR_EQ) if (!token->is_op(OPERATOR_EQ)
...@@ -3791,7 +3811,8 @@ Parse::tuple_assignment(Expression_list* lhs, Range_clause* p_range_clause) ...@@ -3791,7 +3811,8 @@ Parse::tuple_assignment(Expression_list* lhs, Range_clause* p_range_clause)
return; return;
} }
Expression_list* vals = this->expression_list(NULL, false); Expression_list* vals = this->expression_list(NULL, false,
may_be_composite_lit);
// We've parsed everything; check for errors. // We've parsed everything; check for errors.
if (lhs == NULL || vals == NULL) if (lhs == NULL || vals == NULL)
...@@ -3960,7 +3981,7 @@ Parse::return_stat() ...@@ -3960,7 +3981,7 @@ Parse::return_stat()
this->advance_token(); this->advance_token();
Expression_list* vals = NULL; Expression_list* vals = NULL;
if (this->expression_may_start_here()) if (this->expression_may_start_here())
vals = this->expression_list(NULL, false); vals = this->expression_list(NULL, false, true);
this->gogo_->add_statement(Statement::make_return_statement(vals, location)); this->gogo_->add_statement(Statement::make_return_statement(vals, location));
if (vals == NULL if (vals == NULL
...@@ -4321,7 +4342,7 @@ Parse::expr_switch_case(bool* is_default) ...@@ -4321,7 +4342,7 @@ Parse::expr_switch_case(bool* is_default)
if (token->is_keyword(KEYWORD_CASE)) if (token->is_keyword(KEYWORD_CASE))
{ {
this->advance_token(); this->advance_token();
return this->expression_list(NULL, false); return this->expression_list(NULL, false, true);
} }
else if (token->is_keyword(KEYWORD_DEFAULT)) else if (token->is_keyword(KEYWORD_DEFAULT))
{ {
......
...@@ -162,7 +162,8 @@ class Parse ...@@ -162,7 +162,8 @@ class Parse
// Parser nonterminals. // Parser nonterminals.
void identifier_list(Typed_identifier_list*); void identifier_list(Typed_identifier_list*);
Expression_list* expression_list(Expression*, bool may_be_sink); Expression_list* expression_list(Expression*, bool may_be_sink,
bool may_be_composite_lit);
bool qualified_ident(std::string*, Named_object**); bool qualified_ident(std::string*, Named_object**);
Type* type(); Type* type();
bool type_may_start_here(); bool type_may_start_here();
...@@ -207,6 +208,7 @@ class Parse ...@@ -207,6 +208,7 @@ class Parse
bool is_coloneq, bool type_from_init, bool* is_new); bool is_coloneq, bool type_from_init, bool* is_new);
Named_object* create_dummy_global(Type*, Expression*, Location); Named_object* create_dummy_global(Type*, Expression*, Location);
void simple_var_decl_or_assignment(const std::string&, Location, void simple_var_decl_or_assignment(const std::string&, Location,
bool may_be_composite_lit,
Range_clause*, Type_switch*); Range_clause*, Type_switch*);
void function_decl(); void function_decl();
Typed_identifier* receiver(); Typed_identifier* receiver();
...@@ -239,8 +241,9 @@ class Parse ...@@ -239,8 +241,9 @@ class Parse
void expression_stat(Expression*); void expression_stat(Expression*);
void send_stmt(Expression*); void send_stmt(Expression*);
void inc_dec_stat(Expression*); void inc_dec_stat(Expression*);
void assignment(Expression*, Range_clause*); void assignment(Expression*, bool may_be_composite_lit, Range_clause*);
void tuple_assignment(Expression_list*, Range_clause*); void tuple_assignment(Expression_list*, bool may_be_composite_lit,
Range_clause*);
void send(); void send();
void go_or_defer_stat(); void go_or_defer_stat();
void return_stat(); void return_stat();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment