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

Side by Side Diff: runtime/vm/parser.cc

Issue 2939553005: Updated parser to produce error when trying to reinitialize final variables in class constructors. … (Closed)
Patch Set: Addressed asiva's comments Created 3 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 #include "vm/flags.h" 6 #include "vm/flags.h"
7 7
8 #ifndef DART_PRECOMPILED_RUNTIME 8 #ifndef DART_PRECOMPILED_RUNTIME
9 9
10 #include "lib/invocation_mirror.h" 10 #include "lib/invocation_mirror.h"
(...skipping 3003 matching lines...) Expand 10 before | Expand all | Expand 10 after
3014 // have an initializer expression inlined in the class declaration. 3014 // have an initializer expression inlined in the class declaration.
3015 // The remaining fields are those initialized by the constructor's 3015 // The remaining fields are those initialized by the constructor's
3016 // initializing formals and initializer list 3016 // initializing formals and initializer list
3017 int initializer_idx = 0; 3017 int initializer_idx = 0;
3018 while (initializer_idx < initialized_fields->length()) { 3018 while (initializer_idx < initialized_fields->length()) {
3019 Field* initialized_field = (*initialized_fields)[initializer_idx]; 3019 Field* initialized_field = (*initialized_fields)[initializer_idx];
3020 initializer_idx++; 3020 initializer_idx++;
3021 if (initialized_field == NULL) { 3021 if (initialized_field == NULL) {
3022 break; 3022 break;
3023 } 3023 }
3024
3025 const String& initialized_name = String::Handle(initialized_field->name());
3026 const String& field_name = String::Handle(field->name());
3027 if (initialized_name.Equals(field_name) && field->has_initializer()) {
3028 ReportError(init_pos, "final field '%s' is already initialized.",
3029 field_name.ToCString());
3030 }
siva 2017/06/16 00:51:10 Pull the handle creation outside the while loop S
bkonyi 2017/06/16 19:40:44 Done.
3031
3024 if (initialized_field->raw() == field->raw()) { 3032 if (initialized_field->raw() == field->raw()) {
3025 // This final field has been initialized by an inlined 3033 // This final field has been initialized by an inlined
3026 // initializer expression. This is a runtime error. 3034 // initializer expression. This is a runtime error.
3027 // Throw a NoSuchMethodError for the missing setter. 3035 // Throw a NoSuchMethodError for the missing setter.
3028 ASSERT(field->is_final()); 3036 ASSERT(field->is_final());
3029 3037
3030 // Build a call to NoSuchMethodError::_throwNew( 3038 // Build a call to NoSuchMethodError::_throwNew(
3031 // Object receiver, 3039 // Object receiver,
3032 // String memberName, 3040 // String memberName,
3033 // int invocation_type, 3041 // int invocation_type,
(...skipping 1454 matching lines...) Expand 10 before | Expand all | Expand 10 after
4488 MemberDesc* existing_member = &members->members()[i]; 4496 MemberDesc* existing_member = &members->members()[i];
4489 if (name.Equals(*existing_member->DictName())) { 4497 if (name.Equals(*existing_member->DictName())) {
4490 ReportError( 4498 ReportError(
4491 member->name_pos, "%s '%s' conflicts with previously declared %s", 4499 member->name_pos, "%s '%s' conflicts with previously declared %s",
4492 member->ToCString(), name.ToCString(), existing_member->ToCString()); 4500 member->ToCString(), name.ToCString(), existing_member->ToCString());
4493 } 4501 }
4494 } 4502 }
4495 } 4503 }
4496 4504
4497 4505
4506 void Parser::CheckFinalInitializationConflicts(ClassDesc* class_desc) {
4507 const GrowableArray<const Field*>& fields = class_desc->fields();
4508 const GrowableArray<MemberDesc>& members = class_desc->members();
4509 for (intptr_t i = 0; i < fields.length(); i++) {
4510 const Field* current_field = fields.At(i);
4511 if (!current_field->is_final() || !current_field->has_initializer()) {
4512 continue;
4513 }
4514 const String& field_name = String::Handle(current_field->name());
4515 for (intptr_t j = 0; j < members.length(); j++) {
4516 const MemberDesc current_member = members.At(j);
4517 if (!current_member.IsConstructor()) {
4518 continue;
4519 }
4520 const ParamList* params = &current_member.params;
4521 if (!params->has_field_initializer) {
4522 continue;
4523 }
4524 const ZoneGrowableArray<ParamDesc>& parameters = *params->parameters;
4525 for (intptr_t p = 0; p < parameters.length(); p++) {
4526 const ParamDesc& current_param = parameters[p];
4527 if (!current_param.is_field_initializer) {
4528 continue;
4529 }
4530 const String& param_name = *current_param.name;
4531 if (param_name.Equals(field_name)) {
4532 ReportError(current_param.name_pos,
4533 "final field '%s' is already initialized.",
4534 param_name.ToCString());
4535 }
4536 }
4537 }
4538 }
4539 }
siva 2017/06/16 00:51:10 If you invert this loop as for (intptr_t j = 0; j
bkonyi 2017/06/16 19:40:44 Done.
4540
4541
4498 void Parser::ParseClassMemberDefinition(ClassDesc* members, 4542 void Parser::ParseClassMemberDefinition(ClassDesc* members,
4499 TokenPosition metadata_pos) { 4543 TokenPosition metadata_pos) {
4500 TRACE_PARSER("ParseClassMemberDefinition"); 4544 TRACE_PARSER("ParseClassMemberDefinition");
4501 MemberDesc member; 4545 MemberDesc member;
4502 current_member_ = &member; 4546 current_member_ = &member;
4503 member.metadata_pos = metadata_pos; 4547 member.metadata_pos = metadata_pos;
4504 member.decl_begin_pos = TokenPos(); 4548 member.decl_begin_pos = TokenPos();
4505 if ((CurrentToken() == Token::kEXTERNAL) && 4549 if ((CurrentToken() == Token::kEXTERNAL) &&
4506 (LookaheadToken(1) != Token::kLPAREN)) { 4550 (LookaheadToken(1) != Token::kLPAREN)) {
4507 ConsumeToken(); 4551 ConsumeToken();
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
4968 ParseClassMemberDefinition(&members, metadata_pos); 5012 ParseClassMemberDefinition(&members, metadata_pos);
4969 } 5013 }
4970 ExpectToken(Token::kRBRACE); 5014 ExpectToken(Token::kRBRACE);
4971 5015
4972 if (cls.LookupTypeParameter(class_name) != TypeParameter::null()) { 5016 if (cls.LookupTypeParameter(class_name) != TypeParameter::null()) {
4973 ReportError(class_pos, "class name conflicts with type parameter '%s'", 5017 ReportError(class_pos, "class name conflicts with type parameter '%s'",
4974 class_name.ToCString()); 5018 class_name.ToCString());
4975 } 5019 }
4976 CheckConstructors(&members); 5020 CheckConstructors(&members);
4977 5021
5022 // Check that our constructors don't try to reinitialize an initialized
5023 // final variable.
5024 CheckFinalInitializationConflicts(&members);
5025
4978 // Need to compute this here since MakeArray() will clear the 5026 // Need to compute this here since MakeArray() will clear the
4979 // functions array in members. 5027 // functions array in members.
4980 const bool need_implicit_constructor = 5028 const bool need_implicit_constructor =
4981 !members.has_constructor() && !cls.is_patch(); 5029 !members.has_constructor() && !cls.is_patch();
4982 5030
4983 cls.AddFields(members.fields()); 5031 cls.AddFields(members.fields());
4984 5032
4985 // Creating a new array for functions marks the class as parsed. 5033 // Creating a new array for functions marks the class as parsed.
4986 Array& array = Array::Handle(Z, members.MakeFunctionsArray()); 5034 Array& array = Array::Handle(Z, members.MakeFunctionsArray());
4987 cls.SetFunctions(array); 5035 cls.SetFunctions(array);
(...skipping 10326 matching lines...) Expand 10 before | Expand all | Expand 10 after
15314 TokenPosition* start, 15362 TokenPosition* start,
15315 TokenPosition* end) { 15363 TokenPosition* end) {
15316 UNREACHABLE(); 15364 UNREACHABLE();
15317 return false; 15365 return false;
15318 } 15366 }
15319 15367
15320 15368
15321 } // namespace dart 15369 } // namespace dart
15322 15370
15323 #endif // DART_PRECOMPILED_RUNTIME 15371 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698