From 79b4a34ad062d1c4e9effcc508e8b44d6d9b5075 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 4 Jan 2011 19:34:32 +0000 Subject: [PATCH] Check for multiple default cases in switch or select. From-SVN: r168481 --- gcc/go/gofrontend/parse.cc | 42 ++++++++++++++++++++++++++++++++++++------ gcc/go/gofrontend/parse.h | 6 +++--- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index f4b01be..13374f4 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -3825,6 +3825,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val, this->push_break_statement(statement, label); Case_clauses* case_clauses = new Case_clauses(); + bool saw_default = false; while (!this->peek_token()->is_op(OPERATOR_RCURLY)) { if (this->peek_token()->is_eof()) @@ -3833,7 +3834,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val, error_at(this->location(), "missing %<}%>"); return NULL; } - this->expr_case_clause(case_clauses); + this->expr_case_clause(case_clauses, &saw_default); } this->advance_token(); @@ -3848,7 +3849,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val, // FallthroughStat = "fallthrough" . void -Parse::expr_case_clause(Case_clauses* clauses) +Parse::expr_case_clause(Case_clauses* clauses, bool* saw_default) { source_location location = this->location(); @@ -3880,6 +3881,16 @@ Parse::expr_case_clause(Case_clauses* clauses) this->advance_token(); } + if (is_default) + { + if (*saw_default) + { + error_at(location, "multiple defaults in switch"); + return; + } + *saw_default = true; + } + if (is_default || vals != NULL) clauses->add(vals, is_default, statements, is_fallthrough, location); } @@ -3936,6 +3947,7 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch, this->push_break_statement(statement, label); Type_case_clauses* case_clauses = new Type_case_clauses(); + bool saw_default = false; while (!this->peek_token()->is_op(OPERATOR_RCURLY)) { if (this->peek_token()->is_eof()) @@ -3943,7 +3955,7 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch, error_at(this->location(), "missing %<}%>"); return NULL; } - this->type_case_clause(switch_no, case_clauses); + this->type_case_clause(switch_no, case_clauses, &saw_default); } this->advance_token(); @@ -3957,7 +3969,8 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch, // TypeCaseClause = TypeSwitchCase ":" [ StatementList ] . void -Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses) +Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses, + bool* saw_default) { source_location location = this->location(); @@ -4000,6 +4013,12 @@ Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses) if (is_default) { gcc_assert(types.empty()); + if (*saw_default) + { + error_at(location, "multiple defaults in type switch"); + return; + } + *saw_default = true; clauses->add(NULL, false, true, statements, location); } else if (!types.empty()) @@ -4076,6 +4095,7 @@ Parse::select_stat(const Label* label) this->push_break_statement(statement, label); Select_clauses* select_clauses = new Select_clauses(); + bool saw_default = false; while (!this->peek_token()->is_op(OPERATOR_RCURLY)) { if (this->peek_token()->is_eof()) @@ -4083,7 +4103,7 @@ Parse::select_stat(const Label* label) error_at(this->location(), "expected %<}%>"); return; } - this->comm_clause(select_clauses); + this->comm_clause(select_clauses, &saw_default); } this->advance_token(); @@ -4098,7 +4118,7 @@ Parse::select_stat(const Label* label) // CommClause = CommCase [ StatementList ] . void -Parse::comm_clause(Select_clauses* clauses) +Parse::comm_clause(Select_clauses* clauses, bool* saw_default) { source_location location = this->location(); bool is_send = false; @@ -4130,6 +4150,16 @@ Parse::comm_clause(Select_clauses* clauses) statements = this->gogo_->finish_block(this->location()); } + if (is_default) + { + if (*saw_default) + { + error_at(location, "multiple defaults in select"); + return; + } + *saw_default = true; + } + if (got_case) clauses->add(is_send, channel, val, var, is_default, statements, location); } diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h index 1fa9319..65f1586 100644 --- a/gcc/go/gofrontend/parse.h +++ b/gcc/go/gofrontend/parse.h @@ -238,14 +238,14 @@ class Parse void if_stat(); void switch_stat(const Label*); Statement* expr_switch_body(const Label*, Expression*, source_location); - void expr_case_clause(Case_clauses*); + void expr_case_clause(Case_clauses*, bool* saw_default); Expression_list* expr_switch_case(bool*); Statement* type_switch_body(const Label*, const Type_switch&, source_location); - void type_case_clause(Named_object*, Type_case_clauses*); + void type_case_clause(Named_object*, Type_case_clauses*, bool* saw_default); void type_switch_case(std::vector*, bool*); void select_stat(const Label*); - void comm_clause(Select_clauses*); + void comm_clause(Select_clauses*, bool* saw_default); bool comm_case(bool*, Expression**, Expression**, std::string*, bool*); bool send_or_recv_expr(bool*, Expression**, Expression**, std::string*); void for_stat(const Label*); -- 2.7.4