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 2988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
5233 AddFormalParamsToFunction(¶ms, ctor); | 5242 AddFormalParamsToFunction(¶ms, 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 Loading... |
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 |
OLD | NEW |