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

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

Issue 2953843003: Reintroducing parser changes to cause compile-time errors when trying to reinitialize a final field… (Closed)
Patch Set: 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-dartium.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 3004 matching lines...) Expand 10 before | Expand all | Expand 10 after
3015 3015
3016 3016
3017 AstNode* Parser::CheckDuplicateFieldInit( 3017 AstNode* Parser::CheckDuplicateFieldInit(
3018 TokenPosition init_pos, 3018 TokenPosition init_pos,
3019 GrowableArray<Field*>* initialized_fields, 3019 GrowableArray<Field*>* initialized_fields,
3020 AstNode* instance, 3020 AstNode* instance,
3021 Field* field, 3021 Field* field,
3022 AstNode* init_value) { 3022 AstNode* init_value) {
3023 ASSERT(!field->is_static()); 3023 ASSERT(!field->is_static());
3024 AstNode* result = NULL; 3024 AstNode* result = NULL;
3025 const String& field_name = String::Handle(field->name());
3026 String& initialized_name = String::Handle(Z);
3025 3027
3026 // The initializer_list is divided into two sections. The sections 3028 // The initializer_list is divided into two sections. The sections
3027 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...] 3029 // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...]
3028 // The first fields f0 .. fn are final fields of the class that 3030 // The first fields f0 .. fn are final fields of the class that
3029 // have an initializer expression inlined in the class declaration. 3031 // have an initializer expression inlined in the class declaration.
3030 // The remaining fields are those initialized by the constructor's 3032 // The remaining fields are those initialized by the constructor's
3031 // initializing formals and initializer list 3033 // initializing formals and initializer list
3032 int initializer_idx = 0; 3034 int initializer_idx = 0;
3033 while (initializer_idx < initialized_fields->length()) { 3035 while (initializer_idx < initialized_fields->length()) {
3034 Field* initialized_field = (*initialized_fields)[initializer_idx]; 3036 Field* initialized_field = (*initialized_fields)[initializer_idx];
3035 initializer_idx++; 3037 initializer_idx++;
3036 if (initialized_field == NULL) { 3038 if (initialized_field == NULL) {
3037 break; 3039 break;
3038 } 3040 }
3041
3042 initialized_name ^= initialized_field->name();
3043 if (initialized_name.Equals(field_name) && field->has_initializer()) {
3044 ReportError(init_pos, "final field '%s' is already initialized.",
3045 field_name.ToCString());
3046 }
3047
3039 if (initialized_field->raw() == field->raw()) { 3048 if (initialized_field->raw() == field->raw()) {
3040 // This final field has been initialized by an inlined 3049 // This final field has been initialized by an inlined
3041 // initializer expression. This is a runtime error. 3050 // initializer expression. This is a runtime error.
3042 // Throw a NoSuchMethodError for the missing setter. 3051 // Throw a NoSuchMethodError for the missing setter.
3043 ASSERT(field->is_final()); 3052 ASSERT(field->is_final());
3044 3053
3045 // Build a call to NoSuchMethodError::_throwNew( 3054 // Build a call to NoSuchMethodError::_throwNew(
3046 // Object receiver, 3055 // Object receiver,
3047 // String memberName, 3056 // String memberName,
3048 // int invocation_type, 3057 // int invocation_type,
(...skipping 2200 matching lines...) Expand 10 before | Expand all | Expand 10 after
5249 AddFormalParamsToFunction(&params, ctor); 5258 AddFormalParamsToFunction(&params, ctor);
5250 ctor.set_result_type(Object::dynamic_type()); 5259 ctor.set_result_type(Object::dynamic_type());
5251 ResolveSignature(ctor); 5260 ResolveSignature(ctor);
5252 // The body of the constructor cannot modify the type of the constructed 5261 // The body of the constructor cannot modify the type of the constructed
5253 // instance, which is passed in as the receiver. 5262 // instance, which is passed in as the receiver.
5254 ctor.set_result_type(*receiver_type); 5263 ctor.set_result_type(*receiver_type);
5255 cls.AddFunction(ctor); 5264 cls.AddFunction(ctor);
5256 } 5265 }
5257 5266
5258 5267
5268 void Parser::CheckFinalInitializationConflicts(const ClassDesc* class_desc,
5269 const MemberDesc* member) {
5270 const ParamList* params = &member->params;
5271 if (!params->has_field_initializer) {
5272 return;
5273 }
5274
5275 const ZoneGrowableArray<ParamDesc>& parameters = *params->parameters;
5276 const GrowableArray<const Field*>& fields = class_desc->fields();
5277 String& field_name = String::Handle(Z);
5278
5279 for (intptr_t p = 0; p < parameters.length(); p++) {
5280 const ParamDesc& current_param = parameters[p];
5281 if (!current_param.is_field_initializer) {
5282 continue;
5283 }
5284
5285 const String& param_name = *current_param.name;
5286 for (intptr_t i = 0; i < fields.length(); i++) {
5287 const Field* current_field = fields.At(i);
5288 if (!current_field->is_final() || !current_field->has_initializer()) {
5289 continue;
5290 }
5291
5292 field_name ^= current_field->name();
5293 if (param_name.Equals(field_name)) {
5294 ReportError(current_param.name_pos,
5295 "final field '%s' is already initialized.",
5296 param_name.ToCString());
5297 }
5298 }
5299 }
5300 }
5301
5302
5259 // Check for cycles in constructor redirection. 5303 // Check for cycles in constructor redirection.
5260 void Parser::CheckConstructors(ClassDesc* class_desc) { 5304 void Parser::CheckConstructors(ClassDesc* class_desc) {
5261 // Check for cycles in constructor redirection. 5305 // Check for cycles in constructor redirection.
5262 const GrowableArray<MemberDesc>& members = class_desc->members(); 5306 const GrowableArray<MemberDesc>& members = class_desc->members();
5263 for (int i = 0; i < members.length(); i++) { 5307 for (int i = 0; i < members.length(); i++) {
5264 MemberDesc* member = &members[i]; 5308 MemberDesc* member = &members[i];
5309 if (member->IsConstructor()) {
5310 // Check that our constructors don't try and reinitialize an initialized
5311 // final variable.
5312 CheckFinalInitializationConflicts(class_desc, member);
5313 }
5265 if (member->redirect_name == NULL) { 5314 if (member->redirect_name == NULL) {
5266 continue; 5315 continue;
5267 } 5316 }
5268 GrowableArray<MemberDesc*> ctors; 5317 GrowableArray<MemberDesc*> ctors;
5269 while ((member != NULL) && (member->redirect_name != NULL)) { 5318 while ((member != NULL) && (member->redirect_name != NULL)) {
5270 ASSERT(member->IsConstructor()); 5319 ASSERT(member->IsConstructor());
5271 // Check whether we have already seen this member. 5320 // Check whether we have already seen this member.
5272 for (int i = 0; i < ctors.length(); i++) { 5321 for (int i = 0; i < ctors.length(); i++) {
5273 if (ctors[i] == member) { 5322 if (ctors[i] == member) {
5274 ReportError(member->name_pos, 5323 ReportError(member->name_pos,
(...skipping 10072 matching lines...) Expand 10 before | Expand all | Expand 10 after
15347 TokenPosition* start, 15396 TokenPosition* start,
15348 TokenPosition* end) { 15397 TokenPosition* end) {
15349 UNREACHABLE(); 15398 UNREACHABLE();
15350 return false; 15399 return false;
15351 } 15400 }
15352 15401
15353 15402
15354 } // namespace dart 15403 } // namespace dart
15355 15404
15356 #endif // DART_PRECOMPILED_RUNTIME 15405 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-dartium.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698