Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index f96c1a3ec17e9fb14636824aff397baba1ee81ab..2eb8912ae71a1a9b972509e7b7a98a6c9c711c8e 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()); |
+ if (initialized_name.Equals(field_name) && field->IsFinalAndInitialized()) { |
+ ReportError(init_pos, "final field '%s' is already initialized.", |
+ 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 (intptr_t p = 0; p < parameters.length(); p++) { |
+ const ParamDesc& current_param = parameters[p]; |
+ if (!current_param.is_field_initializer) { |
+ continue; |
+ } |
+ const String& name = *current_param.name; |
+ for (intptr_t i = 0; i < members->members().length(); i++) { |
+ MemberDesc* existing_member = &members->members()[i]; |
+ if (existing_member->has_final && |
+ name.Equals(*existing_member->DictName()) && |
+ (existing_member->field_ != NULL) && |
+ existing_member->field_->IsFinalAndInitialized()) { |
siva
2017/06/13 22:37:57
The correct check here is to use field_->has_initi
bkonyi
2017/06/15 22:32:48
Ah, don't know how I missed that... done.
|
+ ReportError(current_param.name_pos, |
+ "final field '%s' is already initialized.", |
+ 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); |
siva
2017/06/13 22:37:56
I don't think this is quite correct, consider this
bkonyi
2017/06/15 22:32:48
This seemed to work, but it probably makes more se
|
members->AddMember(member); |
} |