diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-11-04 23:03:37 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-11-04 23:03:37 +0000 |
commit | 95ac3b7ad0b595c58cb56e9106f93e56a43282e6 (patch) | |
tree | 44cbefd0fecf973f2127b8b276de9ef5e912f6ab | |
parent | cf9e9959d1a5e8c7ddb506f68017b4f9c9292b94 (diff) | |
download | gcc-95ac3b7ad0b595c58cb56e9106f93e56a43282e6.zip gcc-95ac3b7ad0b595c58cb56e9106f93e56a43282e6.tar.gz gcc-95ac3b7ad0b595c58cb56e9106f93e56a43282e6.tar.bz2 |
Fix select { case v, ok := <-c: }.
From-SVN: r180992
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 24 | ||||
-rw-r--r-- | gcc/testsuite/go.test/test/closedchan.go | 29 |
2 files changed, 49 insertions, 4 deletions
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index abc629e..156977d 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -4559,10 +4559,26 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function, loc); Statement* s = Statement::make_tuple_receive_assignment(val, closed, ref, true, loc); + // We have to put S in STATEMENTS_, because that is where the // variables are declared. + go_assert(this->statements_ != NULL); - this->statements_->add_statement_at_front(s); + + // Skip the variable declaration statements themselves. + size_t skip = 1; + if (this->var_ != NULL) + skip = 2; + + // Verify that we are only skipping variable declarations. + size_t i = 0; + for (Block::iterator p = this->statements_->begin(); + i < skip && p != this->statements_->end(); + ++p, ++i) + go_assert((*p)->variable_declaration_statement() != NULL); + + this->statements_->insert_statement_before(skip, s); + // We have to lower STATEMENTS_ again, to lower the tuple // receive assignment we just added. gogo->lower_block(function, this->statements_); @@ -4655,7 +4671,8 @@ Select_clauses::Select_clause::dump_clause( { ast_dump_context->dump_expression(this->channel_); ast_dump_context->ostream() << " <- " ; - ast_dump_context->dump_expression(this->val_); + if (this->val_ != NULL) + ast_dump_context->dump_expression(this->val_); } else { @@ -4667,8 +4684,7 @@ Select_clauses::Select_clause::dump_clause( ast_dump_context->ostream() << " , " ; ast_dump_context->dump_expression(this->closed_); } - if (this->closedvar_ != NULL || - this->var_ != NULL) + if (this->closedvar_ != NULL || this->var_ != NULL) ast_dump_context->ostream() << " := " ; ast_dump_context->ostream() << " <- " ; diff --git a/gcc/testsuite/go.test/test/closedchan.go b/gcc/testsuite/go.test/test/closedchan.go index 95314b3..c2bbec5 100644 --- a/gcc/testsuite/go.test/test/closedchan.go +++ b/gcc/testsuite/go.test/test/closedchan.go @@ -11,6 +11,10 @@ package main +import "os" + +var failed bool + type Chan interface { Send(int) Nbsend(int) bool @@ -225,19 +229,23 @@ func test1(c Chan) { // recv a close signal (a zero value) if x := c.Recv(); x != 0 { println("test1: recv on closed:", x, c.Impl()) + failed = true } if x, ok := c.Recv2(); x != 0 || ok { println("test1: recv2 on closed:", x, ok, c.Impl()) + failed = true } // should work with select: received a value without blocking, so selected == true. x, selected := c.Nbrecv() if x != 0 || !selected { println("test1: recv on closed nb:", x, selected, c.Impl()) + failed = true } x, ok, selected := c.Nbrecv2() if x != 0 || ok || !selected { println("test1: recv2 on closed nb:", x, ok, selected, c.Impl()) + failed = true } } @@ -247,12 +255,14 @@ func test1(c Chan) { // the value should have been discarded. if x := c.Recv(); x != 0 { println("test1: recv on closed got non-zero after send on closed:", x, c.Impl()) + failed = true } // similarly Send. shouldPanic(func() { c.Send(2) }) if x := c.Recv(); x != 0 { println("test1: recv on closed got non-zero after send on closed:", x, c.Impl()) + failed = true } } @@ -260,6 +270,7 @@ func testasync1(c Chan) { // should be able to get the last value via Recv if x := c.Recv(); x != 1 { println("testasync1: Recv did not get 1:", x, c.Impl()) + failed = true } test1(c) @@ -269,6 +280,7 @@ func testasync2(c Chan) { // should be able to get the last value via Recv2 if x, ok := c.Recv2(); x != 1 || !ok { println("testasync1: Recv did not get 1, true:", x, ok, c.Impl()) + failed = true } test1(c) @@ -278,6 +290,7 @@ func testasync3(c Chan) { // should be able to get the last value via Nbrecv if x, selected := c.Nbrecv(); x != 1 || !selected { println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl()) + failed = true } test1(c) @@ -287,6 +300,7 @@ func testasync4(c Chan) { // should be able to get the last value via Nbrecv2 if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected { println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl()) + failed = true } test1(c) } @@ -327,4 +341,19 @@ func main() { testclosed(mk(closedasync())) } } + + var ch chan int + shouldPanic(func() { + close(ch) + }) + + ch = make(chan int) + close(ch) + shouldPanic(func() { + close(ch) + }) + + if failed { + os.Exit(1) + } } |