Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index f96c1a3ec17e9fb14636824aff397baba1ee81ab..f191c8574d8bbf01d0fbc271a667cbda6b66e839 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -3021,6 +3021,15 @@ AstNode* Parser::CheckDuplicateFieldInit( |
| if (initialized_field == NULL) { |
| break; |
| } |
| + |
| + const String& initialized_name = |
| + String::ZoneHandle(initialized_field->name()); |
| + const String& field_name = String::ZoneHandle(field->name()); |
|
siva
2017/06/13 22:20:08
Why do these have to be zone handles and not just
|
| + if (initialized_name.Equals(field_name) && field->IsFinalAndInitialized()) { |
| + ReportError(init_pos, "'%s' is initialized already, and final.", |
|
zra
2017/06/13 20:19:41
How about "final field '%s' is already initialized
bkonyi
2017/06/13 22:16:47
Done.
|
| + field_name.ToCString()); |
| + } |
| + |
| if (initialized_field->raw() == field->raw()) { |
| // This final field has been initialized by an inlined |
| // initializer expression. This is a runtime error. |
| @@ -4495,6 +4504,37 @@ void Parser::CheckMemberNameConflict(ClassDesc* members, MemberDesc* member) { |
| } |
| +void Parser::CheckMemberAlreadyInitializedConflicts(ClassDesc* members, |
| + MemberDesc* member) { |
| + if (!member->IsConstructor()) { |
| + return; |
| + } |
| + ParamList* params = &member->params; |
| + if (!params->has_field_initializer) { |
| + return; |
| + } |
| + const ZoneGrowableArray<ParamDesc>& parameters = *params->parameters; |
| + for (int p = 0; p < parameters.length(); p++) { |
|
zra
2017/06/13 20:19:41
intptr_t p
bkonyi
2017/06/13 22:16:47
Done.
|
| + const ParamDesc& current_param = parameters[p]; |
| + if (!current_param.is_field_initializer) { |
| + continue; |
| + } |
| + const String& name = *current_param.name; |
| + for (int i = 0; i < members->members().length(); i++) { |
|
zra
2017/06/13 20:19:42
intptr_t i
bkonyi
2017/06/13 22:16:47
Done.
|
| + MemberDesc* existing_member = &members->members()[i]; |
| + if (existing_member->has_final && |
| + name.Equals(*existing_member->DictName()) && |
| + existing_member->field_ != NULL && |
|
zra
2017/06/13 20:19:42
parens around != clause
bkonyi
2017/06/13 22:16:47
Done.
|
| + existing_member->field_->IsFinalAndInitialized()) { |
| + ReportError(current_param.name_pos, |
| + "'%s' is initialized already, and final.", |
|
zra
2017/06/13 20:19:41
"final field %s is already initialized"
bkonyi
2017/06/13 22:16:47
Done.
|
| + existing_member->DictName()->ToCString()); |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| void Parser::ParseClassMemberDefinition(ClassDesc* members, |
| TokenPosition metadata_pos) { |
| TRACE_PARSER("ParseClassMemberDefinition"); |
| @@ -4707,6 +4747,7 @@ void Parser::ParseClassMemberDefinition(ClassDesc* members, |
| } |
| current_member_ = NULL; |
| CheckMemberNameConflict(members, &member); |
| + CheckMemberAlreadyInitializedConflicts(members, &member); |
| members->AddMember(member); |
| } |