Implement type checks for switch expression

If the switch expression is not compatible with the case clause
constants, we must report a runtime error. Implement this by annotating
the temporary variable holding the switch expression with the correct
type.

Issue 7274

R=regis@google.com

Review URL: https://codereview.chromium.org//34413007

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@29126 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
hausner@google.com 2013-10-23 21:15:25 +00:00
parent 45e20b5921
commit ddd9907e23
3 changed files with 27 additions and 10 deletions

View file

@ -6028,10 +6028,11 @@ static bool ImplementsEqualOperator(const Instance& value) {
// or any other class that does not override the == operator.
// The expressions are compile-time constants and are thus in the form
// of a LiteralNode.
void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) {
RawClass* Parser::CheckCaseExpressions(
const GrowableArray<LiteralNode*>& values) {
const intptr_t num_expressions = values.length();
if (num_expressions == 0) {
return;
return Object::dynamic_class();
}
const Instance& first_value = values[0]->literal();
for (intptr_t i = 0; i < num_expressions; i++) {
@ -6066,6 +6067,12 @@ void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) {
}
}
}
if (first_value.IsInteger()) {
return Type::Handle(Type::IntType()).type_class();
} else if (first_value.IsString()) {
return Type::Handle(Type::StringType()).type_class();
}
return first_value.clazz();
}
@ -6164,11 +6171,18 @@ AstNode* Parser::ParseSwitchStatement(String* label_name) {
OpenBlock();
current_block_->scope->AddLabel(label);
// Store switch expression in temporary local variable.
// Store switch expression in temporary local variable. The type of the
// variable is set to dynamic. It will later be patched to match the
// type of the case clause expressions. Therefore, we have to allocate
// a new type representing dynamic and can't reuse the canonical
// type object for dynamic.
const Type& temp_var_type =
Type::ZoneHandle(Type::New(Class::Handle(Object::dynamic_class()),
TypeArguments::Handle(),
expr_pos));
temp_var_type.SetIsFinalized();
LocalVariable* temp_variable =
new LocalVariable(expr_pos,
Symbols::SwitchExpr(),
Type::ZoneHandle(Type::DynamicType()));
new LocalVariable(expr_pos, Symbols::SwitchExpr(), temp_var_type);
current_block_->scope->AddVariable(temp_variable);
AstNode* save_switch_expr =
new StoreLocalNode(expr_pos, temp_variable, switch_expr);
@ -6221,8 +6235,11 @@ AstNode* Parser::ParseSwitchStatement(String* label_name) {
}
// Check that all expressions in case clauses are of the same class,
// or implement int, double or String.
CheckCaseExpressions(case_expr_values);
// or implement int, double or String. Patch the type of the temporary
// variable holding the switch expression to match the type of the
// case clause constants.
temp_var_type.set_type_class(
Class::Handle(CheckCaseExpressions(case_expr_values)));
// Check for unresolved label references.
SourceLabel* unresolved_label =

View file

@ -498,7 +498,7 @@ class Parser : public ValueObject {
AstNode* ParseDoWhileStatement(String* label_name);
AstNode* ParseForStatement(String* label_name);
AstNode* ParseForInStatement(intptr_t forin_pos, SourceLabel* label);
void CheckCaseExpressions(const GrowableArray<LiteralNode*>& values);
RawClass* CheckCaseExpressions(const GrowableArray<LiteralNode*>& values);
CaseNode* ParseCaseClause(LocalVariable* switch_expr_value,
GrowableArray<LiteralNode*>* case_expr_values,
SourceLabel* case_label);

View file

@ -162,8 +162,8 @@ LibTest/async/StreamEventTransformer/handleError_A01_t01: Fail # co19 issue 626
### CHECKED MODE FAILURES ###
[ ($runtime == vm || $compiler == dart2js) && $checked]
Language/13_Statements/09_Switch_A09_t01: PASS, FAIL, OK # co19 issue 633
Language/07_Classes/6_Constructors/2_Factories_A12_t02: fail # co19-roll r587: Please triage this failure
Language/13_Statements/09_Switch_A05_t01: FAIL, OK # co19 issue 498
Language/14_Libraries_and_Scripts/1_Imports_A03_t46: PASS, FAIL, OK # co19 issue 560
Language/14_Libraries_and_Scripts/1_Imports_A03_t66: PASS, FAIL, OK # co19 issue 560
LibTest/async/EventTransformStream/contains_A01_t01: FAIL, OK # co19 issue 498