aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-03-24 00:01:44 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-03-24 00:01:44 +0000
commit27a19c584743458ee775ef5e0af5d0e32a465f06 (patch)
tree4cb70d5d25eafaf22a09b592159852d8ae95b17f
parente110e232b6f7bbd3b4315161373f61623204d2b4 (diff)
downloadgcc-27a19c584743458ee775ef5e0af5d0e32a465f06.zip
gcc-27a19c584743458ee775ef5e0af5d0e32a465f06.tar.gz
gcc-27a19c584743458ee775ef5e0af5d0e32a465f06.tar.bz2
Change c <- v from an expression to a statement.
Don't do anything special if we don't use the value of <-c. Fix sending an untyped constant in a select statement. From-SVN: r171371
-rw-r--r--gcc/go/gofrontend/expressions.cc97
-rw-r--r--gcc/go/gofrontend/expressions.h74
-rw-r--r--gcc/go/gofrontend/gogo.cc8
-rw-r--r--gcc/go/gofrontend/parse.cc53
-rw-r--r--gcc/go/gofrontend/parse.h2
-rw-r--r--gcc/go/gofrontend/statements.cc97
-rw-r--r--gcc/go/gofrontend/statements.h44
-rw-r--r--gcc/testsuite/go.test/test/chan/nonblock.go153
-rw-r--r--gcc/testsuite/go.test/test/chan/perm.go65
-rw-r--r--gcc/testsuite/go.test/test/closedchan.go92
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug069.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug196.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug234.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug242.go7
-rw-r--r--gcc/testsuite/go.test/test/named1.go9
15 files changed, 423 insertions, 333 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 8660c75..125715b 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -12357,103 +12357,6 @@ Expression::make_receive(Expression* channel, source_location location)
return new Receive_expression(channel, location);
}
-// Class Send_expression.
-
-// Traversal.
-
-int
-Send_expression::do_traverse(Traverse* traverse)
-{
- if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- return Expression::traverse(&this->val_, traverse);
-}
-
-// Get the type.
-
-Type*
-Send_expression::do_type()
-{
- if (this->is_value_discarded_)
- return Type::make_void_type();
- else
- return Type::lookup_bool_type();
-}
-
-// Set types.
-
-void
-Send_expression::do_determine_type(const Type_context*)
-{
- this->channel_->determine_type_no_context();
-
- Type* type = this->channel_->type();
- Type_context subcontext;
- if (type->channel_type() != NULL)
- subcontext.type = type->channel_type()->element_type();
- this->val_->determine_type(&subcontext);
-}
-
-// Check types.
-
-void
-Send_expression::do_check_types(Gogo*)
-{
- Type* type = this->channel_->type();
- if (type->is_error_type())
- {
- this->set_is_error();
- return;
- }
- Channel_type* channel_type = type->channel_type();
- if (channel_type == NULL)
- {
- error_at(this->location(), "left operand of %<<-%> must be channel");
- this->set_is_error();
- return;
- }
- Type* element_type = channel_type->element_type();
- if (element_type != NULL
- && !Type::are_assignable(element_type, this->val_->type(), NULL))
- {
- this->report_error(_("incompatible types in send"));
- return;
- }
- if (!channel_type->may_send())
- {
- this->report_error(_("invalid send on receive-only channel"));
- return;
- }
-}
-
-// Get a tree for a send expression.
-
-tree
-Send_expression::do_get_tree(Translate_context* context)
-{
- tree channel = this->channel_->get_tree(context);
- tree val = this->val_->get_tree(context);
- if (channel == error_mark_node || val == error_mark_node)
- return error_mark_node;
- Channel_type* channel_type = this->channel_->type()->channel_type();
- val = Expression::convert_for_assignment(context,
- channel_type->element_type(),
- this->val_->type(),
- val,
- this->location());
- return Gogo::send_on_channel(channel, val, this->is_value_discarded_,
- this->for_select_, this->location());
-}
-
-// Make a send expression
-
-Send_expression*
-Expression::make_send(Expression* channel, Expression* val,
- source_location location)
-{
- return new Send_expression(channel, val, location);
-}
-
// An expression which evaluates to a pointer to the type descriptor
// of a type.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 1dc408d..fa240a6 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -36,7 +36,6 @@ class Field_reference_expression;
class Interface_field_reference_expression;
class Type_guard_expression;
class Receive_expression;
-class Send_expression;
class Named_object;
class Export;
class Import;
@@ -89,7 +88,6 @@ class Expression
EXPRESSION_COMPOSITE_LITERAL,
EXPRESSION_HEAP_COMPOSITE,
EXPRESSION_RECEIVE,
- EXPRESSION_SEND,
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_TYPE_INFO,
EXPRESSION_STRUCT_FIELD_OFFSET,
@@ -271,10 +269,6 @@ class Expression
static Receive_expression*
make_receive(Expression* channel, source_location);
- // Make a send expression.
- static Send_expression*
- make_send(Expression* channel, Expression* val, source_location);
-
// Make an expression which evaluates to the type descriptor of a
// type.
static Expression*
@@ -356,8 +350,7 @@ class Expression
// This is called by the parser if the value of this expression is
// being discarded. This issues warnings about computed values
- // being unused, and handles send expressions which act differently
- // depending upon whether the value is used.
+ // being unused.
void
discarding_value()
{ this->do_discarding_value(); }
@@ -1807,7 +1800,7 @@ class Receive_expression : public Expression
public:
Receive_expression(Expression* channel, source_location location)
: Expression(EXPRESSION_RECEIVE, location),
- channel_(channel), is_value_discarded_(false), for_select_(false)
+ channel_(channel), for_select_(false)
{ }
// Return the channel.
@@ -1827,7 +1820,7 @@ class Receive_expression : public Expression
void
do_discarding_value()
- { this->is_value_discarded_ = true; }
+ { }
Type*
do_type();
@@ -1855,67 +1848,6 @@ class Receive_expression : public Expression
private:
// The channel from which we are receiving.
Expression* channel_;
- // Whether the value is being discarded.
- bool is_value_discarded_;
- // Whether this is for a select statement.
- bool for_select_;
-};
-
-// A send expression.
-
-class Send_expression : public Expression
-{
- public:
- Send_expression(Expression* channel, Expression* val,
- source_location location)
- : Expression(EXPRESSION_SEND, location),
- channel_(channel), val_(val), is_value_discarded_(false),
- for_select_(false)
- { }
-
- // Note that this is for a select statement.
- void
- set_for_select()
- { this->for_select_ = true; }
-
- protected:
- int
- do_traverse(Traverse* traverse);
-
- void
- do_discarding_value()
- { this->is_value_discarded_ = true; }
-
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return Expression::make_send(this->channel_->copy(), this->val_->copy(),
- this->location());
- }
-
- bool
- do_must_eval_in_order() const
- { return true; }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The channel on which to send the value.
- Expression* channel_;
- // The value to send.
- Expression* val_;
- // Whether the value is being discarded.
- bool is_value_discarded_;
// Whether this is for a select statement.
bool for_select_;
};
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index f8c143c..f2476d5 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -1926,14 +1926,6 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
{
Expression** pexpr = *p;
- // If the last expression is a send or receive expression, we
- // may be ignoring the value; we don't want to evaluate it
- // early.
- if (p + 1 == find_eval_ordering.end()
- && ((*pexpr)->classification() == Expression::EXPRESSION_SEND
- || (*pexpr)->classification() == Expression::EXPRESSION_RECEIVE))
- break;
-
// The last expression in a thunk will be the call passed to go
// or defer, which we must not evaluate early.
if (is_thunk && p + 1 == find_eval_ordering.end())
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 7c03870..2e59149 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -2944,9 +2944,6 @@ Parse::expression(Precedence precedence, bool may_be_sink,
case OPERATOR_ANDAND:
right_precedence = PRECEDENCE_ANDAND;
break;
- case OPERATOR_CHANOP:
- right_precedence = PRECEDENCE_CHANOP;
- break;
case OPERATOR_EQEQ:
case OPERATOR_NOTEQ:
case OPERATOR_LT:
@@ -2997,10 +2994,7 @@ Parse::expression(Precedence precedence, bool may_be_sink,
Expression* right = this->expression(right_precedence, false,
may_be_composite_lit,
NULL);
- if (op == OPERATOR_CHANOP)
- left = Expression::make_send(left, right, binop_location);
- else
- left = Expression::make_binary(op, left, right, binop_location);
+ left = Expression::make_binary(op, left, right, binop_location);
}
}
@@ -3302,8 +3296,10 @@ Parse::labeled_stmt(const std::string& label_name, source_location location)
this->statement(label);
}
-// SimpleStat =
-// ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
+// SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt |
+// Assignment | ShortVarDecl .
+
+// EmptyStmt was handled in Parse::statement.
// In order to make this work for if and switch statements, if
// RETURN_EXP is true, and we see an ExpressionStat, we return the
@@ -3360,7 +3356,10 @@ Parse::simple_stat(bool may_be_composite_lit, bool return_exp,
return NULL;
}
token = this->peek_token();
- if (token->is_op(OPERATOR_PLUSPLUS) || token->is_op(OPERATOR_MINUSMINUS))
+ if (token->is_op(OPERATOR_CHANOP))
+ this->send_stmt(this->verify_not_sink(exp));
+ else if (token->is_op(OPERATOR_PLUSPLUS)
+ || token->is_op(OPERATOR_MINUSMINUS))
this->inc_dec_stat(this->verify_not_sink(exp));
else if (token->is_op(OPERATOR_COMMA)
|| token->is_op(OPERATOR_EQ))
@@ -3430,6 +3429,20 @@ Parse::expression_stat(Expression* exp)
this->gogo_->add_statement(Statement::make_statement(exp));
}
+// SendStmt = Channel "&lt;-" Expression .
+// Channel = Expression .
+
+void
+Parse::send_stmt(Expression* channel)
+{
+ gcc_assert(this->peek_token()->is_op(OPERATOR_CHANOP));
+ source_location loc = this->location();
+ this->advance_token();
+ Expression* val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ Statement* s = Statement::make_send_statement(channel, val, loc);
+ this->gogo_->add_statement(s);
+}
+
// IncDecStat = Expression ( "++" | "--" ) .
void
@@ -4159,7 +4172,7 @@ Parse::select_stat(const Label* label)
this->gogo_->add_statement(statement);
}
-// CommClause = CommCase [ StatementList ] .
+// CommClause = CommCase ":" { Statement ";" } .
void
Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
@@ -4173,6 +4186,11 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
bool got_case = this->comm_case(&is_send, &channel, &val, &varname,
&is_default);
+ if (this->peek_token()->is_op(OPERATOR_COLON))
+ this->advance_token();
+ else
+ error_at(this->location(), "expected colon");
+
Block* statements = NULL;
Named_object* var = NULL;
if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
@@ -4214,7 +4232,7 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
}
}
-// CommCase = ( "default" | ( "case" ( SendExpr | RecvExpr) ) ) ":" .
+// CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
bool
Parse::comm_case(bool* is_send, Expression** channel, Expression** val,
@@ -4240,18 +4258,9 @@ Parse::comm_case(bool* is_send, Expression** channel, Expression** val,
return false;
}
- if (!this->peek_token()->is_op(OPERATOR_COLON))
- {
- error_at(this->location(), "expected colon");
- return false;
- }
-
- this->advance_token();
-
return true;
}
-// SendExpr = Expression "<-" Expression .
// RecvExpr = [ Expression ( "=" | ":=" ) ] "<-" Expression .
bool
@@ -4291,7 +4300,7 @@ Parse::send_or_recv_expr(bool* is_send, Expression** channel, Expression** val,
}
else
{
- Expression* left = this->expression(PRECEDENCE_CHANOP, true, true, NULL);
+ Expression* left = this->expression(PRECEDENCE_NORMAL, true, true, NULL);
if (this->peek_token()->is_op(OPERATOR_EQ))
{
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index 6f2ac64..04ae324 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -44,7 +44,6 @@ class Parse
PRECEDENCE_NORMAL = 0,
PRECEDENCE_OROR,
PRECEDENCE_ANDAND,
- PRECEDENCE_CHANOP,
PRECEDENCE_RELOP,
PRECEDENCE_ADDOP,
PRECEDENCE_MULOP
@@ -229,6 +228,7 @@ class Parse
void statement_list();
bool statement_list_may_start_here();
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*);
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index c443519..5a4ad06 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -3987,6 +3987,90 @@ Statement::make_type_switch_statement(Named_object* var, Expression* expr,
return new Type_switch_statement(var, expr, location);
}
+// Class Send_statement.
+
+// Traversal.
+
+int
+Send_statement::do_traverse(Traverse* traverse)
+{
+ if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ return this->traverse_expression(traverse, &this->val_);
+}
+
+// Determine types.
+
+void
+Send_statement::do_determine_types()
+{
+ this->channel_->determine_type_no_context();
+ Type* type = this->channel_->type();
+ Type_context context;
+ if (type->channel_type() != NULL)
+ context.type = type->channel_type()->element_type();
+ this->val_->determine_type(&context);
+}
+
+// Check types.
+
+void
+Send_statement::do_check_types(Gogo*)
+{
+ Type* type = this->channel_->type();
+ if (type->is_error_type())
+ {
+ this->set_is_error();
+ return;
+ }
+ Channel_type* channel_type = type->channel_type();
+ if (channel_type == NULL)
+ {
+ error_at(this->location(), "left operand of %<<-%> must be channel");
+ this->set_is_error();
+ return;
+ }
+ Type* element_type = channel_type->element_type();
+ if (!Type::are_assignable(element_type, this->val_->type(), NULL))
+ {
+ this->report_error(_("incompatible types in send"));
+ return;
+ }
+ if (!channel_type->may_send())
+ {
+ this->report_error(_("invalid send on receive-only channel"));
+ return;
+ }
+}
+
+// Get a tree for a send statement.
+
+tree
+Send_statement::do_get_tree(Translate_context* context)
+{
+ tree channel = this->channel_->get_tree(context);
+ tree val = this->val_->get_tree(context);
+ if (channel == error_mark_node || val == error_mark_node)
+ return error_mark_node;
+ Channel_type* channel_type = this->channel_->type()->channel_type();
+ val = Expression::convert_for_assignment(context,
+ channel_type->element_type(),
+ this->val_->type(),
+ val,
+ this->location());
+ return Gogo::send_on_channel(channel, val, true, this->for_select_,
+ this->location());
+}
+
+// Make a send statement.
+
+Send_statement*
+Statement::make_send_statement(Expression* channel, Expression* val,
+ source_location location)
+{
+ return new Send_statement(channel, val, location);
+}
+
// Class Select_clauses::Select_clause.
// Traversal.
@@ -4043,7 +4127,7 @@ Select_clauses::Select_clause::lower(Block* b)
// If this is a send clause, evaluate the value to send before the
// select statement.
Temporary_statement* val_temp = NULL;
- if (this->is_send_)
+ if (this->is_send_ && !this->val_->is_constant())
{
val_temp = Statement::make_temporary(NULL, this->val_, loc);
b->add_statement(val_temp);
@@ -4054,11 +4138,14 @@ Select_clauses::Select_clause::lower(Block* b)
Expression* ref = Expression::make_temporary_reference(channel_temp, loc);
if (this->is_send_)
{
- Expression* ref2 = Expression::make_temporary_reference(val_temp, loc);
- Send_expression* send = Expression::make_send(ref, ref2, loc);
- send->discarding_value();
+ Expression* ref2;
+ if (val_temp == NULL)
+ ref2 = this->val_;
+ else
+ ref2 = Expression::make_temporary_reference(val_temp, loc);
+ Send_statement* send = Statement::make_send_statement(ref, ref2, loc);
send->set_for_select();
- init->add_statement(Statement::make_statement(send));
+ init->add_statement(send);
}
else
{
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index 80cdffe..83d5436 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -23,6 +23,7 @@ class For_statement;
class For_range_statement;
class Switch_statement;
class Type_switch_statement;
+class Send_statement;
class Select_statement;
class Variable;
class Named_object;
@@ -99,6 +100,7 @@ class Statement
STATEMENT_UNNAMED_LABEL,
STATEMENT_IF,
STATEMENT_CONSTANT_SWITCH,
+ STATEMENT_SEND,
STATEMENT_SELECT,
// These statements types are created by the parser, but they
@@ -236,6 +238,10 @@ class Statement
static Type_switch_statement*
make_type_switch_statement(Named_object* var, Expression*, source_location);
+ // Make a send statement.
+ static Send_statement*
+ make_send_statement(Expression* channel, Expression* val, source_location);
+
// Make a select statement.
static Select_statement*
make_select_statement(source_location);
@@ -592,6 +598,44 @@ class Return_statement : public Statement
Expression_list* vals_;
};
+// A send statement.
+
+class Send_statement : public Statement
+{
+ public:
+ Send_statement(Expression* channel, Expression* val,
+ source_location location)
+ : Statement(STATEMENT_SEND, location),
+ channel_(channel), val_(val), for_select_(false)
+ { }
+
+ // Note that this is for a select statement.
+ void
+ set_for_select()
+ { this->for_select_ = true; }
+
+ protected:
+ int
+ do_traverse(Traverse* traverse);
+
+ void
+ do_determine_types();
+
+ void
+ do_check_types(Gogo*);
+
+ tree
+ do_get_tree(Translate_context*);
+
+ private:
+ // The channel on which to send the value.
+ Expression* channel_;
+ // The value to send.
+ Expression* val_;
+ // Whether this is for a select statement.
+ bool for_select_;
+};
+
// Select_clauses holds the clauses of a select statement. This is
// built by the parser.
diff --git a/gcc/testsuite/go.test/test/chan/nonblock.go b/gcc/testsuite/go.test/test/chan/nonblock.go
index 52f04bf..33afb32 100644
--- a/gcc/testsuite/go.test/test/chan/nonblock.go
+++ b/gcc/testsuite/go.test/test/chan/nonblock.go
@@ -76,7 +76,6 @@ func main() {
var i64 int64
var b bool
var s string
- var ok bool
var sync = make(chan bool)
@@ -86,35 +85,45 @@ func main() {
cb := make(chan bool, buffer)
cs := make(chan string, buffer)
- i32, ok = <-c32
- if ok {
+ select {
+ case i32 = <-c32:
panic("blocked i32sender")
+ default:
}
- i64, ok = <-c64
- if ok {
+ select {
+ case i64 = <-c64:
panic("blocked i64sender")
+ default:
}
- b, ok = <-cb
- if ok {
+ select {
+ case b = <-cb:
panic("blocked bsender")
+ default:
}
- s, ok = <-cs
- if ok {
+ select {
+ case s = <-cs:
panic("blocked ssender")
+ default:
}
go i32receiver(c32, sync)
try := 0
- for !(c32 <- 123) {
- try++
- if try > maxTries {
- println("i32receiver buffer=", buffer)
- panic("fail")
+ Send32:
+ for {
+ select {
+ case c32 <- 123:
+ break Send32
+ default:
+ try++
+ if try > maxTries {
+ println("i32receiver buffer=", buffer)
+ panic("fail")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -123,13 +132,19 @@ func main() {
<-sync
}
try = 0
- for i32, ok = <-c32; !ok; i32, ok = <-c32 {
- try++
- if try > maxTries {
- println("i32sender buffer=", buffer)
- panic("fail")
+ Recv32:
+ for {
+ select {
+ case i32 = <-c32:
+ break Recv32
+ default:
+ try++
+ if try > maxTries {
+ println("i32sender buffer=", buffer)
+ panic("fail")
+ }
+ sleep()
}
- sleep()
}
if i32 != 234 {
panic("i32sender value")
@@ -140,12 +155,18 @@ func main() {
go i64receiver(c64, sync)
try = 0
- for !(c64 <- 123456) {
- try++
- if try > maxTries {
- panic("i64receiver")
+ Send64:
+ for {
+ select {
+ case c64 <- 123456:
+ break Send64
+ default:
+ try++
+ if try > maxTries {
+ panic("i64receiver")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -154,12 +175,18 @@ func main() {
<-sync
}
try = 0
- for i64, ok = <-c64; !ok; i64, ok = <-c64 {
- try++
- if try > maxTries {
- panic("i64sender")
+ Recv64:
+ for {
+ select {
+ case i64 = <-c64:
+ break Recv64
+ default:
+ try++
+ if try > maxTries {
+ panic("i64sender")
+ }
+ sleep()
}
- sleep()
}
if i64 != 234567 {
panic("i64sender value")
@@ -170,12 +197,18 @@ func main() {
go breceiver(cb, sync)
try = 0
- for !(cb <- true) {
- try++
- if try > maxTries {
- panic("breceiver")
+ SendBool:
+ for {
+ select {
+ case cb <- true:
+ break SendBool
+ default:
+ try++
+ if try > maxTries {
+ panic("breceiver")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -184,12 +217,18 @@ func main() {
<-sync
}
try = 0
- for b, ok = <-cb; !ok; b, ok = <-cb {
- try++
- if try > maxTries {
- panic("bsender")
+ RecvBool:
+ for {
+ select {
+ case b = <-cb:
+ break RecvBool
+ default:
+ try++
+ if try > maxTries {
+ panic("bsender")
+ }
+ sleep()
}
- sleep()
}
if !b {
panic("bsender value")
@@ -200,12 +239,18 @@ func main() {
go sreceiver(cs, sync)
try = 0
- for !(cs <- "hello") {
- try++
- if try > maxTries {
- panic("sreceiver")
+ SendString:
+ for {
+ select {
+ case cs <- "hello":
+ break SendString
+ default:
+ try++
+ if try > maxTries {
+ panic("sreceiver")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -214,12 +259,18 @@ func main() {
<-sync
}
try = 0
- for s, ok = <-cs; !ok; s, ok = <-cs {
- try++
- if try > maxTries {
- panic("ssender")
+ RecvString:
+ for {
+ select {
+ case s = <-cs:
+ break RecvString
+ default:
+ try++
+ if try > maxTries {
+ panic("ssender")
+ }
+ sleep()
}
- sleep()
}
if s != "hello again" {
panic("ssender value")
diff --git a/gcc/testsuite/go.test/test/chan/perm.go b/gcc/testsuite/go.test/test/chan/perm.go
index d08c035..c725829 100644
--- a/gcc/testsuite/go.test/test/chan/perm.go
+++ b/gcc/testsuite/go.test/test/chan/perm.go
@@ -9,49 +9,46 @@ package main
var (
cr <-chan int
cs chan<- int
- c chan int
+ c chan int
)
func main() {
- cr = c // ok
- cs = c // ok
- c = cr // ERROR "illegal types|incompatible|cannot"
- c = cs // ERROR "illegal types|incompatible|cannot"
- cr = cs // ERROR "illegal types|incompatible|cannot"
- cs = cr // ERROR "illegal types|incompatible|cannot"
-
- c <- 0 // ok
- ok := c <- 0 // ok
- _ = ok
- <-c // ok
- x, ok := <-c // ok
- _, _ = x, ok
-
- cr <- 0 // ERROR "send"
- ok = cr <- 0 // ERROR "send"
- _ = ok
- <-cr // ok
- x, ok = <-cr // ok
- _, _ = x, ok
-
- cs <- 0 // ok
- ok = cs <- 0 // ok
- _ = ok
- <-cs // ERROR "receive"
- x, ok = <-cs // ERROR "receive"
- _, _ = x, ok
+ cr = c // ok
+ cs = c // ok
+ c = cr // ERROR "illegal types|incompatible|cannot"
+ c = cs // ERROR "illegal types|incompatible|cannot"
+ cr = cs // ERROR "illegal types|incompatible|cannot"
+ cs = cr // ERROR "illegal types|incompatible|cannot"
+
+ c <- 0 // ok
+ <-c // ok
+ //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ // x, ok := <-c // ok
+ // _, _ = x, ok
+
+ cr <- 0 // ERROR "send"
+ <-cr // ok
+ //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ // x, ok = <-cr // ok
+ // _, _ = x, ok
+
+ cs <- 0 // ok
+ <-cs // ERROR "receive"
+ ////TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ //// x, ok = <-cs // ERROR "receive"
+ //// _, _ = x, ok
select {
- case c <- 0: // ok
- case x := <-c: // ok
+ case c <- 0: // ok
+ case x := <-c: // ok
_ = x
- case cr <- 0: // ERROR "send"
- case x := <-cr: // ok
+ case cr <- 0: // ERROR "send"
+ case x := <-cr: // ok
_ = x
- case cs <- 0: // ok
- case x := <-cs: // ERROR "receive"
+ case cs <- 0: // ok
+ case x := <-cs: // ERROR "receive"
_ = x
}
}
diff --git a/gcc/testsuite/go.test/test/closedchan.go b/gcc/testsuite/go.test/test/closedchan.go
index 8126d5a..46d9d0f 100644
--- a/gcc/testsuite/go.test/test/closedchan.go
+++ b/gcc/testsuite/go.test/test/closedchan.go
@@ -21,14 +21,21 @@ type Chan interface {
Impl() string
}
-// direct channel operations
+// direct channel operations when possible
type XChan chan int
+
func (c XChan) Send(x int) {
c <- x
}
func (c XChan) Nbsend(x int) bool {
- return c <- x
+ select {
+ case c <- x:
+ return true
+ default:
+ return false
+ }
+ panic("nbsend")
}
func (c XChan) Recv() int {
@@ -36,8 +43,13 @@ func (c XChan) Recv() int {
}
func (c XChan) Nbrecv() (int, bool) {
- x, ok := <-c
- return x, ok
+ select {
+ case x := <-c:
+ return x, true
+ default:
+ return 0, false
+ }
+ panic("nbrecv")
}
func (c XChan) Close() {
@@ -54,6 +66,7 @@ func (c XChan) Impl() string {
// indirect operations via select
type SChan chan int
+
func (c SChan) Send(x int) {
select {
case c <- x:
@@ -62,10 +75,10 @@ func (c SChan) Send(x int) {
func (c SChan) Nbsend(x int) bool {
select {
- case c <- x:
- return true
default:
return false
+ case c <- x:
+ return true
}
panic("nbsend")
}
@@ -80,10 +93,10 @@ func (c SChan) Recv() int {
func (c SChan) Nbrecv() (int, bool) {
select {
- case x := <-c:
- return x, true
default:
return 0, false
+ case x := <-c:
+ return x, true
}
panic("nbrecv")
}
@@ -100,6 +113,62 @@ func (c SChan) Impl() string {
return "(select)"
}
+// indirect operations via larger selects
+var dummy = make(chan bool)
+
+type SSChan chan int
+
+func (c SSChan) Send(x int) {
+ select {
+ case c <- x:
+ case <-dummy:
+ }
+}
+
+func (c SSChan) Nbsend(x int) bool {
+ select {
+ default:
+ return false
+ case <-dummy:
+ case c <- x:
+ return true
+ }
+ panic("nbsend")
+}
+
+func (c SSChan) Recv() int {
+ select {
+ case <-dummy:
+ case x := <-c:
+ return x
+ }
+ panic("recv")
+}
+
+func (c SSChan) Nbrecv() (int, bool) {
+ select {
+ case <-dummy:
+ default:
+ return 0, false
+ case x := <-c:
+ return x, true
+ }
+ panic("nbrecv")
+}
+
+func (c SSChan) Close() {
+ close(c)
+}
+
+func (c SSChan) Closed() bool {
+ return closed(c)
+}
+
+func (c SSChan) Impl() string {
+ return "(select)"
+}
+
+
func shouldPanic(f func()) {
defer func() {
if recover() == nil {
@@ -137,7 +206,7 @@ func test1(c Chan) {
}
// send should work with ,ok too: sent a value without blocking, so ok == true.
- shouldPanic(func(){c.Nbsend(1)})
+ shouldPanic(func() { c.Nbsend(1) })
// the value should have been discarded.
if x := c.Recv(); x != 0 {
@@ -145,7 +214,7 @@ func test1(c Chan) {
}
// similarly Send.
- shouldPanic(func(){c.Send(2)})
+ 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())
}
@@ -195,9 +264,12 @@ func closedasync() chan int {
func main() {
test1(XChan(closedsync()))
test1(SChan(closedsync()))
+ test1(SSChan(closedsync()))
testasync1(XChan(closedasync()))
testasync1(SChan(closedasync()))
+ testasync1(SSChan(closedasync()))
testasync2(XChan(closedasync()))
testasync2(SChan(closedasync()))
+ testasync2(SSChan(closedasync()))
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug069.go b/gcc/testsuite/go.test/test/fixedbugs/bug069.go
index d6796cd..bf73163 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug069.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug069.go
@@ -6,15 +6,16 @@
package main
-func main(){
- c := make(chan int);
- ok := false;
- var i int;
-
- i, ok = <-c; // works
- _, _ = i, ok;
-
- ca := new([2]chan int);
- i, ok = <-(ca[0]); // fails: c.go:11: bad shape across assignment - cr=1 cl=2
- _, _ = i, ok;
+func main() {
+ //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ // c := make(chan int);
+ // ok := false;
+ // var i int;
+ //
+ // i, ok = <-c; // works
+ // _, _ = i, ok;
+ //
+ // ca := new([2]chan int);
+ // i, ok = <-(ca[0]); // fails: c.go:11: bad shape across assignment - cr=1 cl=2
+ // _, _ = i, ok;
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug196.go b/gcc/testsuite/go.test/test/fixedbugs/bug196.go
index ea8ab0d..8cb9c99 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug196.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug196.go
@@ -13,11 +13,12 @@ var i int
func multi() (int, int) { return 1, 2 }
func xxx() {
- var c chan int
- x, ok := <-c
+ //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ // var c chan int
+ // x, ok := <-c
var m map[int]int
- x, ok = m[1]
+ x, ok := m[1]
var i interface{}
var xx int
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug234.go b/gcc/testsuite/go.test/test/fixedbugs/bug234.go
index b806ca6..9affad0 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug234.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug234.go
@@ -7,16 +7,17 @@
package main
func main() {
- c := make(chan int, 1)
- c <- 100
- x, ok := <-c
- if x != 100 || !ok {
- println("x=", x, " ok=", ok, " want 100, true")
- panic("fail")
- }
- x, ok = <-c
- if x != 0 || ok {
- println("x=", x, " ok=", ok, " want 0, false")
- panic("fail")
- }
+ //TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ // c := make(chan int, 1)
+ // c <- 100
+ // x, ok := <-c
+ // if x != 100 || !ok {
+ // println("x=", x, " ok=", ok, " want 100, true")
+ // panic("fail")
+ // }
+ // x, ok = <-c
+ // if x != 0 || ok {
+ // println("x=", x, " ok=", ok, " want 0, false")
+ // panic("fail")
+ // }
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug242.go b/gcc/testsuite/go.test/test/fixedbugs/bug242.go
index 5c21eaa..ad1cef8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug242.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug242.go
@@ -101,10 +101,13 @@ func main() {
c := make(chan byte, 1)
c <- 'C'
+ //TODO(rsc): uncomment when this syntax is valid for receive+check closed
// 15 16
- *f(), p1 = <-e1(c, 16)
+ // *f(), p1 = <-e1(c, 16)
+ *f(), p1 = <-e1(c, 16), true // delete uncommenting above
// 17 18
- *f(), p2 = <-e1(c, 18)
+ // *f(), p2 = <-e1(c, 18)
+ *f(), p2, _ = 0, false, e1(c, 18) // delete when uncommenting above
a[17] += '0'
if !p1 || p2 {
println("bad chan check", i, p1, p2)
diff --git a/gcc/testsuite/go.test/test/named1.go b/gcc/testsuite/go.test/test/named1.go
index 600e502..1776313 100644
--- a/gcc/testsuite/go.test/test/named1.go
+++ b/gcc/testsuite/go.test/test/named1.go
@@ -43,12 +43,9 @@ func main() {
_, b = m[2] // ERROR "cannot .* bool.*type Bool"
m[2] = 1, b // ERROR "cannot use.*type Bool.*as type bool"
- b = c <- 1 // ERROR "cannot use.*type bool.*type Bool"
- _ = b
- asBool(c <- 1) // ERROR "cannot use.*type bool.*as type Bool"
-
- _, b = <-c // ERROR "cannot .* bool.*type Bool"
- _ = b
+ ////TODO(rsc): uncomment when this syntax is valid for receive+check closed
+ //// _, b = <-c // ERROR "cannot .* bool.*type Bool"
+ //// _ = b
var inter interface{}
_, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"