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

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

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

Powered by Google App Engine
This is Rietveld 408576698