OLD | NEW |
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 Loading... |
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 Loading... |
5249 AddFormalParamsToFunction(¶ms, ctor); | 5258 AddFormalParamsToFunction(¶ms, 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 Loading... |
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 |
OLD | NEW |