This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: Fix parse of for with possible composite literal


This patch to the Go frontend fixes a bad parse.  For code like
    for first := true; first; first = false {
the frontend would erroneously assume that "false {" could be the start
of a composite literal.  It can't be, because composite literals in a
for statement must be parenthesized.  Bootstrapped and ran Go testsuite
on x86_64-unknown-linux-gnu.  Committed to mainline and gccgo branch.

Ian

diff -r eb21fb5e5da4 go/parse.cc
--- a/go/parse.cc	Fri May 04 07:55:30 2012 -0700
+++ b/go/parse.cc	Fri May 04 12:28:35 2012 -0700
@@ -126,18 +126,22 @@
 
 // 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 "_".
 
 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();
   if (first != NULL)
     ret->push_back(first);
   while (true)
     {
-      ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink, true,
-				      NULL));
+      ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink,
+				      may_be_composite_lit, NULL));
 
       const Token* token = this->peek_token();
       if (!token->is_op(OPERATOR_COMMA))
@@ -1425,7 +1429,7 @@
   else
     {
       this->advance_token();
-      expr_list = this->expression_list(NULL, false);
+      expr_list = this->expression_list(NULL, false, true);
       *last_type = type;
       if (*last_expr_list != NULL)
 	delete *last_expr_list;
@@ -1575,13 +1579,13 @@
       if (this->peek_token()->is_op(OPERATOR_EQ))
 	{
 	  this->advance_token();
-	  init = this->expression_list(NULL, false);
+	  init = this->expression_list(NULL, false, true);
 	}
     }
   else
     {
       this->advance_token();
-      init = this->expression_list(NULL, false);
+      init = this->expression_list(NULL, false, true);
     }
 
   this->init_vars(&til, type, init, false, location);
@@ -1988,6 +1992,9 @@
 // In order to support both "a, b := 1, 0" and "a, b = 1, 0" we accept
 // 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
 // RangeClause.
 
@@ -1997,6 +2004,7 @@
 void
 Parse::simple_var_decl_or_assignment(const std::string& name,
 				     Location location,
+				     bool may_be_composite_lit,
 				     Range_clause* p_range_clause,
 				     Type_switch* p_type_switch)
 {
@@ -2053,14 +2061,15 @@
 	    exprs->push_back(this->id_to_expression(p->name(),
 						    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();
 	       p != more_exprs->end();
 	       ++p)
 	    exprs->push_back(*p);
 	  delete more_exprs;
 
-	  this->tuple_assignment(exprs, p_range_clause);
+	  this->tuple_assignment(exprs, may_be_composite_lit, p_range_clause);
 	  return;
 	}
     }
@@ -2076,11 +2085,12 @@
 
   Expression_list* init;
   if (p_type_switch == NULL)
-    init = this->expression_list(NULL, false);
+    init = this->expression_list(NULL, false, may_be_composite_lit);
   else
     {
       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);
       if (is_type_switch)
 	{
@@ -2099,7 +2109,7 @@
       else
 	{
 	  this->advance_token();
-	  init = this->expression_list(expr, false);
+	  init = this->expression_list(expr, false, may_be_composite_lit);
 	}
     }
 
@@ -3065,7 +3075,7 @@
   const Token* token = this->advance_token();
   if (!token->is_op(OPERATOR_RPAREN))
     {
-      args = this->expression_list(NULL, false);
+      args = this->expression_list(NULL, false, true);
       token = this->peek_token();
       if (token->is_op(OPERATOR_ELLIPSIS))
 	{
@@ -3578,6 +3588,7 @@
 	{
 	  identifier = this->gogo_->pack_hidden_name(identifier, is_exported);
 	  this->simple_var_decl_or_assignment(identifier, location,
+					      may_be_composite_lit,
 					      p_range_clause,
 					      (token->is_op(OPERATOR_COLONEQ)
 					       ? p_type_switch
@@ -3613,7 +3624,7 @@
     this->inc_dec_stat(this->verify_not_sink(exp));
   else if (token->is_op(OPERATOR_COMMA)
 	   || 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)
 	   || token->is_op(OPERATOR_MINUSEQ)
 	   || token->is_op(OPERATOR_OREQ)
@@ -3625,7 +3636,8 @@
 	   || token->is_op(OPERATOR_RSHIFTEQ)
 	   || token->is_op(OPERATOR_ANDEQ)
 	   || 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)
     return this->verify_not_sink(exp);
   else
@@ -3731,11 +3743,15 @@
 
 // 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
 // RangeClause.
 
 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;
   if (!this->peek_token()->is_op(OPERATOR_COMMA))
@@ -3746,20 +3762,24 @@
   else
     {
       this->advance_token();
-      vars = this->expression_list(expr, true);
-    }
-
-  this->tuple_assignment(vars, p_range_clause);
+      vars = this->expression_list(expr, true, may_be_composite_lit);
+    }
+
+  this->tuple_assignment(vars, may_be_composite_lit, p_range_clause);
 }
 
 // An assignment statement.  LHS is the list of expressions which
 // 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
 // RangeClause.
 
 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();
   if (!token->is_op(OPERATOR_EQ)
@@ -3791,7 +3811,8 @@
       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.
   if (lhs == NULL || vals == NULL)
@@ -3960,7 +3981,7 @@
   this->advance_token();
   Expression_list* vals = NULL;
   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));
 
   if (vals == NULL
@@ -4321,7 +4342,7 @@
   if (token->is_keyword(KEYWORD_CASE))
     {
       this->advance_token();
-      return this->expression_list(NULL, false);
+      return this->expression_list(NULL, false, true);
     }
   else if (token->is_keyword(KEYWORD_DEFAULT))
     {
diff -r eb21fb5e5da4 go/parse.h
--- a/go/parse.h	Fri May 04 07:55:30 2012 -0700
+++ b/go/parse.h	Fri May 04 12:28:35 2012 -0700
@@ -162,7 +162,8 @@
 
   // Parser nonterminals.
   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**);
   Type* type();
   bool type_may_start_here();
@@ -207,6 +208,7 @@
 			 bool is_coloneq, bool type_from_init, bool* is_new);
   Named_object* create_dummy_global(Type*, Expression*, Location);
   void simple_var_decl_or_assignment(const std::string&, Location,
+				     bool may_be_composite_lit,
 				     Range_clause*, Type_switch*);
   void function_decl();
   Typed_identifier* receiver();
@@ -239,8 +241,9 @@
   void expression_stat(Expression*);
   void send_stmt(Expression*);
   void inc_dec_stat(Expression*);
-  void assignment(Expression*, Range_clause*);
-  void tuple_assignment(Expression_list*, Range_clause*);
+  void assignment(Expression*, bool may_be_composite_lit, Range_clause*);
+  void tuple_assignment(Expression_list*, bool may_be_composite_lit,
+			Range_clause*);
   void send();
   void go_or_defer_stat();
   void return_stat();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]