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

Unified Diff: runtime/vm/parser.cc

Issue 10825140: Add check for duplicate field initialization (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 10098)
+++ runtime/vm/parser.cc (working copy)
@@ -1609,7 +1609,9 @@
}
-AstNode* Parser::ParseInitializer(const Class& cls, LocalVariable* receiver) {
+AstNode* Parser::ParseInitializer(const Class& cls,
+ LocalVariable* receiver,
+ GrowableArray<Field*>* initialized_fields) {
TRACE_PARSER("ParseInitializer");
const intptr_t field_pos = TokenPos();
if (CurrentToken() == Token::kTHIS) {
@@ -1630,6 +1632,7 @@
ErrorMsg(field_pos, "unresolved reference to instance field '%s'",
field_name.ToCString());
}
+ CheckDuplicateFieldInit(field_pos, initialized_fields, &field);
AstNode* instance = new LoadLocalNode(field_pos, *receiver);
return new StoreInstanceFieldNode(field_pos, instance, field, init_expr);
}
@@ -1671,7 +1674,8 @@
void Parser::ParseInitializedInstanceFields(const Class& cls,
- GrowableArray<FieldInitExpression>* initializers) {
+ GrowableArray<FieldInitExpression>* initializers,
+ GrowableArray<Field*>* initialized_fields) {
TRACE_PARSER("ParseInitializedInstanceFields");
const Array& fields = Array::Handle(cls.fields());
Field& f = Field::Handle();
@@ -1681,11 +1685,18 @@
if (!f.is_static() && f.has_initializer()) {
Field& field = Field::ZoneHandle();
field ^= fields.At(i);
+ if (field.is_final()) {
+ // Final fields with initializer expression may not be initialized
+ // again by constructors. Remember that this field is already
+ // initialized.
+ initialized_fields->Add(&field);
+ }
intptr_t field_pos = field.token_pos();
SetPosition(field_pos);
ASSERT(IsIdentifier());
ConsumeToken();
ExpectToken(Token::kASSIGN);
+ // TODO(hausner): Allow non-const expressions here for final fields.
AstNode* init_expr = ParseConstExpr();
ASSERT(init_expr != NULL);
FieldInitExpression initializer;
@@ -1698,7 +1709,25 @@
}
-void Parser::ParseInitializers(const Class& cls, LocalVariable* receiver) {
+void Parser::CheckDuplicateFieldInit(intptr_t init_pos,
+ GrowableArray<Field*>* initialized_fields,
+ Field* field) {
+ ASSERT(!field->is_static());
+ for (int i = 0; i < initialized_fields->length(); i++) {
+ Field* initialized_field = (*initialized_fields)[i];
+ if (initialized_field->raw() == field->raw()) {
+ ErrorMsg(init_pos,
+ "Duplicate initialization for field %s",
regis 2012/08/01 21:58:03 Most error messages start with a lower case.
hausner 2012/08/01 22:23:14 Done.
+ String::Handle(field->name()).ToCString());
+ }
+ }
+ initialized_fields->Add(field);
+}
+
+
+void Parser::ParseInitializers(const Class& cls,
+ LocalVariable* receiver,
+ GrowableArray<Field*>* initialized_fields) {
TRACE_PARSER("ParseInitializers");
bool super_init_seen = false;
if (CurrentToken() == Token::kCOLON) {
@@ -1724,7 +1753,7 @@
init_statement = ParseSuperInitializer(cls, receiver);
super_init_seen = true;
} else {
- init_statement = ParseInitializer(cls, receiver);
+ init_statement = ParseInitializer(cls, receiver, initialized_fields);
}
current_block_->statements->Add(init_statement);
} while (CurrentToken() == Token::kCOMMA);
@@ -1799,8 +1828,9 @@
// Parse expressions of instance fields that have an explicit
// initializers.
GrowableArray<FieldInitExpression> initializers;
+ GrowableArray<Field*> initialized_fields;
Class& cls = Class::Handle(func.owner());
- ParseInitializedInstanceFields(cls, &initializers);
+ ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
LocalVariable* receiver = new LocalVariable(
ctor_pos,
@@ -1891,7 +1921,8 @@
// the parameters are added to the scope, so that a parameter
// name cannot shadow a name used in the field initializer expression.
GrowableArray<FieldInitExpression> initializers;
- ParseInitializedInstanceFields(cls, &initializers);
+ GrowableArray<Field*> initialized_fields;
+ ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
// Now populate function scope with the formal parameters.
AddFormalParamsToScope(&params, current_block_->scope);
@@ -1926,6 +1957,7 @@
"unresolved reference to instance field '%s'",
field_name.ToCString());
}
+ CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field);
AstNode* instance = new LoadLocalNode(param.name_pos, *receiver);
LocalVariable* p =
current_block_->scope->LookupVariable(*param.name, false);
@@ -1943,7 +1975,7 @@
}
// Now parse the explicit initializer list or constructor redirection.
- ParseInitializers(cls, receiver);
+ ParseInitializers(cls, receiver, &initialized_fields);
SequenceNode* init_statements = CloseBlock();
if (init_statements->length() > 0) {
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698