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())
error_at(this->location(), "missing %<}%>");
return NULL;
}
- this->expr_case_clause(case_clauses);
+ this->expr_case_clause(case_clauses, &saw_default);
}
this->advance_token();
// 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();
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);
}
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())
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();
// 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();
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())
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())
error_at(this->location(), "expected %<}%>");
return;
}
- this->comm_clause(select_clauses);
+ this->comm_clause(select_clauses, &saw_default);
}
this->advance_token();
// 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;
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);
}
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<Type*>*, 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*);