OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
13 #include "vm/symbols.h" | 13 #include "vm/symbols.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
| 17 DEFINE_FLAG(bool, error_on_bad_override, false, |
| 18 "Report error for bad overrides."); |
17 DEFINE_FLAG(bool, error_on_malformed_type, false, | 19 DEFINE_FLAG(bool, error_on_malformed_type, false, |
18 "Report error for malformed types."); | 20 "Report error for malformed types."); |
19 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); | 21 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
20 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 22 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
21 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 23 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
22 DECLARE_FLAG(bool, enable_type_checks); | 24 DECLARE_FLAG(bool, enable_type_checks); |
23 DECLARE_FLAG(bool, use_cha); | 25 DECLARE_FLAG(bool, use_cha); |
24 | 26 |
25 bool ClassFinalizer::AllClassesFinalized() { | 27 bool ClassFinalizer::AllClassesFinalized() { |
26 ObjectStore* object_store = Isolate::Current()->object_store(); | 28 ObjectStore* object_store = Isolate::Current()->object_store(); |
(...skipping 16 matching lines...) Expand all Loading... |
43 // Switch all functions' code to unoptimized. | 45 // Switch all functions' code to unoptimized. |
44 const ClassTable& class_table = *Isolate::Current()->class_table(); | 46 const ClassTable& class_table = *Isolate::Current()->class_table(); |
45 Class& cls = Class::Handle(); | 47 Class& cls = Class::Handle(); |
46 Array& array = Array::Handle(); | 48 Array& array = Array::Handle(); |
47 Function& function = Function::Handle(); | 49 Function& function = Function::Handle(); |
48 for (intptr_t i = 0; i < added_subclasses_to_cids.length(); i++) { | 50 for (intptr_t i = 0; i < added_subclasses_to_cids.length(); i++) { |
49 intptr_t cid = added_subclasses_to_cids[i]; | 51 intptr_t cid = added_subclasses_to_cids[i]; |
50 cls = class_table.At(cid); | 52 cls = class_table.At(cid); |
51 ASSERT(!cls.IsNull()); | 53 ASSERT(!cls.IsNull()); |
52 array = cls.functions(); | 54 array = cls.functions(); |
53 intptr_t num_functions = array.IsNull() ? 0 : array.Length(); | 55 const intptr_t num_functions = array.IsNull() ? 0 : array.Length(); |
54 for (intptr_t f = 0; f < num_functions; f++) { | 56 for (intptr_t f = 0; f < num_functions; f++) { |
55 function ^= array.At(f); | 57 function ^= array.At(f); |
56 ASSERT(!function.IsNull()); | 58 ASSERT(!function.IsNull()); |
57 if (function.HasOptimizedCode()) { | 59 if (function.HasOptimizedCode()) { |
58 function.SwitchToUnoptimizedCode(); | 60 function.SwitchToUnoptimizedCode(); |
59 } | 61 } |
60 } | 62 } |
61 } | 63 } |
62 } | 64 } |
63 | 65 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); | 135 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
134 class_array = object_store->pending_classes(); | 136 class_array = object_store->pending_classes(); |
135 ASSERT(!class_array.IsNull()); | 137 ASSERT(!class_array.IsNull()); |
136 // Collect superclasses that were already finalized before this run of | 138 // Collect superclasses that were already finalized before this run of |
137 // finalization. | 139 // finalization. |
138 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); | 140 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); |
139 Class& cls = Class::Handle(); | 141 Class& cls = Class::Handle(); |
140 // First resolve all superclasses. | 142 // First resolve all superclasses. |
141 for (intptr_t i = 0; i < class_array.Length(); i++) { | 143 for (intptr_t i = 0; i < class_array.Length(); i++) { |
142 cls ^= class_array.At(i); | 144 cls ^= class_array.At(i); |
143 if (FLAG_trace_class_finalization) { | |
144 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); | |
145 } | |
146 GrowableArray<intptr_t> visited_interfaces; | 145 GrowableArray<intptr_t> visited_interfaces; |
147 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
148 } | 147 } |
149 // Finalize all classes. | 148 // Finalize all classes. |
150 for (intptr_t i = 0; i < class_array.Length(); i++) { | 149 for (intptr_t i = 0; i < class_array.Length(); i++) { |
151 cls ^= class_array.At(i); | 150 cls ^= class_array.At(i); |
152 FinalizeTypesInClass(cls); | 151 FinalizeTypesInClass(cls); |
153 } | 152 } |
154 if (FLAG_print_classes) { | 153 if (FLAG_print_classes) { |
155 for (intptr_t i = 0; i < class_array.Length(); i++) { | 154 for (intptr_t i = 0; i < class_array.Length(); i++) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 const Class& cls, | 300 const Class& cls, |
302 const Function& factory, | 301 const Function& factory, |
303 const GrowableObjectArray& visited_factories) { | 302 const GrowableObjectArray& visited_factories) { |
304 ASSERT(factory.IsRedirectingFactory()); | 303 ASSERT(factory.IsRedirectingFactory()); |
305 | 304 |
306 // Check for redirection cycle. | 305 // Check for redirection cycle. |
307 for (int i = 0; i < visited_factories.Length(); i++) { | 306 for (int i = 0; i < visited_factories.Length(); i++) { |
308 if (visited_factories.At(i) == factory.raw()) { | 307 if (visited_factories.At(i) == factory.raw()) { |
309 // A redirection cycle is reported as a compile-time error. | 308 // A redirection cycle is reported as a compile-time error. |
310 const Script& script = Script::Handle(cls.script()); | 309 const Script& script = Script::Handle(cls.script()); |
311 ReportError(script, factory.token_pos(), | 310 ReportError(Error::Handle(), // No previous error. |
| 311 script, factory.token_pos(), |
312 "factory '%s' illegally redirects to itself", | 312 "factory '%s' illegally redirects to itself", |
313 String::Handle(factory.name()).ToCString()); | 313 String::Handle(factory.name()).ToCString()); |
314 } | 314 } |
315 } | 315 } |
316 visited_factories.Add(factory); | 316 visited_factories.Add(factory); |
317 | 317 |
318 // Check if target is already resolved. | 318 // Check if target is already resolved. |
319 Type& type = Type::Handle(factory.RedirectionType()); | 319 Type& type = Type::Handle(factory.RedirectionType()); |
320 Function& target = Function::Handle(factory.RedirectionTarget()); | 320 Function& target = Function::Handle(factory.RedirectionTarget()); |
321 if (type.IsMalformed()) { | 321 if (type.IsMalformed()) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 cls, | 375 cls, |
376 factory.token_pos(), | 376 factory.token_pos(), |
377 "class '%s' has no constructor or factory named '%s'", | 377 "class '%s' has no constructor or factory named '%s'", |
378 target_class_name.ToCString(), | 378 target_class_name.ToCString(), |
379 user_visible_target_name.ToCString()); | 379 user_visible_target_name.ToCString()); |
380 factory.SetRedirectionType(type); | 380 factory.SetRedirectionType(type); |
381 ASSERT(factory.RedirectionTarget() == Function::null()); | 381 ASSERT(factory.RedirectionTarget() == Function::null()); |
382 return; | 382 return; |
383 } | 383 } |
384 | 384 |
385 // Verify that the target is compatible with the redirecting factory. | 385 if (FLAG_error_on_bad_override) { |
386 if (!target.HasCompatibleParametersWith(factory)) { | 386 // Verify that the target is compatible with the redirecting factory. |
387 type = NewFinalizedMalformedType( | 387 Error& error = Error::Handle(); |
388 Error::Handle(), // No previous error. | 388 if (!target.HasCompatibleParametersWith(factory, &error)) { |
389 cls, | 389 type = NewFinalizedMalformedType( |
390 factory.token_pos(), | 390 error, target_class, target.token_pos(), |
391 "constructor '%s' has incompatible parameters with " | 391 "constructor '%s' has incompatible parameters with " |
392 "redirecting factory '%s'", | 392 "redirecting factory '%s'", |
393 String::Handle(target.name()).ToCString(), | 393 String::Handle(target.name()).ToCString(), |
394 String::Handle(factory.name()).ToCString()); | 394 String::Handle(factory.name()).ToCString()); |
395 factory.SetRedirectionType(type); | 395 factory.SetRedirectionType(type); |
396 ASSERT(factory.RedirectionTarget() == Function::null()); | 396 ASSERT(factory.RedirectionTarget() == Function::null()); |
397 return; | 397 return; |
| 398 } |
398 } | 399 } |
399 | 400 |
400 // Verify that the target is const if the redirecting factory is const. | 401 // Verify that the target is const if the redirecting factory is const. |
401 if (factory.is_const() && !target.is_const()) { | 402 if (factory.is_const() && !target.is_const()) { |
402 const Script& script = Script::Handle(cls.script()); | 403 const Script& script = Script::Handle(target_class.script()); |
403 ReportError(script, factory.token_pos(), | 404 ReportError(Error::Handle(), // No previous error. |
| 405 script, target.token_pos(), |
404 "constructor '%s' must be const as required by redirecting" | 406 "constructor '%s' must be const as required by redirecting" |
405 "const factory '%s'", | 407 "const factory '%s'", |
406 String::Handle(target.name()).ToCString(), | 408 String::Handle(target.name()).ToCString(), |
407 String::Handle(factory.name()).ToCString()); | 409 String::Handle(factory.name()).ToCString()); |
408 } | 410 } |
409 | 411 |
410 // Update redirection data with resolved target. | 412 // Update redirection data with resolved target. |
411 factory.SetRedirectionTarget(target); | 413 factory.SetRedirectionTarget(target); |
412 // Not needed anymore. | 414 // Not needed anymore. |
413 factory.SetRedirectionIdentifier(Object::null_string()); | 415 factory.SetRedirectionIdentifier(Object::null_string()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 } | 494 } |
493 return; | 495 return; |
494 } | 496 } |
495 parameterized_type.set_type_class(type_class); | 497 parameterized_type.set_type_class(type_class); |
496 } | 498 } |
497 | 499 |
498 // Resolve type arguments, if any. | 500 // Resolve type arguments, if any. |
499 const AbstractTypeArguments& arguments = | 501 const AbstractTypeArguments& arguments = |
500 AbstractTypeArguments::Handle(type.arguments()); | 502 AbstractTypeArguments::Handle(type.arguments()); |
501 if (!arguments.IsNull()) { | 503 if (!arguments.IsNull()) { |
502 intptr_t num_arguments = arguments.Length(); | 504 const intptr_t num_arguments = arguments.Length(); |
503 AbstractType& type_argument = AbstractType::Handle(); | 505 AbstractType& type_argument = AbstractType::Handle(); |
504 for (intptr_t i = 0; i < num_arguments; i++) { | 506 for (intptr_t i = 0; i < num_arguments; i++) { |
505 type_argument = arguments.TypeAt(i); | 507 type_argument = arguments.TypeAt(i); |
506 ResolveType(cls, type_argument, finalization); | 508 ResolveType(cls, type_argument, finalization); |
507 } | 509 } |
508 } | 510 } |
509 } | 511 } |
510 | 512 |
511 | 513 |
512 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { | 514 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 if (!type_class.is_type_finalized()) { | 763 if (!type_class.is_type_finalized()) { |
762 FinalizeTypeParameters(type_class); | 764 FinalizeTypeParameters(type_class); |
763 ResolveUpperBounds(type_class); | 765 ResolveUpperBounds(type_class); |
764 } | 766 } |
765 | 767 |
766 // Finalize the current type arguments of the type, which are still the | 768 // Finalize the current type arguments of the type, which are still the |
767 // parsed type arguments. | 769 // parsed type arguments. |
768 AbstractTypeArguments& arguments = | 770 AbstractTypeArguments& arguments = |
769 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 771 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
770 if (!arguments.IsNull()) { | 772 if (!arguments.IsNull()) { |
771 intptr_t num_arguments = arguments.Length(); | 773 const intptr_t num_arguments = arguments.Length(); |
772 AbstractType& type_argument = AbstractType::Handle(); | 774 AbstractType& type_argument = AbstractType::Handle(); |
773 for (intptr_t i = 0; i < num_arguments; i++) { | 775 for (intptr_t i = 0; i < num_arguments; i++) { |
774 type_argument = arguments.TypeAt(i); | 776 type_argument = arguments.TypeAt(i); |
775 type_argument = FinalizeType(cls, type_argument, finalization); | 777 type_argument = FinalizeType(cls, type_argument, finalization); |
776 if (type_argument.IsMalformed()) { | 778 if (type_argument.IsMalformed()) { |
777 // Malformed type arguments are mapped to dynamic. | 779 // Malformed type arguments are mapped to dynamic. |
778 type_argument = Type::DynamicType(); | 780 type_argument = Type::DynamicType(); |
779 } | 781 } |
780 arguments.SetTypeAt(i, type_argument); | 782 arguments.SetTypeAt(i, type_argument); |
781 } | 783 } |
782 } | 784 } |
783 | 785 |
784 // The finalized type argument vector needs num_type_arguments types. | 786 // The finalized type argument vector needs num_type_arguments types. |
785 const intptr_t num_type_arguments = type_class.NumTypeArguments(); | 787 const intptr_t num_type_arguments = type_class.NumTypeArguments(); |
786 // The type class has num_type_parameters type parameters. | 788 // The type class has num_type_parameters type parameters. |
787 const intptr_t num_type_parameters = type_class.NumTypeParameters(); | 789 const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
788 | 790 |
789 // Initialize the type argument vector. | 791 // Initialize the type argument vector. |
790 // Check the number of parsed type arguments, if any. | 792 // Check the number of parsed type arguments, if any. |
791 // Specifying no type arguments indicates a raw type, which is not an error. | 793 // Specifying no type arguments indicates a raw type, which is not an error. |
792 // However, type parameter bounds are checked below, even for a raw type. | 794 // However, type parameter bounds are checked below, even for a raw type. |
793 if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { | 795 if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
794 // Wrong number of type arguments. The type is malformed. | 796 // Wrong number of type arguments. The type is malformed. |
795 if (FLAG_error_on_malformed_type) { | 797 if (FLAG_error_on_malformed_type) { |
796 const Script& script = Script::Handle(cls.script()); | 798 const Script& script = Script::Handle(cls.script()); |
797 const String& type_class_name = String::Handle(type_class.Name()); | 799 const String& type_class_name = String::Handle(type_class.Name()); |
798 ReportError(script, parameterized_type.token_pos(), | 800 ReportError(Error::Handle(), // No previous error. |
| 801 script, parameterized_type.token_pos(), |
799 "wrong number of type arguments for class '%s'", | 802 "wrong number of type arguments for class '%s'", |
800 type_class_name.ToCString()); | 803 type_class_name.ToCString()); |
801 } | 804 } |
802 // Make the type raw and continue without reporting any error. | 805 // Make the type raw and continue without reporting any error. |
803 // A static warning should have been reported. | 806 // A static warning should have been reported. |
804 arguments = AbstractTypeArguments::null(); | 807 arguments = AbstractTypeArguments::null(); |
805 parameterized_type.set_arguments(arguments); | 808 parameterized_type.set_arguments(arguments); |
806 } | 809 } |
807 // The full type argument vector consists of the type arguments of the | 810 // The full type argument vector consists of the type arguments of the |
808 // super types of type_class, which may be initialized from the parsed | 811 // super types of type_class, which may be initialized from the parsed |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 // class or in a subclass. | 1024 // class or in a subclass. |
1022 // - a static field, instance field, or static method (but not an instance | 1025 // - a static field, instance field, or static method (but not an instance |
1023 // method) having the same name as an instance member in a super class. | 1026 // method) having the same name as an instance member in a super class. |
1024 | 1027 |
1025 // Resolve type of fields and check for conflicts in super classes. | 1028 // Resolve type of fields and check for conflicts in super classes. |
1026 Array& array = Array::Handle(cls.fields()); | 1029 Array& array = Array::Handle(cls.fields()); |
1027 Field& field = Field::Handle(); | 1030 Field& field = Field::Handle(); |
1028 AbstractType& type = AbstractType::Handle(); | 1031 AbstractType& type = AbstractType::Handle(); |
1029 String& name = String::Handle(); | 1032 String& name = String::Handle(); |
1030 Class& super_class = Class::Handle(); | 1033 Class& super_class = Class::Handle(); |
1031 intptr_t num_fields = array.Length(); | 1034 const intptr_t num_fields = array.Length(); |
1032 for (intptr_t i = 0; i < num_fields; i++) { | 1035 for (intptr_t i = 0; i < num_fields; i++) { |
1033 field ^= array.At(i); | 1036 field ^= array.At(i); |
1034 type = field.type(); | 1037 type = field.type(); |
1035 ResolveType(cls, type, kCanonicalize); | 1038 ResolveType(cls, type, kCanonicalize); |
1036 type = FinalizeType(cls, type, kCanonicalize); | 1039 type = FinalizeType(cls, type, kCanonicalize); |
1037 field.set_type(type); | 1040 field.set_type(type); |
1038 name = field.name(); | 1041 name = field.name(); |
1039 if (field.is_static()) { | 1042 if (field.is_static()) { |
1040 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 1043 super_class = FindSuperOwnerOfInstanceMember(cls, name); |
1041 if (!super_class.IsNull()) { | 1044 if (!super_class.IsNull()) { |
1042 const String& class_name = String::Handle(cls.Name()); | 1045 const String& class_name = String::Handle(cls.Name()); |
1043 const String& super_class_name = String::Handle(super_class.Name()); | 1046 const String& super_class_name = String::Handle(super_class.Name()); |
1044 const Script& script = Script::Handle(cls.script()); | 1047 const Script& script = Script::Handle(cls.script()); |
1045 ReportError(script, field.token_pos(), | 1048 ReportError(Error::Handle(), // No previous error. |
| 1049 script, field.token_pos(), |
1046 "static field '%s' of class '%s' conflicts with " | 1050 "static field '%s' of class '%s' conflicts with " |
1047 "instance member '%s' of super class '%s'", | 1051 "instance member '%s' of super class '%s'", |
1048 name.ToCString(), | 1052 name.ToCString(), |
1049 class_name.ToCString(), | 1053 class_name.ToCString(), |
1050 name.ToCString(), | 1054 name.ToCString(), |
1051 super_class_name.ToCString()); | 1055 super_class_name.ToCString()); |
1052 } | 1056 } |
1053 } else { | 1057 } else { |
1054 // Instance field. Check whether the field overrides a method | 1058 // Instance field. Check whether the field overrides a method |
1055 // (but not getter). | 1059 // (but not getter). |
1056 super_class = FindSuperOwnerOfFunction(cls, name); | 1060 super_class = FindSuperOwnerOfFunction(cls, name); |
1057 if (!super_class.IsNull()) { | 1061 if (!super_class.IsNull()) { |
1058 const String& class_name = String::Handle(cls.Name()); | 1062 const String& class_name = String::Handle(cls.Name()); |
1059 const String& super_class_name = String::Handle(super_class.Name()); | 1063 const String& super_class_name = String::Handle(super_class.Name()); |
1060 const Script& script = Script::Handle(cls.script()); | 1064 const Script& script = Script::Handle(cls.script()); |
1061 ReportError(script, field.token_pos(), | 1065 ReportError(Error::Handle(), // No previous error. |
| 1066 script, field.token_pos(), |
1062 "field '%s' of class '%s' conflicts with method '%s' " | 1067 "field '%s' of class '%s' conflicts with method '%s' " |
1063 "of super class '%s'", | 1068 "of super class '%s'", |
1064 name.ToCString(), | 1069 name.ToCString(), |
1065 class_name.ToCString(), | 1070 class_name.ToCString(), |
1066 name.ToCString(), | 1071 name.ToCString(), |
1067 super_class_name.ToCString()); | 1072 super_class_name.ToCString()); |
1068 } | 1073 } |
1069 } | 1074 } |
1070 if ((FLAG_enable_type_checks || FLAG_error_on_malformed_type) && | 1075 if ((FLAG_enable_type_checks || FLAG_error_on_malformed_type) && |
1071 field.is_static() && field.is_const() && | 1076 field.is_static() && field.is_const() && |
1072 (field.value() != Object::null()) && | 1077 (field.value() != Object::null()) && |
1073 (field.value() != Object::sentinel().raw())) { | 1078 (field.value() != Object::sentinel().raw())) { |
1074 // The parser does not preset the value if the type is a type parameter or | 1079 // The parser does not preset the value if the type is a type parameter or |
1075 // is parameterized unless the value is null. | 1080 // is parameterized unless the value is null. |
1076 Error& malformed_error = Error::Handle(); | 1081 Error& malformed_error = Error::Handle(); |
1077 if (type.IsMalformed()) { | 1082 if (type.IsMalformed()) { |
1078 malformed_error = type.malformed_error(); | 1083 malformed_error = type.malformed_error(); |
1079 } else { | 1084 } else { |
1080 ASSERT(type.IsInstantiated()); | 1085 ASSERT(type.IsInstantiated()); |
1081 } | 1086 } |
1082 const Instance& const_value = Instance::Handle(field.value()); | 1087 const Instance& const_value = Instance::Handle(field.value()); |
1083 if (!malformed_error.IsNull() || | 1088 if (!malformed_error.IsNull() || |
1084 (!type.IsDynamicType() && | 1089 (!type.IsDynamicType() && |
1085 !const_value.IsInstanceOf(type, | 1090 !const_value.IsInstanceOf(type, |
1086 AbstractTypeArguments::Handle(), | 1091 AbstractTypeArguments::Handle(), |
1087 &malformed_error))) { | 1092 &malformed_error))) { |
1088 // If the failure is due to a malformed type error, display it instead. | 1093 const AbstractType& const_value_type = AbstractType::Handle( |
1089 if (!malformed_error.IsNull()) { | 1094 const_value.GetType()); |
1090 ReportError(malformed_error); | 1095 const String& const_value_type_name = String::Handle( |
1091 } else { | 1096 const_value_type.UserVisibleName()); |
1092 const AbstractType& const_value_type = AbstractType::Handle( | 1097 const String& type_name = String::Handle(type.UserVisibleName()); |
1093 const_value.GetType()); | 1098 const Script& script = Script::Handle(cls.script()); |
1094 const String& const_value_type_name = String::Handle( | 1099 ReportError(malformed_error, script, field.token_pos(), |
1095 const_value_type.UserVisibleName()); | 1100 "error initializing const field '%s': type '%s' is not a " |
1096 const String& type_name = String::Handle(type.UserVisibleName()); | 1101 "subtype of type '%s'", |
1097 const Script& script = Script::Handle(cls.script()); | 1102 name.ToCString(), |
1098 ReportError(script, field.token_pos(), | 1103 const_value_type_name.ToCString(), |
1099 "error initializing const field '%s': type '%s' is not a " | 1104 type_name.ToCString()); |
1100 "subtype of type '%s'", | |
1101 name.ToCString(), | |
1102 const_value_type_name.ToCString(), | |
1103 type_name.ToCString()); | |
1104 } | |
1105 } | 1105 } |
1106 } | 1106 } |
1107 } | 1107 } |
1108 // Collect interfaces, super interfaces, and super classes of this class. | 1108 // Collect interfaces, super interfaces, and super classes of this class. |
1109 const GrowableObjectArray& interfaces = | 1109 const GrowableObjectArray& interfaces = |
1110 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1110 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
1111 CollectInterfaces(cls, interfaces); | 1111 CollectInterfaces(cls, interfaces); |
1112 // Include superclasses in list of interfaces and super interfaces. | 1112 // Include superclasses in list of interfaces and super interfaces. |
1113 super_class = cls.SuperClass(); | 1113 super_class = cls.SuperClass(); |
1114 while (!super_class.IsNull()) { | 1114 while (!super_class.IsNull()) { |
1115 interfaces.Add(super_class); | 1115 interfaces.Add(super_class); |
1116 CollectInterfaces(super_class, interfaces); | 1116 CollectInterfaces(super_class, interfaces); |
1117 super_class = super_class.SuperClass(); | 1117 super_class = super_class.SuperClass(); |
1118 } | 1118 } |
1119 // Resolve function signatures and check for conflicts in super classes and | 1119 // Resolve function signatures and check for conflicts in super classes and |
1120 // interfaces. | 1120 // interfaces. |
1121 array = cls.functions(); | 1121 array = cls.functions(); |
1122 Function& function = Function::Handle(); | 1122 Function& function = Function::Handle(); |
1123 Function& overridden_function = Function::Handle(); | 1123 Function& overridden_function = Function::Handle(); |
1124 intptr_t num_functions = array.Length(); | 1124 const intptr_t num_functions = array.Length(); |
1125 String& function_name = String::Handle(); | 1125 String& function_name = String::Handle(); |
| 1126 Error& error = Error::Handle(); |
1126 for (intptr_t i = 0; i < num_functions; i++) { | 1127 for (intptr_t i = 0; i < num_functions; i++) { |
1127 function ^= array.At(i); | 1128 function ^= array.At(i); |
1128 ResolveAndFinalizeSignature(cls, function); | 1129 ResolveAndFinalizeSignature(cls, function); |
1129 function_name = function.name(); | 1130 function_name = function.name(); |
1130 if (function.is_static()) { | 1131 if (function.is_static()) { |
1131 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 1132 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); |
1132 if (!super_class.IsNull()) { | 1133 if (!super_class.IsNull()) { |
1133 const String& class_name = String::Handle(cls.Name()); | 1134 const String& class_name = String::Handle(cls.Name()); |
1134 const String& super_class_name = String::Handle(super_class.Name()); | 1135 const String& super_class_name = String::Handle(super_class.Name()); |
1135 const Script& script = Script::Handle(cls.script()); | 1136 const Script& script = Script::Handle(cls.script()); |
1136 ReportError(script, function.token_pos(), | 1137 ReportError(Error::Handle(), // No previous error. |
| 1138 script, function.token_pos(), |
1137 "static function '%s' of class '%s' conflicts with " | 1139 "static function '%s' of class '%s' conflicts with " |
1138 "instance member '%s' of super class '%s'", | 1140 "instance member '%s' of super class '%s'", |
1139 function_name.ToCString(), | 1141 function_name.ToCString(), |
1140 class_name.ToCString(), | 1142 class_name.ToCString(), |
1141 function_name.ToCString(), | 1143 function_name.ToCString(), |
1142 super_class_name.ToCString()); | 1144 super_class_name.ToCString()); |
1143 } | 1145 } |
1144 // The function may be a still unresolved redirecting factory. Do not yet | 1146 // The function may be a still unresolved redirecting factory. Do not yet |
1145 // try to resolve it in order to avoid cycles in class finalization. | 1147 // try to resolve it in order to avoid cycles in class finalization. |
1146 } else { | 1148 } else if (FLAG_error_on_bad_override && !function.IsConstructor()) { |
| 1149 // A constructor cannot override anything. |
1147 for (int i = 0; i < interfaces.Length(); i++) { | 1150 for (int i = 0; i < interfaces.Length(); i++) { |
1148 super_class ^= interfaces.At(i); | 1151 super_class ^= interfaces.At(i); |
1149 overridden_function = super_class.LookupDynamicFunction(function_name); | 1152 overridden_function = super_class.LookupDynamicFunction(function_name); |
1150 if (!overridden_function.IsNull() && | 1153 if (!overridden_function.IsNull() && |
1151 !function.HasCompatibleParametersWith(overridden_function)) { | 1154 !function.HasCompatibleParametersWith(overridden_function, |
| 1155 &error)) { |
1152 // Function types are purposely not checked for subtyping. | 1156 // Function types are purposely not checked for subtyping. |
1153 const String& class_name = String::Handle(cls.Name()); | 1157 const String& class_name = String::Handle(cls.Name()); |
1154 const String& super_class_name = String::Handle(super_class.Name()); | 1158 const String& super_class_name = String::Handle(super_class.Name()); |
1155 const Script& script = Script::Handle(cls.script()); | 1159 const Script& script = Script::Handle(cls.script()); |
1156 ReportError(script, function.token_pos(), | 1160 ReportError(error, script, function.token_pos(), |
1157 "class '%s' overrides function '%s' of super class '%s' " | 1161 "class '%s' overrides function '%s' of super class '%s' " |
1158 "with incompatible parameters", | 1162 "with incompatible parameters", |
1159 class_name.ToCString(), | 1163 class_name.ToCString(), |
1160 function_name.ToCString(), | 1164 function_name.ToCString(), |
1161 super_class_name.ToCString()); | 1165 super_class_name.ToCString()); |
1162 } | 1166 } |
1163 } | 1167 } |
1164 } | 1168 } |
1165 if (function.IsGetterFunction()) { | 1169 if (function.IsGetterFunction()) { |
1166 name = Field::NameFromGetter(function_name); | 1170 name = Field::NameFromGetter(function_name); |
1167 super_class = FindSuperOwnerOfFunction(cls, name); | 1171 super_class = FindSuperOwnerOfFunction(cls, name); |
1168 if (!super_class.IsNull()) { | 1172 if (!super_class.IsNull()) { |
1169 const String& class_name = String::Handle(cls.Name()); | 1173 const String& class_name = String::Handle(cls.Name()); |
1170 const String& super_class_name = String::Handle(super_class.Name()); | 1174 const String& super_class_name = String::Handle(super_class.Name()); |
1171 const Script& script = Script::Handle(cls.script()); | 1175 const Script& script = Script::Handle(cls.script()); |
1172 ReportError(script, function.token_pos(), | 1176 ReportError(Error::Handle(), // No previous error. |
| 1177 script, function.token_pos(), |
1173 "getter '%s' of class '%s' conflicts with " | 1178 "getter '%s' of class '%s' conflicts with " |
1174 "function '%s' of super class '%s'", | 1179 "function '%s' of super class '%s'", |
1175 name.ToCString(), | 1180 name.ToCString(), |
1176 class_name.ToCString(), | 1181 class_name.ToCString(), |
1177 name.ToCString(), | 1182 name.ToCString(), |
1178 super_class_name.ToCString()); | 1183 super_class_name.ToCString()); |
1179 } | 1184 } |
1180 } else if (!function.IsSetterFunction()) { | 1185 } else if (!function.IsSetterFunction()) { |
1181 // A function cannot conflict with a setter, since they cannot | 1186 // A function cannot conflict with a setter, since they cannot |
1182 // have the same name. Thus, we do not need to check setters. | 1187 // have the same name. Thus, we do not need to check setters. |
1183 name = Field::GetterName(function_name); | 1188 name = Field::GetterName(function_name); |
1184 super_class = FindSuperOwnerOfFunction(cls, name); | 1189 super_class = FindSuperOwnerOfFunction(cls, name); |
1185 if (!super_class.IsNull()) { | 1190 if (!super_class.IsNull()) { |
1186 const String& class_name = String::Handle(cls.Name()); | 1191 const String& class_name = String::Handle(cls.Name()); |
1187 const String& super_class_name = String::Handle(super_class.Name()); | 1192 const String& super_class_name = String::Handle(super_class.Name()); |
1188 const Script& script = Script::Handle(cls.script()); | 1193 const Script& script = Script::Handle(cls.script()); |
1189 ReportError(script, function.token_pos(), | 1194 ReportError(Error::Handle(), // No previous error. |
| 1195 script, function.token_pos(), |
1190 "function '%s' of class '%s' conflicts with " | 1196 "function '%s' of class '%s' conflicts with " |
1191 "getter '%s' of super class '%s'", | 1197 "getter '%s' of super class '%s'", |
1192 function_name.ToCString(), | 1198 function_name.ToCString(), |
1193 class_name.ToCString(), | 1199 class_name.ToCString(), |
1194 function_name.ToCString(), | 1200 function_name.ToCString(), |
1195 super_class_name.ToCString()); | 1201 super_class_name.ToCString()); |
1196 } | 1202 } |
1197 } | 1203 } |
1198 } | 1204 } |
1199 } | 1205 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 TypeArguments::Handle(super_class.type_parameters()); | 1239 TypeArguments::Handle(super_class.type_parameters()); |
1234 const TypeArguments& super_type_args = | 1240 const TypeArguments& super_type_args = |
1235 TypeArguments::Handle(TypeArguments::New(num_super_parameters)); | 1241 TypeArguments::Handle(TypeArguments::New(num_super_parameters)); |
1236 for (int i = 0; i < num_super_parameters; i++) { | 1242 for (int i = 0; i < num_super_parameters; i++) { |
1237 param ^= super_params.TypeAt(i); | 1243 param ^= super_params.TypeAt(i); |
1238 param_name = param.name(); | 1244 param_name = param.name(); |
1239 param_bound = param.bound(); | 1245 param_bound = param.bound(); |
1240 // TODO(hausner): handle type bounds. | 1246 // TODO(hausner): handle type bounds. |
1241 if (!param_bound.IsObjectType()) { | 1247 if (!param_bound.IsObjectType()) { |
1242 const Script& script = Script::Handle(mixapp_class.script()); | 1248 const Script& script = Script::Handle(mixapp_class.script()); |
1243 ReportError(script, param.token_pos(), | 1249 ReportError(Error::Handle(), // No previous error. |
| 1250 script, param.token_pos(), |
1244 "type parameter '%s': type bounds not yet" | 1251 "type parameter '%s': type bounds not yet" |
1245 " implemented for mixins\n", | 1252 " implemented for mixins\n", |
1246 param_name.ToCString()); | 1253 param_name.ToCString()); |
1247 } | 1254 } |
1248 param_name = String::Concat(param_name, Symbols::Backtick()); | 1255 param_name = String::Concat(param_name, Symbols::Backtick()); |
1249 param_name = Symbols::New(param_name); | 1256 param_name = Symbols::New(param_name); |
1250 cloned_param = TypeParameter::New(mixapp_class, | 1257 cloned_param = TypeParameter::New(mixapp_class, |
1251 cloned_index, | 1258 cloned_index, |
1252 param_name, | 1259 param_name, |
1253 param_bound, | 1260 param_bound, |
(...skipping 21 matching lines...) Expand all Loading... |
1275 const TypeArguments& interface_type_args = TypeArguments::Handle( | 1282 const TypeArguments& interface_type_args = TypeArguments::Handle( |
1276 TypeArguments::New(num_mixin_parameters)); | 1283 TypeArguments::New(num_mixin_parameters)); |
1277 for (int i = 0; i < num_mixin_parameters; i++) { | 1284 for (int i = 0; i < num_mixin_parameters; i++) { |
1278 param ^= mixin_params.TypeAt(i); | 1285 param ^= mixin_params.TypeAt(i); |
1279 param_name = param.name(); | 1286 param_name = param.name(); |
1280 param_bound = param.bound(); | 1287 param_bound = param.bound(); |
1281 | 1288 |
1282 // TODO(hausner): handle type bounds. | 1289 // TODO(hausner): handle type bounds. |
1283 if (!param_bound.IsObjectType()) { | 1290 if (!param_bound.IsObjectType()) { |
1284 const Script& script = Script::Handle(mixapp_class.script()); | 1291 const Script& script = Script::Handle(mixapp_class.script()); |
1285 ReportError(script, param.token_pos(), | 1292 ReportError(Error::Handle(), // No previous error. |
| 1293 script, param.token_pos(), |
1286 "type parameter '%s': type bounds not yet" | 1294 "type parameter '%s': type bounds not yet" |
1287 " implemented for mixins\n", | 1295 " implemented for mixins\n", |
1288 param_name.ToCString()); | 1296 param_name.ToCString()); |
1289 } | 1297 } |
1290 cloned_param = TypeParameter::New(mixapp_class, | 1298 cloned_param = TypeParameter::New(mixapp_class, |
1291 cloned_index, | 1299 cloned_index, |
1292 param_name, | 1300 param_name, |
1293 param_bound, | 1301 param_bound, |
1294 param.token_pos()); | 1302 param.token_pos()); |
1295 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | 1303 cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
(...skipping 30 matching lines...) Expand all Loading... |
1326 cls.token_pos()); | 1334 cls.token_pos()); |
1327 } | 1335 } |
1328 | 1336 |
1329 // Check that the super class of the mixin class is extending | 1337 // Check that the super class of the mixin class is extending |
1330 // class Object. | 1338 // class Object. |
1331 const AbstractType& mixin_super_type = | 1339 const AbstractType& mixin_super_type = |
1332 AbstractType::Handle(mixin_cls.super_type()); | 1340 AbstractType::Handle(mixin_cls.super_type()); |
1333 if (!mixin_super_type.IsObjectType()) { | 1341 if (!mixin_super_type.IsObjectType()) { |
1334 const Script& script = Script::Handle(cls.script()); | 1342 const Script& script = Script::Handle(cls.script()); |
1335 const String& class_name = String::Handle(mixin_cls.Name()); | 1343 const String& class_name = String::Handle(mixin_cls.Name()); |
1336 ReportError(script, cls.token_pos(), | 1344 ReportError(Error::Handle(), // No previous error. |
| 1345 script, cls.token_pos(), |
1337 "mixin class %s must extend class Object", | 1346 "mixin class %s must extend class Object", |
1338 class_name.ToCString()); | 1347 class_name.ToCString()); |
1339 } | 1348 } |
1340 | 1349 |
1341 // Copy type parameters to mixin application class. | 1350 // Copy type parameters to mixin application class. |
1342 CloneTypeParameters(cls); | 1351 CloneTypeParameters(cls); |
1343 | 1352 |
1344 if (FLAG_trace_class_finalization) { | 1353 if (FLAG_trace_class_finalization) { |
1345 OS::Print("Done applying mixin type '%s' to class %s %s extending '%s'\n", | 1354 OS::Print("Done applying mixin type '%s' to class %s %s extending '%s'\n", |
1346 String::Handle(mixin_type.Name()).ToCString(), | 1355 String::Handle(mixin_type.Name()).ToCString(), |
1347 String::Handle(cls.Name()).ToCString(), | 1356 String::Handle(cls.Name()).ToCString(), |
1348 TypeArguments::Handle(cls.type_parameters()).ToCString(), | 1357 TypeArguments::Handle(cls.type_parameters()).ToCString(), |
1349 AbstractType::Handle(cls.super_type()).ToCString()); | 1358 AbstractType::Handle(cls.super_type()).ToCString()); |
1350 } | 1359 } |
1351 } | 1360 } |
1352 | 1361 |
1353 | 1362 |
1354 void ClassFinalizer::CreateForwardingConstructors( | 1363 void ClassFinalizer::CreateForwardingConstructors( |
1355 const Class& mixin_app, | 1364 const Class& mixin_app, |
1356 const GrowableObjectArray& cloned_funcs) { | 1365 const GrowableObjectArray& cloned_funcs) { |
1357 const String& mixin_name = String::Handle(mixin_app.Name()); | 1366 const String& mixin_name = String::Handle(mixin_app.Name()); |
1358 const Class& super_class = Class::Handle(mixin_app.SuperClass()); | 1367 const Class& super_class = Class::Handle(mixin_app.SuperClass()); |
1359 const String& super_name = String::Handle(super_class.Name()); | 1368 const String& super_name = String::Handle(super_class.Name()); |
1360 const Type& dynamic_type = Type::Handle(Type::DynamicType()); | 1369 const Type& dynamic_type = Type::Handle(Type::DynamicType()); |
1361 const Array& functions = Array::Handle(super_class.functions()); | 1370 const Array& functions = Array::Handle(super_class.functions()); |
1362 intptr_t num_functions = functions.Length(); | 1371 const intptr_t num_functions = functions.Length(); |
1363 Function& func = Function::Handle(); | 1372 Function& func = Function::Handle(); |
1364 for (intptr_t i = 0; i < num_functions; i++) { | 1373 for (intptr_t i = 0; i < num_functions; i++) { |
1365 func ^= functions.At(i); | 1374 func ^= functions.At(i); |
1366 if (func.IsConstructor()) { | 1375 if (func.IsConstructor()) { |
1367 // Build constructor name from mixin application class name | 1376 // Build constructor name from mixin application class name |
1368 // and name of cloned super class constructor. | 1377 // and name of cloned super class constructor. |
1369 String& ctor_name = String::Handle(func.name()); | 1378 String& ctor_name = String::Handle(func.name()); |
1370 ctor_name = String::SubString(ctor_name, super_name.Length()); | 1379 ctor_name = String::SubString(ctor_name, super_name.Length()); |
1371 String& clone_name = | 1380 String& clone_name = |
1372 String::Handle(String::Concat(mixin_name, ctor_name)); | 1381 String::Handle(String::Concat(mixin_name, ctor_name)); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1430 ASSERT((functions = cls.functions(), functions.Length() == 0)); | 1439 ASSERT((functions = cls.functions(), functions.Length() == 0)); |
1431 // Now clone the functions from the mixin class. | 1440 // Now clone the functions from the mixin class. |
1432 functions = mixin_cls.functions(); | 1441 functions = mixin_cls.functions(); |
1433 const intptr_t num_functions = functions.Length(); | 1442 const intptr_t num_functions = functions.Length(); |
1434 for (int i = 0; i < num_functions; i++) { | 1443 for (int i = 0; i < num_functions; i++) { |
1435 func ^= functions.At(i); | 1444 func ^= functions.At(i); |
1436 if (func.IsConstructor()) { | 1445 if (func.IsConstructor()) { |
1437 // A mixin class must not have explicit constructors. | 1446 // A mixin class must not have explicit constructors. |
1438 if (!func.IsImplicitConstructor()) { | 1447 if (!func.IsImplicitConstructor()) { |
1439 const Script& script = Script::Handle(isolate, cls.script()); | 1448 const Script& script = Script::Handle(isolate, cls.script()); |
1440 ReportError(script, cls.token_pos(), | 1449 ReportError(Error::Handle(), // No previous error. |
| 1450 script, cls.token_pos(), |
1441 "mixin class %s must not have constructors\n", | 1451 "mixin class %s must not have constructors\n", |
1442 String::Handle(isolate, mixin_cls.Name()).ToCString()); | 1452 String::Handle(isolate, mixin_cls.Name()).ToCString()); |
1443 } | 1453 } |
1444 continue; // Skip the implicit constructor. | 1454 continue; // Skip the implicit constructor. |
1445 } | 1455 } |
1446 if (!func.is_static()) { | 1456 if (!func.is_static()) { |
1447 func = func.Clone(cls); | 1457 func = func.Clone(cls); |
1448 cloned_funcs.Add(func); | 1458 cloned_funcs.Add(func); |
1449 } | 1459 } |
1450 } | 1460 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 HANDLESCOPE(Isolate::Current()); | 1492 HANDLESCOPE(Isolate::Current()); |
1483 if (cls.is_type_finalized()) { | 1493 if (cls.is_type_finalized()) { |
1484 return; | 1494 return; |
1485 } | 1495 } |
1486 if (FLAG_trace_class_finalization) { | 1496 if (FLAG_trace_class_finalization) { |
1487 OS::Print("Finalize types in %s\n", cls.ToCString()); | 1497 OS::Print("Finalize types in %s\n", cls.ToCString()); |
1488 } | 1498 } |
1489 if (!IsSuperCycleFree(cls)) { | 1499 if (!IsSuperCycleFree(cls)) { |
1490 const String& name = String::Handle(cls.Name()); | 1500 const String& name = String::Handle(cls.Name()); |
1491 const Script& script = Script::Handle(cls.script()); | 1501 const Script& script = Script::Handle(cls.script()); |
1492 ReportError(script, cls.token_pos(), | 1502 ReportError(Error::Handle(), // No previous error. |
| 1503 script, cls.token_pos(), |
1493 "class '%s' has a cycle in its superclass relationship", | 1504 "class '%s' has a cycle in its superclass relationship", |
1494 name.ToCString()); | 1505 name.ToCString()); |
1495 } | 1506 } |
1496 // Finalize super class. | 1507 // Finalize super class. |
1497 const Class& super_class = Class::Handle(cls.SuperClass()); | 1508 const Class& super_class = Class::Handle(cls.SuperClass()); |
1498 if (!super_class.IsNull()) { | 1509 if (!super_class.IsNull()) { |
1499 FinalizeTypesInClass(super_class); | 1510 FinalizeTypesInClass(super_class); |
1500 } | 1511 } |
1501 if (cls.mixin() != Type::null()) { | 1512 if (cls.mixin() != Type::null()) { |
1502 // Copy the type parameters to the mixin application. | 1513 // Copy the type parameters to the mixin application. |
(...skipping 13 matching lines...) Expand all Loading... |
1516 // out of bound type argument. | 1527 // out of bound type argument. |
1517 super_type = FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1528 super_type = FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
1518 cls.set_super_type(super_type); | 1529 cls.set_super_type(super_type); |
1519 } | 1530 } |
1520 if (cls.IsSignatureClass()) { | 1531 if (cls.IsSignatureClass()) { |
1521 // Check for illegal self references. | 1532 // Check for illegal self references. |
1522 GrowableArray<intptr_t> visited_aliases; | 1533 GrowableArray<intptr_t> visited_aliases; |
1523 if (!IsAliasCycleFree(cls, &visited_aliases)) { | 1534 if (!IsAliasCycleFree(cls, &visited_aliases)) { |
1524 const String& name = String::Handle(cls.Name()); | 1535 const String& name = String::Handle(cls.Name()); |
1525 const Script& script = Script::Handle(cls.script()); | 1536 const Script& script = Script::Handle(cls.script()); |
1526 ReportError(script, cls.token_pos(), | 1537 ReportError(Error::Handle(), // No previous error. |
| 1538 script, cls.token_pos(), |
1527 "typedef '%s' illegally refers to itself", | 1539 "typedef '%s' illegally refers to itself", |
1528 name.ToCString()); | 1540 name.ToCString()); |
1529 } | 1541 } |
1530 cls.set_is_type_finalized(); | 1542 cls.set_is_type_finalized(); |
1531 // Signature classes extend Object. No need to add this class to the direct | 1543 // Signature classes extend Object. No need to add this class to the direct |
1532 // subclasses of Object. | 1544 // subclasses of Object. |
1533 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1545 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
1534 | 1546 |
1535 // The type parameters of signature classes may have bounds. | 1547 // The type parameters of signature classes may have bounds. |
1536 FinalizeUpperBounds(cls); | 1548 FinalizeUpperBounds(cls); |
(...skipping 17 matching lines...) Expand all Loading... |
1554 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1566 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
1555 interface_types.SetAt(i, interface_type); | 1567 interface_types.SetAt(i, interface_type); |
1556 | 1568 |
1557 // Check whether the interface is duplicated. We need to wait with | 1569 // Check whether the interface is duplicated. We need to wait with |
1558 // this check until the super type and interface types are finalized, | 1570 // this check until the super type and interface types are finalized, |
1559 // so that we can use Type::Equals() for the test. | 1571 // so that we can use Type::Equals() for the test. |
1560 ASSERT(interface_type.IsFinalized()); | 1572 ASSERT(interface_type.IsFinalized()); |
1561 ASSERT(super_type.IsNull() || super_type.IsFinalized()); | 1573 ASSERT(super_type.IsNull() || super_type.IsFinalized()); |
1562 if (!super_type.IsNull() && interface_type.Equals(super_type)) { | 1574 if (!super_type.IsNull() && interface_type.Equals(super_type)) { |
1563 const Script& script = Script::Handle(cls.script()); | 1575 const Script& script = Script::Handle(cls.script()); |
1564 ReportError(script, cls.token_pos(), | 1576 ReportError(Error::Handle(), // No previous error. |
| 1577 script, cls.token_pos(), |
1565 "super type '%s' may not be listed in " | 1578 "super type '%s' may not be listed in " |
1566 "implements clause of class '%s'", | 1579 "implements clause of class '%s'", |
1567 String::Handle(super_type.Name()).ToCString(), | 1580 String::Handle(super_type.Name()).ToCString(), |
1568 String::Handle(cls.Name()).ToCString()); | 1581 String::Handle(cls.Name()).ToCString()); |
1569 } | 1582 } |
1570 for (intptr_t j = 0; j < i; j++) { | 1583 for (intptr_t j = 0; j < i; j++) { |
1571 seen_interf ^= interface_types.At(j); | 1584 seen_interf ^= interface_types.At(j); |
1572 if (interface_type.Equals(seen_interf)) { | 1585 if (interface_type.Equals(seen_interf)) { |
1573 const Script& script = Script::Handle(cls.script()); | 1586 const Script& script = Script::Handle(cls.script()); |
1574 ReportError(script, cls.token_pos(), | 1587 ReportError(Error::Handle(), // No previous error. |
| 1588 script, cls.token_pos(), |
1575 "interface '%s' appears twice in " | 1589 "interface '%s' appears twice in " |
1576 "implements clause of class '%s'", | 1590 "implements clause of class '%s'", |
1577 String::Handle(interface_type.Name()).ToCString(), | 1591 String::Handle(interface_type.Name()).ToCString(), |
1578 String::Handle(cls.Name()).ToCString()); | 1592 String::Handle(cls.Name()).ToCString()); |
1579 } | 1593 } |
1580 } | 1594 } |
1581 } | 1595 } |
1582 // Mark as type finalized before resolving type parameter upper bounds | 1596 // Mark as type finalized before resolving type parameter upper bounds |
1583 // in order to break cycles. | 1597 // in order to break cycles. |
1584 cls.set_is_type_finalized(); | 1598 cls.set_is_type_finalized(); |
1585 // Finalize bounds even if running in production mode, so that a snapshot | 1599 // Finalize bounds even if running in production mode, so that a snapshot |
1586 // contains them. | 1600 // contains them. |
1587 FinalizeUpperBounds(cls); | 1601 FinalizeUpperBounds(cls); |
1588 // Add this class to the direct subclasses of the superclass, unless the | 1602 // Add this class to the direct subclasses of the superclass, unless the |
1589 // superclass is Object. | 1603 // superclass is Object. |
1590 if (!super_type.IsNull() && !super_type.IsObjectType()) { | 1604 if (!super_type.IsNull() && !super_type.IsObjectType()) { |
1591 ASSERT(!super_class.IsNull()); | 1605 ASSERT(!super_class.IsNull()); |
1592 super_class.AddDirectSubclass(cls); | 1606 super_class.AddDirectSubclass(cls); |
1593 } | 1607 } |
1594 // Top level classes are parsed eagerly so just finalize it. | 1608 // A top level class is parsed eagerly so just finalize it. |
1595 if (cls.IsTopLevel()) { | 1609 if (cls.IsTopLevel()) { |
1596 FinalizeClass(cls); | 1610 FinalizeClass(cls); |
| 1611 } else { |
| 1612 // This class should not contain any fields or functions yet, because it has |
| 1613 // not been compiled yet. Since 'ResolveAndFinalizeMemberTypes(cls)' has not |
| 1614 // been called yet, unfinalized member types could choke the snapshotter. |
| 1615 ASSERT(Array::Handle(cls.fields()).Length() == 0); |
| 1616 ASSERT(Array::Handle(cls.functions()).Length() == 0); |
1597 } | 1617 } |
1598 } | 1618 } |
1599 | 1619 |
1600 | 1620 |
1601 void ClassFinalizer::FinalizeClass(const Class& cls) { | 1621 void ClassFinalizer::FinalizeClass(const Class& cls) { |
1602 HANDLESCOPE(Isolate::Current()); | 1622 HANDLESCOPE(Isolate::Current()); |
1603 if (cls.is_finalized()) { | 1623 if (cls.is_finalized()) { |
1604 return; | 1624 return; |
1605 } | 1625 } |
1606 if (FLAG_trace_class_finalization) { | 1626 if (FLAG_trace_class_finalization) { |
1607 OS::Print("Finalize %s\n", cls.ToCString()); | 1627 OS::Print("Finalize %s\n", cls.ToCString()); |
1608 } | 1628 } |
1609 if (cls.mixin() != Type::null()) { | 1629 if (cls.mixin() != Type::null()) { |
1610 // Copy instance methods and fields from the mixin class. | 1630 // Copy instance methods and fields from the mixin class. |
1611 // This has to happen before the check whether the methods of | 1631 // This has to happen before the check whether the methods of |
1612 // the class conflict with inherited methods. | 1632 // the class conflict with inherited methods. |
1613 ApplyMixin(cls); | 1633 ApplyMixin(cls); |
1614 } | 1634 } |
1615 // Ensure super class is finalized. | 1635 // Ensure super class is finalized. |
1616 const Class& super = Class::Handle(cls.SuperClass()); | 1636 const Class& super = Class::Handle(cls.SuperClass()); |
1617 if (!super.IsNull()) { | 1637 if (!super.IsNull()) { |
1618 FinalizeClass(super); | 1638 FinalizeClass(super); |
1619 } | 1639 } |
1620 // Mark as parsed and finalized. | 1640 // Mark as parsed and finalized. |
1621 cls.Finalize(); | 1641 cls.Finalize(); |
| 1642 // Mixin typedef classes may still lack their implicit constructor. |
| 1643 // TODO(regis): Implement mixin typedefs with an alias class. |
| 1644 if (cls.is_synthesized_class() && |
| 1645 (cls.functions() == Object::empty_array().raw())) { |
| 1646 Parser::AddImplicitConstructor(cls); |
| 1647 } |
| 1648 // Every class should have at least a constructor, unless it is a top level |
| 1649 // class or a signature class. |
| 1650 ASSERT(cls.IsTopLevel() || |
| 1651 cls.IsSignatureClass() || |
| 1652 (Array::Handle(cls.functions()).Length() > 0)); |
1622 // Resolve and finalize all member types. | 1653 // Resolve and finalize all member types. |
1623 ResolveAndFinalizeMemberTypes(cls); | 1654 ResolveAndFinalizeMemberTypes(cls); |
1624 // Run additional checks after all types are finalized. | 1655 // Run additional checks after all types are finalized. |
1625 if (cls.is_const()) { | 1656 if (cls.is_const()) { |
1626 CheckForLegalConstClass(cls); | 1657 CheckForLegalConstClass(cls); |
1627 } | 1658 } |
1628 } | 1659 } |
1629 | 1660 |
1630 | 1661 |
1631 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 1662 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1708 type = function.ParameterTypeAt(i); | 1739 type = function.ParameterTypeAt(i); |
1709 if (!IsParameterTypeCycleFree(cls, type, visited)) { | 1740 if (!IsParameterTypeCycleFree(cls, type, visited)) { |
1710 return false; | 1741 return false; |
1711 } | 1742 } |
1712 } | 1743 } |
1713 visited->RemoveLast(); | 1744 visited->RemoveLast(); |
1714 return true; | 1745 return true; |
1715 } | 1746 } |
1716 | 1747 |
1717 | 1748 |
1718 void ClassFinalizer::CollectTypeArguments(const Class& cls, | 1749 void ClassFinalizer::CollectTypeArguments( |
1719 const Type& type, | 1750 const Class& cls, |
1720 const GrowableObjectArray& collected_args) { | 1751 const Type& type, |
| 1752 const GrowableObjectArray& collected_args) { |
1721 ASSERT(type.HasResolvedTypeClass()); | 1753 ASSERT(type.HasResolvedTypeClass()); |
1722 Class& type_class = Class::Handle(type.type_class()); | 1754 Class& type_class = Class::Handle(type.type_class()); |
1723 AbstractTypeArguments& type_args = | 1755 AbstractTypeArguments& type_args = |
1724 AbstractTypeArguments::Handle(type.arguments()); | 1756 AbstractTypeArguments::Handle(type.arguments()); |
1725 intptr_t num_type_parameters = type_class.NumTypeParameters(); | 1757 const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
1726 intptr_t num_type_arguments = type_args.IsNull() ? 0 : type_args.Length(); | 1758 const intptr_t num_type_arguments = |
| 1759 type_args.IsNull() ? 0 : type_args.Length(); |
1727 AbstractType& arg = AbstractType::Handle(); | 1760 AbstractType& arg = AbstractType::Handle(); |
1728 if (num_type_arguments > 0) { | 1761 if (num_type_arguments > 0) { |
1729 if (num_type_arguments != num_type_parameters) { | 1762 if (num_type_arguments != num_type_parameters) { |
1730 const Script& script = Script::Handle(cls.script()); | 1763 const Script& script = Script::Handle(cls.script()); |
1731 const String& type_class_name = String::Handle(type_class.Name()); | 1764 const String& type_class_name = String::Handle(type_class.Name()); |
1732 ReportError(script, type.token_pos(), | 1765 ReportError(Error::Handle(), // No previous error. |
1733 "wrong number of type arguments for class '%s'", | 1766 script, type.token_pos(), |
1734 type_class_name.ToCString()); | 1767 "wrong number of type arguments for class '%s'", |
| 1768 type_class_name.ToCString()); |
1735 } | 1769 } |
1736 for (int i = 0; i < num_type_arguments; i++) { | 1770 for (int i = 0; i < num_type_arguments; i++) { |
1737 arg = type_args.TypeAt(i); | 1771 arg = type_args.TypeAt(i); |
1738 collected_args.Add(arg); | 1772 collected_args.Add(arg); |
1739 } | 1773 } |
1740 } else { | 1774 } else { |
1741 // Fill arguments with type dynamic. | 1775 // Fill arguments with type dynamic. |
1742 for (int i = 0; i < num_type_parameters; i++) { | 1776 for (int i = 0; i < num_type_parameters; i++) { |
1743 arg = Type::DynamicType(); | 1777 arg = Type::DynamicType(); |
1744 collected_args.Add(arg); | 1778 collected_args.Add(arg); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 // Recursively walks the graph of explicitly declared super type and | 1831 // Recursively walks the graph of explicitly declared super type and |
1798 // interfaces, resolving unresolved super types and interfaces. | 1832 // interfaces, resolving unresolved super types and interfaces. |
1799 // Reports an error if there is an interface reference that cannot be | 1833 // Reports an error if there is an interface reference that cannot be |
1800 // resolved, or if there is a cycle in the graph. We detect cycles by | 1834 // resolved, or if there is a cycle in the graph. We detect cycles by |
1801 // remembering interfaces we've visited in each path through the | 1835 // remembering interfaces we've visited in each path through the |
1802 // graph. If we visit an interface a second time on a given path, | 1836 // graph. If we visit an interface a second time on a given path, |
1803 // we found a loop. | 1837 // we found a loop. |
1804 void ClassFinalizer::ResolveSuperTypeAndInterfaces( | 1838 void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
1805 const Class& cls, GrowableArray<intptr_t>* visited) { | 1839 const Class& cls, GrowableArray<intptr_t>* visited) { |
1806 ASSERT(visited != NULL); | 1840 ASSERT(visited != NULL); |
| 1841 if (FLAG_trace_class_finalization) { |
| 1842 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); |
| 1843 } |
1807 const intptr_t cls_index = cls.id(); | 1844 const intptr_t cls_index = cls.id(); |
1808 for (int i = 0; i < visited->length(); i++) { | 1845 for (int i = 0; i < visited->length(); i++) { |
1809 if ((*visited)[i] == cls_index) { | 1846 if ((*visited)[i] == cls_index) { |
1810 // We have already visited class 'cls'. We found a cycle. | 1847 // We have already visited class 'cls'. We found a cycle. |
1811 const String& class_name = String::Handle(cls.Name()); | 1848 const String& class_name = String::Handle(cls.Name()); |
1812 const Script& script = Script::Handle(cls.script()); | 1849 const Script& script = Script::Handle(cls.script()); |
1813 ReportError(script, cls.token_pos(), | 1850 ReportError(Error::Handle(), // No previous error. |
| 1851 script, cls.token_pos(), |
1814 "cyclic reference found for class '%s'", | 1852 "cyclic reference found for class '%s'", |
1815 class_name.ToCString()); | 1853 class_name.ToCString()); |
1816 } | 1854 } |
1817 } | 1855 } |
1818 | 1856 |
1819 // If the class/interface has no explicit super class/interfaces | 1857 // If the class/interface has no explicit super class/interfaces |
1820 // and is not a mixin application, we are done. | 1858 // and is not a mixin application, we are done. |
1821 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 1859 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
1822 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1860 Array& super_interfaces = Array::Handle(cls.interfaces()); |
1823 if ((super_type.IsNull() || super_type.IsObjectType()) && | 1861 if ((super_type.IsNull() || super_type.IsObjectType()) && |
(...skipping 16 matching lines...) Expand all Loading... |
1840 AbstractType& interface = AbstractType::Handle(); | 1878 AbstractType& interface = AbstractType::Handle(); |
1841 Class& interface_class = Class::Handle(); | 1879 Class& interface_class = Class::Handle(); |
1842 | 1880 |
1843 // Resolve super type. Failures lead to a longjmp. | 1881 // Resolve super type. Failures lead to a longjmp. |
1844 ResolveType(cls, super_type, kCanonicalizeWellFormed); | 1882 ResolveType(cls, super_type, kCanonicalizeWellFormed); |
1845 if (super_type.IsMalformed()) { | 1883 if (super_type.IsMalformed()) { |
1846 ReportError(Error::Handle(super_type.malformed_error())); | 1884 ReportError(Error::Handle(super_type.malformed_error())); |
1847 } | 1885 } |
1848 if (super_type.IsDynamicType()) { | 1886 if (super_type.IsDynamicType()) { |
1849 const Script& script = Script::Handle(cls.script()); | 1887 const Script& script = Script::Handle(cls.script()); |
1850 ReportError(script, cls.token_pos(), | 1888 ReportError(Error::Handle(), // No previous error. |
| 1889 script, cls.token_pos(), |
1851 "class '%s' may not extend 'dynamic'", | 1890 "class '%s' may not extend 'dynamic'", |
1852 String::Handle(cls.Name()).ToCString()); | 1891 String::Handle(cls.Name()).ToCString()); |
1853 } | 1892 } |
| 1893 interface_class = super_type.type_class(); |
| 1894 if (interface_class.IsSignatureClass()) { |
| 1895 const Script& script = Script::Handle(cls.script()); |
| 1896 ReportError(Error::Handle(), // No previous error. |
| 1897 script, cls.token_pos(), |
| 1898 "class '%s' may not extend function type alias '%s'", |
| 1899 String::Handle(cls.Name()).ToCString(), |
| 1900 String::Handle(super_type.UserVisibleName()).ToCString()); |
| 1901 } |
1854 | 1902 |
1855 interface_class = super_type.type_class(); | |
1856 // If cls belongs to core lib or to core lib's implementation, restrictions | 1903 // If cls belongs to core lib or to core lib's implementation, restrictions |
1857 // about allowed interfaces are lifted. | 1904 // about allowed interfaces are lifted. |
1858 if (!cls_belongs_to_core_lib) { | 1905 if (!cls_belongs_to_core_lib) { |
1859 // Prevent extending core implementation classes. | 1906 // Prevent extending core implementation classes. |
1860 bool is_error = false; | 1907 bool is_error = false; |
1861 switch (interface_class.id()) { | 1908 switch (interface_class.id()) { |
1862 case kNumberCid: | 1909 case kNumberCid: |
1863 case kIntegerCid: // Class Integer, not int. | 1910 case kIntegerCid: // Class Integer, not int. |
1864 case kSmiCid: | 1911 case kSmiCid: |
1865 case kMintCid: | 1912 case kMintCid: |
(...skipping 23 matching lines...) Expand all Loading... |
1889 if (super_type.IsDoubleType() || | 1936 if (super_type.IsDoubleType() || |
1890 super_type.IsIntType() || | 1937 super_type.IsIntType() || |
1891 super_type.IsStringType()) { | 1938 super_type.IsStringType()) { |
1892 is_error = true; | 1939 is_error = true; |
1893 } | 1940 } |
1894 break; | 1941 break; |
1895 } | 1942 } |
1896 } | 1943 } |
1897 if (is_error) { | 1944 if (is_error) { |
1898 const Script& script = Script::Handle(cls.script()); | 1945 const Script& script = Script::Handle(cls.script()); |
1899 ReportError(script, cls.token_pos(), | 1946 ReportError(Error::Handle(), // No previous error. |
| 1947 script, cls.token_pos(), |
1900 "'%s' is not allowed to extend '%s'", | 1948 "'%s' is not allowed to extend '%s'", |
1901 String::Handle(cls.Name()).ToCString(), | 1949 String::Handle(cls.Name()).ToCString(), |
1902 String::Handle(interface_class.Name()).ToCString()); | 1950 String::Handle(interface_class.Name()).ToCString()); |
1903 } | 1951 } |
1904 } | 1952 } |
1905 // Now resolve the super interfaces of the super type. | 1953 // Now resolve the super interfaces of the super type. |
1906 ResolveSuperTypeAndInterfaces(interface_class, visited); | 1954 ResolveSuperTypeAndInterfaces(interface_class, visited); |
1907 | 1955 |
1908 // Resolve interfaces. Failures lead to a longjmp. | 1956 // Resolve interfaces. Failures lead to a longjmp. |
1909 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { | 1957 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { |
1910 interface ^= super_interfaces.At(i); | 1958 interface ^= super_interfaces.At(i); |
1911 ResolveType(cls, interface, kCanonicalizeWellFormed); | 1959 ResolveType(cls, interface, kCanonicalizeWellFormed); |
1912 ASSERT(!interface.IsTypeParameter()); // Should be detected by parser. | 1960 ASSERT(!interface.IsTypeParameter()); // Should be detected by parser. |
1913 if (interface.IsMalformed()) { | 1961 if (interface.IsMalformed()) { |
1914 ReportError(Error::Handle(interface.malformed_error())); | 1962 ReportError(Error::Handle(interface.malformed_error())); |
1915 } | 1963 } |
1916 if (interface.IsDynamicType()) { | 1964 if (interface.IsDynamicType()) { |
1917 const Script& script = Script::Handle(cls.script()); | 1965 const Script& script = Script::Handle(cls.script()); |
1918 ReportError(script, cls.token_pos(), | 1966 ReportError(Error::Handle(), // No previous error. |
| 1967 script, cls.token_pos(), |
1919 "'dynamic' may not be used as interface"); | 1968 "'dynamic' may not be used as interface"); |
1920 } | 1969 } |
1921 interface_class = interface.type_class(); | 1970 interface_class = interface.type_class(); |
1922 if (interface_class.IsSignatureClass()) { | 1971 if (interface_class.IsSignatureClass()) { |
1923 const Script& script = Script::Handle(cls.script()); | 1972 const Script& script = Script::Handle(cls.script()); |
1924 ReportError(script, cls.token_pos(), | 1973 ReportError(Error::Handle(), // No previous error. |
1925 "'%s' is used where an interface or class name is expected", | 1974 script, cls.token_pos(), |
| 1975 "function type alias '%s' may not be used as interface", |
1926 String::Handle(interface_class.Name()).ToCString()); | 1976 String::Handle(interface_class.Name()).ToCString()); |
1927 } | 1977 } |
1928 // Verify that unless cls belongs to core lib, it cannot extend or implement | 1978 // Verify that unless cls belongs to core lib, it cannot extend or implement |
1929 // any of bool, num, int, double, String, Function, dynamic. | 1979 // any of bool, num, int, double, String, Function, dynamic. |
1930 // The exception is signature classes, which are compiler generated and | 1980 // The exception is signature classes, which are compiler generated and |
1931 // represent a function type, therefore implementing the Function interface. | 1981 // represent a function type, therefore implementing the Function interface. |
1932 if (!cls_belongs_to_core_lib) { | 1982 if (!cls_belongs_to_core_lib) { |
1933 if (interface.IsBoolType() || | 1983 if (interface.IsBoolType() || |
1934 interface.IsNumberType() || | 1984 interface.IsNumberType() || |
1935 interface.IsIntType() || | 1985 interface.IsIntType() || |
1936 interface.IsDoubleType() || | 1986 interface.IsDoubleType() || |
1937 interface.IsStringType() || | 1987 interface.IsStringType() || |
1938 (interface.IsFunctionType() && !cls.IsSignatureClass()) || | 1988 (interface.IsFunctionType() && !cls.IsSignatureClass()) || |
1939 interface.IsDynamicType()) { | 1989 interface.IsDynamicType()) { |
1940 const Script& script = Script::Handle(cls.script()); | 1990 const Script& script = Script::Handle(cls.script()); |
1941 ReportError(script, cls.token_pos(), | 1991 ReportError(Error::Handle(), // No previous error. |
| 1992 script, cls.token_pos(), |
1942 "'%s' is not allowed to extend or implement '%s'", | 1993 "'%s' is not allowed to extend or implement '%s'", |
1943 String::Handle(cls.Name()).ToCString(), | 1994 String::Handle(cls.Name()).ToCString(), |
1944 String::Handle(interface_class.Name()).ToCString()); | 1995 String::Handle(interface_class.Name()).ToCString()); |
1945 } | 1996 } |
1946 } | 1997 } |
1947 interface_class.set_is_implemented(); | 1998 interface_class.set_is_implemented(); |
1948 // Now resolve the super interfaces. | 1999 // Now resolve the super interfaces. |
1949 ResolveSuperTypeAndInterfaces(interface_class, visited); | 2000 ResolveSuperTypeAndInterfaces(interface_class, visited); |
1950 } | 2001 } |
1951 visited->RemoveLast(); | 2002 visited->RemoveLast(); |
1952 } | 2003 } |
1953 | 2004 |
1954 | 2005 |
1955 // A class is marked as constant if it has one constant constructor. | 2006 // A class is marked as constant if it has one constant constructor. |
1956 // A constant class can only have final instance fields. | 2007 // A constant class can only have final instance fields. |
1957 // Note: we must check for cycles before checking for const properties. | 2008 // Note: we must check for cycles before checking for const properties. |
1958 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 2009 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
1959 ASSERT(cls.is_const()); | 2010 ASSERT(cls.is_const()); |
1960 const Array& fields_array = Array::Handle(cls.fields()); | 2011 const Array& fields_array = Array::Handle(cls.fields()); |
1961 intptr_t len = fields_array.Length(); | 2012 intptr_t len = fields_array.Length(); |
1962 Field& field = Field::Handle(); | 2013 Field& field = Field::Handle(); |
1963 for (intptr_t i = 0; i < len; i++) { | 2014 for (intptr_t i = 0; i < len; i++) { |
1964 field ^= fields_array.At(i); | 2015 field ^= fields_array.At(i); |
1965 if (!field.is_static() && !field.is_final()) { | 2016 if (!field.is_static() && !field.is_final()) { |
1966 const String& class_name = String::Handle(cls.Name()); | 2017 const String& class_name = String::Handle(cls.Name()); |
1967 const String& field_name = String::Handle(field.name()); | 2018 const String& field_name = String::Handle(field.name()); |
1968 const Script& script = Script::Handle(cls.script()); | 2019 const Script& script = Script::Handle(cls.script()); |
1969 ReportError(script, field.token_pos(), | 2020 ReportError(Error::Handle(), // No previous error. |
| 2021 script, field.token_pos(), |
1970 "const class '%s' has non-final field '%s'", | 2022 "const class '%s' has non-final field '%s'", |
1971 class_name.ToCString(), field_name.ToCString()); | 2023 class_name.ToCString(), field_name.ToCString()); |
1972 } | 2024 } |
1973 } | 2025 } |
1974 } | 2026 } |
1975 | 2027 |
1976 | 2028 |
1977 void ClassFinalizer::PrintClassInformation(const Class& cls) { | 2029 void ClassFinalizer::PrintClassInformation(const Class& cls) { |
1978 HANDLESCOPE(Isolate::Current()); | 2030 HANDLESCOPE(Isolate::Current()); |
1979 const String& class_name = String::Handle(cls.Name()); | 2031 const String& class_name = String::Handle(cls.Name()); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 va_end(args); | 2136 va_end(args); |
2085 } | 2137 } |
2086 | 2138 |
2087 | 2139 |
2088 void ClassFinalizer::ReportError(const Error& error) { | 2140 void ClassFinalizer::ReportError(const Error& error) { |
2089 Isolate::Current()->long_jump_base()->Jump(1, error); | 2141 Isolate::Current()->long_jump_base()->Jump(1, error); |
2090 UNREACHABLE(); | 2142 UNREACHABLE(); |
2091 } | 2143 } |
2092 | 2144 |
2093 | 2145 |
2094 void ClassFinalizer::ReportError(const Script& script, | 2146 void ClassFinalizer::ReportError(const Error& prev_error, |
| 2147 const Script& script, |
2095 intptr_t token_pos, | 2148 intptr_t token_pos, |
2096 const char* format, ...) { | 2149 const char* format, ...) { |
2097 va_list args; | 2150 va_list args; |
2098 va_start(args, format); | 2151 va_start(args, format); |
2099 const Error& error = Error::Handle( | 2152 Error& error = Error::Handle(); |
2100 Parser::FormatError(script, token_pos, "Error", format, args)); | 2153 if (prev_error.IsNull()) { |
| 2154 error ^= Parser::FormatError(script, token_pos, "Error", format, args); |
| 2155 } else { |
| 2156 error ^= Parser::FormatErrorWithAppend( |
| 2157 prev_error, script, token_pos, "Error", format, args); |
| 2158 } |
2101 va_end(args); | 2159 va_end(args); |
2102 ReportError(error); | 2160 ReportError(error); |
2103 } | 2161 } |
2104 | 2162 |
2105 | 2163 |
2106 void ClassFinalizer::ReportError(const char* format, ...) { | 2164 void ClassFinalizer::ReportError(const char* format, ...) { |
2107 va_list args; | 2165 va_list args; |
2108 va_start(args, format); | 2166 va_start(args, format); |
2109 const Error& error = Error::Handle( | 2167 const Error& error = Error::Handle( |
2110 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 2168 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2166 expected_name ^= String::New("_offset"); | 2224 expected_name ^= String::New("_offset"); |
2167 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2225 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
2168 field ^= fields_array.At(2); | 2226 field ^= fields_array.At(2); |
2169 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2227 ASSERT(field.Offset() == TypedDataView::length_offset()); |
2170 name ^= field.name(); | 2228 name ^= field.name(); |
2171 ASSERT(name.Equals("length")); | 2229 ASSERT(name.Equals("length")); |
2172 #endif | 2230 #endif |
2173 } | 2231 } |
2174 | 2232 |
2175 } // namespace dart | 2233 } // namespace dart |
OLD | NEW |