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

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: Added test, addressed 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 =
3026 String::ZoneHandle(initialized_field->name());
3027 const String& field_name = String::ZoneHandle(field->name());
3028 if (initialized_name.Equals(field_name) && field->IsFinalAndInitialized()) {
3029 ReportError(init_pos, "final field '%s' is already initialized.",
3030 field_name.ToCString());
3031 }
3032
3024 if (initialized_field->raw() == field->raw()) { 3033 if (initialized_field->raw() == field->raw()) {
3025 // This final field has been initialized by an inlined 3034 // This final field has been initialized by an inlined
3026 // initializer expression. This is a runtime error. 3035 // initializer expression. This is a runtime error.
3027 // Throw a NoSuchMethodError for the missing setter. 3036 // Throw a NoSuchMethodError for the missing setter.
3028 ASSERT(field->is_final()); 3037 ASSERT(field->is_final());
3029 3038
3030 // Build a call to NoSuchMethodError::_throwNew( 3039 // Build a call to NoSuchMethodError::_throwNew(
3031 // Object receiver, 3040 // Object receiver,
3032 // String memberName, 3041 // String memberName,
3033 // int invocation_type, 3042 // int invocation_type,
(...skipping 1454 matching lines...) Expand 10 before | Expand all | Expand 10 after
4488 MemberDesc* existing_member = &members->members()[i]; 4497 MemberDesc* existing_member = &members->members()[i];
4489 if (name.Equals(*existing_member->DictName())) { 4498 if (name.Equals(*existing_member->DictName())) {
4490 ReportError( 4499 ReportError(
4491 member->name_pos, "%s '%s' conflicts with previously declared %s", 4500 member->name_pos, "%s '%s' conflicts with previously declared %s",
4492 member->ToCString(), name.ToCString(), existing_member->ToCString()); 4501 member->ToCString(), name.ToCString(), existing_member->ToCString());
4493 } 4502 }
4494 } 4503 }
4495 } 4504 }
4496 4505
4497 4506
4507 void Parser::CheckMemberAlreadyInitializedConflicts(ClassDesc* members,
4508 MemberDesc* member) {
4509 if (!member->IsConstructor()) {
4510 return;
4511 }
4512 ParamList* params = &member->params;
4513 if (!params->has_field_initializer) {
4514 return;
4515 }
4516 const ZoneGrowableArray<ParamDesc>& parameters = *params->parameters;
4517 for (intptr_t p = 0; p < parameters.length(); p++) {
4518 const ParamDesc& current_param = parameters[p];
4519 if (!current_param.is_field_initializer) {
4520 continue;
4521 }
4522 const String& name = *current_param.name;
4523 for (intptr_t i = 0; i < members->members().length(); i++) {
4524 MemberDesc* existing_member = &members->members()[i];
4525 if (existing_member->has_final &&
4526 name.Equals(*existing_member->DictName()) &&
4527 (existing_member->field_ != NULL) &&
4528 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.
4529 ReportError(current_param.name_pos,
4530 "final field '%s' is already initialized.",
4531 existing_member->DictName()->ToCString());
4532 }
4533 }
4534 }
4535 }
4536
4537
4498 void Parser::ParseClassMemberDefinition(ClassDesc* members, 4538 void Parser::ParseClassMemberDefinition(ClassDesc* members,
4499 TokenPosition metadata_pos) { 4539 TokenPosition metadata_pos) {
4500 TRACE_PARSER("ParseClassMemberDefinition"); 4540 TRACE_PARSER("ParseClassMemberDefinition");
4501 MemberDesc member; 4541 MemberDesc member;
4502 current_member_ = &member; 4542 current_member_ = &member;
4503 member.metadata_pos = metadata_pos; 4543 member.metadata_pos = metadata_pos;
4504 member.decl_begin_pos = TokenPos(); 4544 member.decl_begin_pos = TokenPos();
4505 if ((CurrentToken() == Token::kEXTERNAL) && 4545 if ((CurrentToken() == Token::kEXTERNAL) &&
4506 (LookaheadToken(1) != Token::kLPAREN)) { 4546 (LookaheadToken(1) != Token::kLPAREN)) {
4507 ConsumeToken(); 4547 ConsumeToken();
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
4700 AbstractType& type = AbstractType::ZoneHandle(Z, member.type->raw()); 4740 AbstractType& type = AbstractType::ZoneHandle(Z, member.type->raw());
4701 ResolveType(&type); 4741 ResolveType(&type);
4702 member.type = &type; 4742 member.type = &type;
4703 } 4743 }
4704 ParseFieldDefinition(members, &member); 4744 ParseFieldDefinition(members, &member);
4705 } else { 4745 } else {
4706 UnexpectedToken(); 4746 UnexpectedToken();
4707 } 4747 }
4708 current_member_ = NULL; 4748 current_member_ = NULL;
4709 CheckMemberNameConflict(members, &member); 4749 CheckMemberNameConflict(members, &member);
4750 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
4710 members->AddMember(member); 4751 members->AddMember(member);
4711 } 4752 }
4712 4753
4713 4754
4714 void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes, 4755 void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes,
4715 const Object& tl_owner, 4756 const Object& tl_owner,
4716 TokenPosition metadata_pos) { 4757 TokenPosition metadata_pos) {
4717 TRACE_PARSER("ParseEnumDeclaration"); 4758 TRACE_PARSER("ParseEnumDeclaration");
4718 const TokenPosition declaration_pos = 4759 const TokenPosition declaration_pos =
4719 (metadata_pos.IsReal()) ? metadata_pos : TokenPos(); 4760 (metadata_pos.IsReal()) ? metadata_pos : TokenPos();
(...skipping 10594 matching lines...) Expand 10 before | Expand all | Expand 10 after
15314 TokenPosition* start, 15355 TokenPosition* start,
15315 TokenPosition* end) { 15356 TokenPosition* end) {
15316 UNREACHABLE(); 15357 UNREACHABLE();
15317 return false; 15358 return false;
15318 } 15359 }
15319 15360
15320 15361
15321 } // namespace dart 15362 } // namespace dart
15322 15363
15323 #endif // DART_PRECOMPILED_RUNTIME 15364 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698