Commit 79b4a34a by Ian Lance Taylor

Check for multiple default cases in switch or select.

From-SVN: r168481
parent f36067eb
...@@ -3825,6 +3825,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val, ...@@ -3825,6 +3825,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val,
this->push_break_statement(statement, label); this->push_break_statement(statement, label);
Case_clauses* case_clauses = new Case_clauses(); Case_clauses* case_clauses = new Case_clauses();
bool saw_default = false;
while (!this->peek_token()->is_op(OPERATOR_RCURLY)) while (!this->peek_token()->is_op(OPERATOR_RCURLY))
{ {
if (this->peek_token()->is_eof()) if (this->peek_token()->is_eof())
...@@ -3833,7 +3834,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val, ...@@ -3833,7 +3834,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val,
error_at(this->location(), "missing %<}%>"); error_at(this->location(), "missing %<}%>");
return NULL; return NULL;
} }
this->expr_case_clause(case_clauses); this->expr_case_clause(case_clauses, &saw_default);
} }
this->advance_token(); this->advance_token();
...@@ -3848,7 +3849,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val, ...@@ -3848,7 +3849,7 @@ Parse::expr_switch_body(const Label* label, Expression* switch_val,
// FallthroughStat = "fallthrough" . // FallthroughStat = "fallthrough" .
void void
Parse::expr_case_clause(Case_clauses* clauses) Parse::expr_case_clause(Case_clauses* clauses, bool* saw_default)
{ {
source_location location = this->location(); source_location location = this->location();
...@@ -3880,6 +3881,16 @@ Parse::expr_case_clause(Case_clauses* clauses) ...@@ -3880,6 +3881,16 @@ Parse::expr_case_clause(Case_clauses* clauses)
this->advance_token(); 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) if (is_default || vals != NULL)
clauses->add(vals, is_default, statements, is_fallthrough, location); 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, ...@@ -3936,6 +3947,7 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch,
this->push_break_statement(statement, label); this->push_break_statement(statement, label);
Type_case_clauses* case_clauses = new Type_case_clauses(); Type_case_clauses* case_clauses = new Type_case_clauses();
bool saw_default = false;
while (!this->peek_token()->is_op(OPERATOR_RCURLY)) while (!this->peek_token()->is_op(OPERATOR_RCURLY))
{ {
if (this->peek_token()->is_eof()) if (this->peek_token()->is_eof())
...@@ -3943,7 +3955,7 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch, ...@@ -3943,7 +3955,7 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch,
error_at(this->location(), "missing %<}%>"); error_at(this->location(), "missing %<}%>");
return NULL; return NULL;
} }
this->type_case_clause(switch_no, case_clauses); this->type_case_clause(switch_no, case_clauses, &saw_default);
} }
this->advance_token(); this->advance_token();
...@@ -3957,7 +3969,8 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch, ...@@ -3957,7 +3969,8 @@ Parse::type_switch_body(const Label* label, const Type_switch& type_switch,
// TypeCaseClause = TypeSwitchCase ":" [ StatementList ] . // TypeCaseClause = TypeSwitchCase ":" [ StatementList ] .
void 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(); source_location location = this->location();
...@@ -4000,6 +4013,12 @@ Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses) ...@@ -4000,6 +4013,12 @@ Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses)
if (is_default) if (is_default)
{ {
gcc_assert(types.empty()); 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); clauses->add(NULL, false, true, statements, location);
} }
else if (!types.empty()) else if (!types.empty())
...@@ -4076,6 +4095,7 @@ Parse::select_stat(const Label* label) ...@@ -4076,6 +4095,7 @@ Parse::select_stat(const Label* label)
this->push_break_statement(statement, label); this->push_break_statement(statement, label);
Select_clauses* select_clauses = new Select_clauses(); Select_clauses* select_clauses = new Select_clauses();
bool saw_default = false;
while (!this->peek_token()->is_op(OPERATOR_RCURLY)) while (!this->peek_token()->is_op(OPERATOR_RCURLY))
{ {
if (this->peek_token()->is_eof()) if (this->peek_token()->is_eof())
...@@ -4083,7 +4103,7 @@ Parse::select_stat(const Label* label) ...@@ -4083,7 +4103,7 @@ Parse::select_stat(const Label* label)
error_at(this->location(), "expected %<}%>"); error_at(this->location(), "expected %<}%>");
return; return;
} }
this->comm_clause(select_clauses); this->comm_clause(select_clauses, &saw_default);
} }
this->advance_token(); this->advance_token();
...@@ -4098,7 +4118,7 @@ Parse::select_stat(const Label* label) ...@@ -4098,7 +4118,7 @@ Parse::select_stat(const Label* label)
// CommClause = CommCase [ StatementList ] . // CommClause = CommCase [ StatementList ] .
void void
Parse::comm_clause(Select_clauses* clauses) Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
{ {
source_location location = this->location(); source_location location = this->location();
bool is_send = false; bool is_send = false;
...@@ -4130,6 +4150,16 @@ Parse::comm_clause(Select_clauses* clauses) ...@@ -4130,6 +4150,16 @@ Parse::comm_clause(Select_clauses* clauses)
statements = this->gogo_->finish_block(this->location()); 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) if (got_case)
clauses->add(is_send, channel, val, var, is_default, statements, location); clauses->add(is_send, channel, val, var, is_default, statements, location);
} }
......
...@@ -238,14 +238,14 @@ class Parse ...@@ -238,14 +238,14 @@ class Parse
void if_stat(); void if_stat();
void switch_stat(const Label*); void switch_stat(const Label*);
Statement* expr_switch_body(const Label*, Expression*, source_location); 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*); Expression_list* expr_switch_case(bool*);
Statement* type_switch_body(const Label*, const Type_switch&, Statement* type_switch_body(const Label*, const Type_switch&,
source_location); 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 type_switch_case(std::vector<Type*>*, bool*);
void select_stat(const Label*); 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 comm_case(bool*, Expression**, Expression**, std::string*, bool*);
bool send_or_recv_expr(bool*, Expression**, Expression**, std::string*); bool send_or_recv_expr(bool*, Expression**, Expression**, std::string*);
void for_stat(const Label*); void for_stat(const Label*);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment