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

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 final comment 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/final_attempt_reinitialization_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2989 matching lines...) Expand 10 before | Expand all | Expand 10 after
3000 3000
3001 3001
3002 AstNode* Parser::CheckDuplicateFieldInit( 3002 AstNode* Parser::CheckDuplicateFieldInit(
3003 TokenPosition init_pos, 3003 TokenPosition init_pos,
3004 GrowableArray<Field*>* initialized_fields, 3004 GrowableArray<Field*>* initialized_fields,
3005 AstNode* instance, 3005 AstNode* instance,
3006 Field* field, 3006 Field* field,
3007 AstNode* init_value) { 3007 AstNode* init_value) {
3008 ASSERT(!field->is_static()); 3008 ASSERT(!field->is_static());
3009 AstNode* result = NULL; 3009 AstNode* result = NULL;
3010 const String& field_name = String::Handle(field->name());
3011 String& initialized_name = String::Handle(Z);
3010 3012
3011 // The initializer_list is divided into two sections. The sections 3013 // The initializer_list is divided into two sections. The sections
3012 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] 3014 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...]
3013 // The first fields f0 .. fn are final fields of the class that 3015 // The first fields f0 .. fn are final fields of the class that
3014 // have an initializer expression inlined in the class declaration. 3016 // have an initializer expression inlined in the class declaration.
3015 // The remaining fields are those initialized by the constructor's 3017 // The remaining fields are those initialized by the constructor's
3016 // initializing formals and initializer list 3018 // initializing formals and initializer list
3017 int initializer_idx = 0; 3019 int initializer_idx = 0;
3018 while (initializer_idx < initialized_fields->length()) { 3020 while (initializer_idx < initialized_fields->length()) {
3019 Field* initialized_field = (*initialized_fields)[initializer_idx]; 3021 Field* initialized_field = (*initialized_fields)[initializer_idx];
3020 initializer_idx++; 3022 initializer_idx++;
3021 if (initialized_field == NULL) { 3023 if (initialized_field == NULL) {
3022 break; 3024 break;
3023 } 3025 }
3026
3027 initialized_name ^= initialized_field->name();
3028 if (initialized_name.Equals(field_name) && field->has_initializer()) {
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 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after
5234 AddFormalParamsToFunction(&params, ctor); 5243 AddFormalParamsToFunction(&params, ctor);
5235 ctor.set_result_type(Object::dynamic_type()); 5244 ctor.set_result_type(Object::dynamic_type());
5236 ResolveSignature(ctor); 5245 ResolveSignature(ctor);
5237 // The body of the constructor cannot modify the type of the constructed 5246 // The body of the constructor cannot modify the type of the constructed
5238 // instance, which is passed in as the receiver. 5247 // instance, which is passed in as the receiver.
5239 ctor.set_result_type(*receiver_type); 5248 ctor.set_result_type(*receiver_type);
5240 cls.AddFunction(ctor); 5249 cls.AddFunction(ctor);
5241 } 5250 }
5242 5251
5243 5252
5253 void Parser::CheckFinalInitializationConflicts(const ClassDesc* class_desc,
5254 const MemberDesc* member) {
5255 const ParamList* params = &member->params;
5256 if (!params->has_field_initializer) {
5257 return;
5258 }
5259
5260 const ZoneGrowableArray<ParamDesc>& parameters = *params->parameters;
5261 const GrowableArray<const Field*>& fields = class_desc->fields();
5262 String& field_name = String::Handle(Z);
5263
5264 for (intptr_t p = 0; p < parameters.length(); p++) {
5265 const ParamDesc& current_param = parameters[p];
5266 if (!current_param.is_field_initializer) {
5267 continue;
5268 }
5269
5270 const String& param_name = *current_param.name;
5271 for (intptr_t i = 0; i < fields.length(); i++) {
5272 const Field* current_field = fields.At(i);
5273 if (!current_field->is_final() || !current_field->has_initializer()) {
5274 continue;
5275 }
5276
5277 field_name ^= current_field->name();
5278 if (param_name.Equals(field_name)) {
5279 ReportError(current_param.name_pos,
5280 "final field '%s' is already initialized.",
5281 param_name.ToCString());
5282 }
5283 }
5284 }
5285 }
5286
5287
5244 // Check for cycles in constructor redirection. 5288 // Check for cycles in constructor redirection.
5245 void Parser::CheckConstructors(ClassDesc* class_desc) { 5289 void Parser::CheckConstructors(ClassDesc* class_desc) {
5246 // Check for cycles in constructor redirection. 5290 // Check for cycles in constructor redirection.
5247 const GrowableArray<MemberDesc>& members = class_desc->members(); 5291 const GrowableArray<MemberDesc>& members = class_desc->members();
5248 for (int i = 0; i < members.length(); i++) { 5292 for (int i = 0; i < members.length(); i++) {
5249 MemberDesc* member = &members[i]; 5293 MemberDesc* member = &members[i];
5294 if (member->IsConstructor()) {
5295 // Check that our constructors don't try and reinitialize an initialized
5296 // final variable.
5297 CheckFinalInitializationConflicts(class_desc, member);
5298 }
5250 if (member->redirect_name == NULL) { 5299 if (member->redirect_name == NULL) {
5251 continue; 5300 continue;
5252 } 5301 }
5253 GrowableArray<MemberDesc*> ctors; 5302 GrowableArray<MemberDesc*> ctors;
5254 while ((member != NULL) && (member->redirect_name != NULL)) { 5303 while ((member != NULL) && (member->redirect_name != NULL)) {
5255 ASSERT(member->IsConstructor()); 5304 ASSERT(member->IsConstructor());
5256 // Check whether we have already seen this member. 5305 // Check whether we have already seen this member.
5257 for (int i = 0; i < ctors.length(); i++) { 5306 for (int i = 0; i < ctors.length(); i++) {
5258 if (ctors[i] == member) { 5307 if (ctors[i] == member) {
5259 ReportError(member->name_pos, 5308 ReportError(member->name_pos,
(...skipping 10054 matching lines...) Expand 10 before | Expand all | Expand 10 after
15314 TokenPosition* start, 15363 TokenPosition* start,
15315 TokenPosition* end) { 15364 TokenPosition* end) {
15316 UNREACHABLE(); 15365 UNREACHABLE();
15317 return false; 15366 return false;
15318 } 15367 }
15319 15368
15320 15369
15321 } // namespace dart 15370 } // namespace dart
15322 15371
15323 #endif // DART_PRECOMPILED_RUNTIME 15372 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/final_attempt_reinitialization_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698