Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Unified Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10916002: Change switch to give errors when cases don't follow the newest syntax. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/compiler/implementation/ssa/builder.dart
diff --git a/lib/compiler/implementation/ssa/builder.dart b/lib/compiler/implementation/ssa/builder.dart
index 4f4afed3e79c44934fc8442b8dda423643c74f1a..1776b892d1875f33321f6cc7a908cd996827a7ba 100644
--- a/lib/compiler/implementation/ssa/builder.dart
+++ b/lib/compiler/implementation/ssa/builder.dart
@@ -3138,8 +3138,13 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
bool tryBuildConstantSwitch(SwitchStatement node) {
+ // TODO(lrn): Move the constant resolution to the resolver, so
+ // we can report an error before reaching the backend.
Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
- // First check whether all case expressions are compile-time constants.
+ // First check whether all case expressions are compile-time constants,
+ // and all have the same type that doesn't override operator==.
+ Constant firstConstant = null;
+ bool failure = false;
for (SwitchCase switchCase in node.cases) {
for (Node labelOrCase in switchCase.labelsAndCases) {
if (labelOrCase is CaseMatch) {
@@ -3147,14 +3152,37 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
Constant constant =
compiler.constantHandler.tryCompileNodeWithDefinitions(
match.expression, elements);
- if (constant === null) return false;
+ if (constant === null) {
+ compiler.reportWarning(match.expression,
+ MessageKind.NOT_A_COMPILE_TIME_CONSTANT.error());
+ failure = true;
+ continue;
+ }
+ if (firstConstant == null) {
+ firstConstant = constant;
+ if (nonPrimitiveTypeOverridesEquals(constant)) {
+ compiler.reportWarning(match.expression,
+ MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS.error());
+ failure = true;
+ }
+ } else {
+ if (!constant.isSameType(firstConstant)) {
+ compiler.reportWarning(match.expression,
+ MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL.error());
+ failure = true;
+ }
+ }
constants[labelOrCase] = constant;
} else {
- // We don't handle labels yet.
- return false;
+ compiler.reportWarning(node, "Unsupported: Labels on cases");
+ failure = true;
}
}
}
+ if (failure) {
+ return false;
+ }
+
// TODO(ngeoffray): Handle switch-instruction in bailout code.
work.allowSpeculativeOptimization = false;
// Then build a switch structure.
@@ -3266,6 +3294,29 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
return true;
}
+ bool nonPrimitiveTypeOverridesEquals(Constant constant) {
+ // If constant is primitive, just return false. We know
+ // about the equals methods of num/String classes.
+ // [Map] and [List] does not override equals.
floitsch 2012/08/30 14:08:18 do not
Lasse Reichstein Nielsen 2012/09/03 09:12:56 Done.
+ if (!constant.isConstructedObject()) return false;
+
+ ConstructedConstant constructedConstant = constant;
+ Type type = constructedConstant.type;
+ assert(type !== null);
+ Element element = type.element;
ngeoffray 2012/08/30 07:29:13 The code below probably deserves to be in a helper
Lasse Reichstein Nielsen 2012/08/30 10:54:25 Any wish for the abstraction level? isOverridingEq
ngeoffray 2012/08/30 11:07:13 I like the three of them :) The first two are easy
Lasse Reichstein Nielsen 2012/09/03 09:12:56 I went with typeOverridesObjectEquals and lookup
+ // If the type is not a class, we'll just assume it overrides
+ // operator==. Typedefs do, since [Function] does.
+ if (!element.isClass()) return true;
+ ClassElement classElement = element;
+ SourceString dartMethodName = Elements.constructOperatorName(
+ const SourceString('operator'),
+ const SourceString('=='));
+ Element operatorEq = classElement.lookupMember(dartMethodName);
+ if (operatorEq == null) return false;
+ // If the operator== declaration is in Object, it's not overridden.
+ return (operatorEq.getEnclosingClass() != compiler.objectClass);
+ }
+
// Recursively build an if/else structure to match the cases.
void buildSwitchCases(Link<Node> cases, HInstruction expression,
@@ -3326,33 +3377,9 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
compiler.constantHandler.tryCompileNodeWithDefinitions(
match.expression, elements);
if (constant !== null) {
- if (constant.isInt()) {
- // Report the first mixed-string/int type error only.
- if (encounteredCaseTypes == STRING_TYPE) {
- compiler.reportWarning(
- match, MessageKind.INVALID_CASE_EXPRESSION_TYPE);
- }
- encounteredCaseTypes = combine(encounteredCaseTypes, INT_TYPE);
- } else if (constant.isString()) {
- if (encounteredCaseTypes == INT_TYPE) {
- compiler.reportWarning(
- match, MessageKind.INVALID_CASE_EXPRESSION_TYPE);
- }
- encounteredCaseTypes = combine(encounteredCaseTypes, STRING_TYPE);
- } else {
- compiler.reportWarning(match,
- MessageKind.INVALID_CASE_EXPRESSION);
- encounteredCaseTypes = CONFLICT_TYPE;
- }
stack.add(graph.addConstant(constant));
} else {
- // TODO(lrn): Remove this else branch, and make the constant
- // evaluation mandatory when we are ready to break existing code using
- // non constant-int-or-string expressions.
- compiler.reportWarning(match,
- 'case expressions not compile-time constant int or string.');
visit(match.expression);
- encounteredCaseTypes = CONFLICT_TYPE;
}
push(new HEquals(target, pop(), expression));
}

Powered by Google App Engine
This is Rietveld 408576698