| 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 |