compiler: correct parse of parenthesized select case
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 5 Feb 2018 01:40:51 +0000 (01:40 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 5 Feb 2018 01:40:51 +0000 (01:40 +0000)
    We used to mishandle `select { case (<-c): }` and friends.

    The test case for this is https://golang.org/cl/91657.

    Fixes golang/go#20923

    Reviewed-on: https://go-review.googlesource.com/91695

From-SVN: r257374

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/parse.cc

index 9cf3b14..257ca95 100644 (file)
@@ -1,4 +1,4 @@
-9057b8f71e6078f140938fe60be9aaa7d59a3a2b
+2f7ac42a3f83b78d97912ce1e86296b2af4f52b7
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 8162abf..86d3510 100644 (file)
@@ -5160,7 +5160,18 @@ 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, NULL);
+    {
+      e = this->expression(PRECEDENCE_NORMAL, true, true, NULL, NULL);
+      if (e->receive_expression() != NULL)
+       {
+         *is_send = false;
+         *channel = e->receive_expression()->channel();
+         // This is 'case (<-c):'.  We now expect ':'.  If we see
+         // '<-', then we have case (<-c)<-v:
+         if (!this->peek_token()->is_op(OPERATOR_CHANOP))
+           return true;
+       }
+    }
   else
     {
       // case <-c:
@@ -5189,14 +5200,17 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
 
   if (this->peek_token()->is_op(OPERATOR_EQ))
     {
-      if (!this->advance_token()->is_op(OPERATOR_CHANOP))
+      *is_send = false;
+      this->advance_token();
+      Location recvloc = this->location();
+      Expression* recvexpr = this->expression(PRECEDENCE_NORMAL, false,
+                                             true, NULL, NULL);
+      if (recvexpr->receive_expression() == NULL)
        {
-         go_error_at(this->location(), "missing %<<-%>");
+         go_error_at(recvloc, "missing %<<-%>");
          return false;
        }
-      *is_send = false;
-      this->advance_token();
-      *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
+      *channel = recvexpr->receive_expression()->channel();
       if (saw_comma)
        {
          // case v, e = <-c: