OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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" |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 if (super_type.IsNull()) { | 292 if (super_type.IsNull()) { |
293 return; | 293 return; |
294 } | 294 } |
295 // Resolve failures lead to a longjmp. | 295 // Resolve failures lead to a longjmp. |
296 ResolveType(cls, super_type); | 296 ResolveType(cls, super_type); |
297 const Class& super_class = Class::Handle(super_type.type_class()); | 297 const Class& super_class = Class::Handle(super_type.type_class()); |
298 if (cls.is_interface() != super_class.is_interface()) { | 298 if (cls.is_interface() != super_class.is_interface()) { |
299 String& class_name = String::Handle(cls.Name()); | 299 String& class_name = String::Handle(cls.Name()); |
300 String& super_class_name = String::Handle(super_class.Name()); | 300 String& super_class_name = String::Handle(super_class.Name()); |
301 const Script& script = Script::Handle(cls.script()); | 301 const Script& script = Script::Handle(cls.script()); |
302 ReportError(script, -1, | 302 ReportError(script, cls.token_index(), |
303 "class '%s' and superclass '%s' are not " | 303 "class '%s' and superclass '%s' are not " |
304 "both classes or both interfaces.\n", | 304 "both classes or both interfaces.\n", |
305 class_name.ToCString(), | 305 class_name.ToCString(), |
306 super_class_name.ToCString()); | 306 super_class_name.ToCString()); |
307 } | 307 } |
308 // If cls belongs to core lib or to core lib's implementation, restrictions | 308 // If cls belongs to core lib or to core lib's implementation, restrictions |
309 // about allowed interfaces are lifted. | 309 // about allowed interfaces are lifted. |
310 if ((cls.library() != Library::CoreLibrary()) && | 310 if ((cls.library() != Library::CoreLibrary()) && |
311 (cls.library() != Library::CoreImplLibrary())) { | 311 (cls.library() != Library::CoreImplLibrary())) { |
312 // Prevent extending core implementation classes Bool, Double, ObjectArray, | 312 // Prevent extending core implementation classes Bool, Double, ObjectArray, |
(...skipping 17 matching lines...) Expand all Loading... |
330 (super_class.raw() == object_store->internal_byte_array_class()) || | 330 (super_class.raw() == object_store->internal_byte_array_class()) || |
331 (super_class.raw() == object_store->external_byte_array_class()) || | 331 (super_class.raw() == object_store->external_byte_array_class()) || |
332 (super_class.raw() == integer_implementation_class.raw()) || | 332 (super_class.raw() == integer_implementation_class.raw()) || |
333 (super_class.raw() == object_store->smi_class()) || | 333 (super_class.raw() == object_store->smi_class()) || |
334 (super_class.raw() == object_store->mint_class()) || | 334 (super_class.raw() == object_store->mint_class()) || |
335 (super_class.raw() == object_store->bigint_class()) || | 335 (super_class.raw() == object_store->bigint_class()) || |
336 (super_class.raw() == object_store->one_byte_string_class()) || | 336 (super_class.raw() == object_store->one_byte_string_class()) || |
337 (super_class.raw() == object_store->two_byte_string_class()) || | 337 (super_class.raw() == object_store->two_byte_string_class()) || |
338 (super_class.raw() == object_store->four_byte_string_class())) { | 338 (super_class.raw() == object_store->four_byte_string_class())) { |
339 const Script& script = Script::Handle(cls.script()); | 339 const Script& script = Script::Handle(cls.script()); |
340 ReportError(script, -1, | 340 ReportError(script, cls.token_index(), |
341 "'%s' is not allowed to extend '%s'\n", | 341 "'%s' is not allowed to extend '%s'\n", |
342 String::Handle(cls.Name()).ToCString(), | 342 String::Handle(cls.Name()).ToCString(), |
343 String::Handle(super_class.Name()).ToCString()); | 343 String::Handle(super_class.Name()).ToCString()); |
344 } | 344 } |
345 } | 345 } |
346 return; | 346 return; |
347 } | 347 } |
348 | 348 |
349 | 349 |
350 void ClassFinalizer::ResolveDefaultClass(const Class& interface) { | 350 void ClassFinalizer::ResolveDefaultClass(const Class& interface) { |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 if (!type_extends.IsInstantiated()) { | 554 if (!type_extends.IsInstantiated()) { |
555 type_extends = type_extends.InstantiateFrom(arguments); | 555 type_extends = type_extends.InstantiateFrom(arguments); |
556 } | 556 } |
557 // TODO(regis): Where do we check the constraints when the type is | 557 // TODO(regis): Where do we check the constraints when the type is |
558 // generic? | 558 // generic? |
559 if (!type.IsSubtypeOf(type_extends)) { | 559 if (!type.IsSubtypeOf(type_extends)) { |
560 const String& type_argument_name = String::Handle(type.Name()); | 560 const String& type_argument_name = String::Handle(type.Name()); |
561 const String& class_name = String::Handle(cls.Name()); | 561 const String& class_name = String::Handle(cls.Name()); |
562 const String& extends_name = String::Handle(type_extends.Name()); | 562 const String& extends_name = String::Handle(type_extends.Name()); |
563 const Script& script = Script::Handle(cls.script()); | 563 const Script& script = Script::Handle(cls.script()); |
564 ReportError(script, -1, | 564 ReportError(script, type.token_index(), |
565 "type argument '%s' of class '%s' " | 565 "type argument '%s' of class '%s' " |
566 "does not extend type '%s'\n", | 566 "does not extend type '%s'\n", |
567 type_argument_name.ToCString(), | 567 type_argument_name.ToCString(), |
568 class_name.ToCString(), | 568 class_name.ToCString(), |
569 extends_name.ToCString()); | 569 extends_name.ToCString()); |
570 } | 570 } |
571 } | 571 } |
572 } | 572 } |
573 } | 573 } |
574 const Type& super_type = Type::Handle(cls.super_type()); | 574 const Type& super_type = Type::Handle(cls.super_type()); |
(...skipping 28 matching lines...) Expand all Loading... |
603 type_parameter.set_is_finalized(); | 603 type_parameter.set_is_finalized(); |
604 // We do not canonicalize type parameters. | 604 // We do not canonicalize type parameters. |
605 return type_parameter.raw(); | 605 return type_parameter.raw(); |
606 } | 606 } |
607 | 607 |
608 // At this point, we can only have a parameterized_type. | 608 // At this point, we can only have a parameterized_type. |
609 Type& parameterized_type = Type::Handle(); | 609 Type& parameterized_type = Type::Handle(); |
610 parameterized_type ^= type.raw(); | 610 parameterized_type ^= type.raw(); |
611 | 611 |
612 if (parameterized_type.IsBeingFinalized()) { | 612 if (parameterized_type.IsBeingFinalized()) { |
613 ReportError("type '%s' illegally refers to itself\n", | 613 const Script& script = Script::Handle(cls.script()); |
| 614 ReportError(script, parameterized_type.token_index(), |
| 615 "type '%s' illegally refers to itself\n", |
614 String::Handle(parameterized_type.Name()).ToCString()); | 616 String::Handle(parameterized_type.Name()).ToCString()); |
615 } | 617 } |
616 | 618 |
617 // Mark type as being finalized in order to detect illegal self reference. | 619 // Mark type as being finalized in order to detect illegal self reference. |
618 parameterized_type.set_is_being_finalized(); | 620 parameterized_type.set_is_being_finalized(); |
619 | 621 |
620 // Finalize the current type arguments of the type, which are still the | 622 // Finalize the current type arguments of the type, which are still the |
621 // parsed type arguments. | 623 // parsed type arguments. |
622 AbstractTypeArguments& arguments = | 624 AbstractTypeArguments& arguments = |
623 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 625 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
(...skipping 28 matching lines...) Expand all Loading... |
652 // The finalized type argument vector needs num_type_arguments types. | 654 // The finalized type argument vector needs num_type_arguments types. |
653 const intptr_t num_type_arguments = type_class.NumTypeArguments(); | 655 const intptr_t num_type_arguments = type_class.NumTypeArguments(); |
654 // The type class has num_type_parameters type parameters. | 656 // The type class has num_type_parameters type parameters. |
655 const intptr_t num_type_parameters = type_class.NumTypeParameters(); | 657 const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
656 | 658 |
657 // Initialize the type argument vector. | 659 // Initialize the type argument vector. |
658 // Check the number of parsed type arguments, if any. | 660 // Check the number of parsed type arguments, if any. |
659 // Specifying no type arguments indicates a raw type, which is not an error. | 661 // Specifying no type arguments indicates a raw type, which is not an error. |
660 // However, subtyping constraints are checked below, even for a raw type. | 662 // However, subtyping constraints are checked below, even for a raw type. |
661 if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { | 663 if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
662 // TODO(regis): We need to store the token_index in each type. | 664 const Script& script = Script::Handle(cls.script()); |
663 ReportError("wrong number of type arguments in type '%s'\n", | 665 ReportError(script, type.token_index(), |
| 666 "wrong number of type arguments in type '%s'\n", |
664 String::Handle(type.Name()).ToCString()); | 667 String::Handle(type.Name()).ToCString()); |
665 } | 668 } |
666 // The full type argument vector consists of the type arguments of the | 669 // The full type argument vector consists of the type arguments of the |
667 // super types of type_class, which may be initialized from the parsed | 670 // super types of type_class, which may be initialized from the parsed |
668 // type arguments, followed by the parsed type arguments. | 671 // type arguments, followed by the parsed type arguments. |
669 if (num_type_arguments > 0) { | 672 if (num_type_arguments > 0) { |
670 TypeArguments& full_arguments = TypeArguments::Handle( | 673 TypeArguments& full_arguments = TypeArguments::Handle( |
671 TypeArguments::New(num_type_arguments)); | 674 TypeArguments::New(num_type_arguments)); |
672 // Copy the parsed type arguments at the correct offset in the full type | 675 // Copy the parsed type arguments at the correct offset in the full type |
673 // argument vector. | 676 // argument vector. |
(...skipping 29 matching lines...) Expand all Loading... |
703 if (FLAG_enable_type_checks) { | 706 if (FLAG_enable_type_checks) { |
704 VerifyUpperBounds(type_class, full_arguments); | 707 VerifyUpperBounds(type_class, full_arguments); |
705 } | 708 } |
706 } else { | 709 } else { |
707 parameterized_type.set_is_finalized(); | 710 parameterized_type.set_is_finalized(); |
708 } | 711 } |
709 return parameterized_type.Canonicalize(); | 712 return parameterized_type.Canonicalize(); |
710 } | 713 } |
711 | 714 |
712 | 715 |
713 RawAbstractType* ClassFinalizer::FinalizeAndCanonicalizeType( | |
714 const Class& cls, | |
715 const AbstractType& type, | |
716 Error* error) { | |
717 Isolate* isolate = Isolate::Current(); | |
718 ASSERT(isolate != NULL); | |
719 LongJump* base = isolate->long_jump_base(); | |
720 LongJump jump; | |
721 isolate->set_long_jump_base(&jump); | |
722 if (setjmp(*jump.Set()) == 0) { | |
723 const AbstractType& finalized_type = | |
724 AbstractType::Handle(FinalizeType(cls, type)); | |
725 isolate->set_long_jump_base(base); | |
726 *error = Error::null(); | |
727 return finalized_type.raw(); | |
728 } else { | |
729 // Error occured: Get the error message. | |
730 isolate->set_long_jump_base(base); | |
731 *error = isolate->object_store()->sticky_error(); | |
732 return type.raw(); | |
733 } | |
734 UNREACHABLE(); | |
735 return NULL; | |
736 } | |
737 | |
738 | |
739 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, | 716 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, |
740 const Function& function) { | 717 const Function& function) { |
741 // Resolve result type. | 718 // Resolve result type. |
742 AbstractType& type = AbstractType::Handle(function.result_type()); | 719 AbstractType& type = AbstractType::Handle(function.result_type()); |
743 ResolveType(cls, type); | 720 ResolveType(cls, type); |
744 type = FinalizeType(cls, type); | 721 type = FinalizeType(cls, type); |
745 function.set_result_type(type); | 722 function.set_result_type(type); |
746 // Resolve formal parameter types. | 723 // Resolve formal parameter types. |
747 const intptr_t num_parameters = function.NumberOfParameters(); | 724 const intptr_t num_parameters = function.NumberOfParameters(); |
748 for (intptr_t i = 0; i < num_parameters; i++) { | 725 for (intptr_t i = 0; i < num_parameters; i++) { |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 return; | 941 return; |
965 } | 942 } |
966 if (FLAG_trace_class_finalization) { | 943 if (FLAG_trace_class_finalization) { |
967 OS::Print("Finalize %s\n", cls.ToCString()); | 944 OS::Print("Finalize %s\n", cls.ToCString()); |
968 } | 945 } |
969 // Signature classes are finalized upon creation. | 946 // Signature classes are finalized upon creation. |
970 ASSERT(!cls.IsSignatureClass()); | 947 ASSERT(!cls.IsSignatureClass()); |
971 if (!IsSuperCycleFree(cls)) { | 948 if (!IsSuperCycleFree(cls)) { |
972 const String& name = String::Handle(cls.Name()); | 949 const String& name = String::Handle(cls.Name()); |
973 const Script& script = Script::Handle(cls.script()); | 950 const Script& script = Script::Handle(cls.script()); |
974 ReportError(script, -1, | 951 ReportError(script, cls.token_index(), |
975 "class '%s' has a cycle in its superclass relationship.\n", | 952 "class '%s' has a cycle in its superclass relationship.\n", |
976 name.ToCString()); | 953 name.ToCString()); |
977 } | 954 } |
978 GrowableArray<const Class*> visited; | 955 GrowableArray<const Class*> visited; |
979 ResolveInterfaces(cls, &visited); | 956 ResolveInterfaces(cls, &visited); |
980 Type& super_type = Type::Handle(cls.super_type()); | 957 Type& super_type = Type::Handle(cls.super_type()); |
981 if (!super_type.IsNull()) { | 958 if (!super_type.IsNull()) { |
982 const Class& super_class = Class::Handle(super_type.type_class()); | 959 const Class& super_class = Class::Handle(super_type.type_class()); |
983 // Finalize super class and super type. | 960 // Finalize super class and super type. |
984 FinalizeClass(super_class, generating_snapshot); | 961 FinalizeClass(super_class, generating_snapshot); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 CheckForLegalConstClass(cls); | 993 CheckForLegalConstClass(cls); |
1017 } | 994 } |
1018 // Check to ensure we don't have classes with native fields in libraries | 995 // Check to ensure we don't have classes with native fields in libraries |
1019 // which do not have a native resolver. | 996 // which do not have a native resolver. |
1020 if (!generating_snapshot && cls.num_native_fields() != 0) { | 997 if (!generating_snapshot && cls.num_native_fields() != 0) { |
1021 const Library& lib = Library::Handle(cls.library()); | 998 const Library& lib = Library::Handle(cls.library()); |
1022 if (lib.native_entry_resolver() == NULL) { | 999 if (lib.native_entry_resolver() == NULL) { |
1023 const String& cls_name = String::Handle(cls.Name()); | 1000 const String& cls_name = String::Handle(cls.Name()); |
1024 const String& lib_name = String::Handle(lib.url()); | 1001 const String& lib_name = String::Handle(lib.url()); |
1025 const Script& script = Script::Handle(cls.script()); | 1002 const Script& script = Script::Handle(cls.script()); |
1026 ReportError(script, -1, | 1003 ReportError(script, cls.token_index(), |
1027 "class '%s' is trying to extend a native fields class, " | 1004 "class '%s' is trying to extend a native fields class, " |
1028 "but library '%s' has no native resolvers", | 1005 "but library '%s' has no native resolvers", |
1029 cls_name.ToCString(), lib_name.ToCString()); | 1006 cls_name.ToCString(), lib_name.ToCString()); |
1030 } | 1007 } |
1031 } | 1008 } |
1032 } | 1009 } |
1033 | 1010 |
1034 | 1011 |
1035 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 1012 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
1036 Class& test1 = Class::Handle(cls.raw()); | 1013 Class& test1 = Class::Handle(cls.raw()); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 // graph. If we visit an interface a second time on a given path, | 1076 // graph. If we visit an interface a second time on a given path, |
1100 // we found a loop. | 1077 // we found a loop. |
1101 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1078 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
1102 GrowableArray<const Class*>* visited) { | 1079 GrowableArray<const Class*>* visited) { |
1103 ASSERT(visited != NULL); | 1080 ASSERT(visited != NULL); |
1104 for (int i = 0; i < visited->length(); i++) { | 1081 for (int i = 0; i < visited->length(); i++) { |
1105 if ((*visited)[i]->raw() == cls.raw()) { | 1082 if ((*visited)[i]->raw() == cls.raw()) { |
1106 // We have already visited interface class 'cls'. We found a cycle. | 1083 // We have already visited interface class 'cls'. We found a cycle. |
1107 const String& interface_name = String::Handle(cls.Name()); | 1084 const String& interface_name = String::Handle(cls.Name()); |
1108 const Script& script = Script::Handle(cls.script()); | 1085 const Script& script = Script::Handle(cls.script()); |
1109 ReportError(script, -1, | 1086 ReportError(script, cls.token_index(), |
1110 "Cyclic reference found for interface '%s'\n", | 1087 "Cyclic reference found for interface '%s'\n", |
1111 interface_name.ToCString()); | 1088 interface_name.ToCString()); |
1112 } | 1089 } |
1113 } | 1090 } |
1114 | 1091 |
1115 // If the class/interface has no explicit interfaces, we are done. | 1092 // If the class/interface has no explicit interfaces, we are done. |
1116 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1093 Array& super_interfaces = Array::Handle(cls.interfaces()); |
1117 if (super_interfaces.Length() == 0) { | 1094 if (super_interfaces.Length() == 0) { |
1118 return; | 1095 return; |
1119 } | 1096 } |
1120 | 1097 |
1121 // If cls belongs to core lib or to core lib's implementation, restrictions | 1098 // If cls belongs to core lib or to core lib's implementation, restrictions |
1122 // about allowed interfaces are lifted. | 1099 // about allowed interfaces are lifted. |
1123 const bool cls_belongs_to_core_lib = | 1100 const bool cls_belongs_to_core_lib = |
1124 (cls.library() == Library::CoreLibrary()) || | 1101 (cls.library() == Library::CoreLibrary()) || |
1125 (cls.library() == Library::CoreImplLibrary()); | 1102 (cls.library() == Library::CoreImplLibrary()); |
1126 | 1103 |
1127 // Resolve and check the interfaces of cls. | 1104 // Resolve and check the interfaces of cls. |
1128 visited->Add(&cls); | 1105 visited->Add(&cls); |
1129 AbstractType& interface = AbstractType::Handle(); | 1106 AbstractType& interface = AbstractType::Handle(); |
1130 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { | 1107 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { |
1131 interface ^= super_interfaces.At(i); | 1108 interface ^= super_interfaces.At(i); |
1132 ResolveType(cls, interface); | 1109 ResolveType(cls, interface); |
1133 if (interface.IsTypeParameter()) { | 1110 if (interface.IsTypeParameter()) { |
1134 const Script& script = Script::Handle(cls.script()); | 1111 const Script& script = Script::Handle(cls.script()); |
1135 ReportError(script, -1, | 1112 ReportError(script, cls.token_index(), |
1136 "Type parameter '%s' cannot be used as interface\n", | 1113 "Type parameter '%s' cannot be used as interface\n", |
1137 String::Handle(interface.Name()).ToCString()); | 1114 String::Handle(interface.Name()).ToCString()); |
1138 } | 1115 } |
1139 const Class& interface_class = Class::Handle(interface.type_class()); | 1116 const Class& interface_class = Class::Handle(interface.type_class()); |
1140 if (!interface_class.is_interface()) { | 1117 if (!interface_class.is_interface()) { |
1141 const Script& script = Script::Handle(cls.script()); | 1118 const Script& script = Script::Handle(cls.script()); |
1142 ReportError(script, -1, | 1119 ReportError(script, cls.token_index(), |
1143 "Class '%s' is used where an interface is expected\n", | 1120 "Class '%s' is used where an interface is expected\n", |
1144 String::Handle(interface_class.Name()).ToCString()); | 1121 String::Handle(interface_class.Name()).ToCString()); |
1145 } | 1122 } |
1146 // Verify that unless cls belongs to core lib, it cannot extend or implement | 1123 // Verify that unless cls belongs to core lib, it cannot extend or implement |
1147 // any of bool, num, int, double, String, Function, Dynamic. | 1124 // any of bool, num, int, double, String, Function, Dynamic. |
1148 // The exception is signature classes, which are compiler generated and | 1125 // The exception is signature classes, which are compiler generated and |
1149 // represent a function type, therefore implementing the Function interface. | 1126 // represent a function type, therefore implementing the Function interface. |
1150 if (!cls_belongs_to_core_lib) { | 1127 if (!cls_belongs_to_core_lib) { |
1151 if (interface.IsBoolInterface() || | 1128 if (interface.IsBoolInterface() || |
1152 interface.IsNumberInterface() || | 1129 interface.IsNumberInterface() || |
1153 interface.IsIntInterface() || | 1130 interface.IsIntInterface() || |
1154 interface.IsDoubleInterface() || | 1131 interface.IsDoubleInterface() || |
1155 interface.IsStringInterface() || | 1132 interface.IsStringInterface() || |
1156 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || | 1133 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || |
1157 interface.IsDynamicType()) { | 1134 interface.IsDynamicType()) { |
1158 const Script& script = Script::Handle(cls.script()); | 1135 const Script& script = Script::Handle(cls.script()); |
1159 ReportError(script, -1, | 1136 ReportError(script, cls.token_index(), |
1160 "'%s' is not allowed to extend or implement '%s'\n", | 1137 "'%s' is not allowed to extend or implement '%s'\n", |
1161 String::Handle(cls.Name()).ToCString(), | 1138 String::Handle(cls.Name()).ToCString(), |
1162 String::Handle(interface_class.Name()).ToCString()); | 1139 String::Handle(interface_class.Name()).ToCString()); |
1163 } | 1140 } |
1164 } | 1141 } |
1165 // Now resolve the super interfaces. | 1142 // Now resolve the super interfaces. |
1166 ResolveInterfaces(interface_class, visited); | 1143 ResolveInterfaces(interface_class, visited); |
1167 } | 1144 } |
1168 visited->RemoveLast(); | 1145 visited->RemoveLast(); |
1169 } | 1146 } |
1170 | 1147 |
1171 | 1148 |
1172 // A class is marked as constant if it has one constant constructor. | 1149 // A class is marked as constant if it has one constant constructor. |
1173 // A constant class: | 1150 // A constant class: |
1174 // - may extend only const classes. | 1151 // - may extend only const classes. |
1175 // - has only const instance fields. | 1152 // - has only const instance fields. |
1176 // Note: we must check for cycles before checking for const properties. | 1153 // Note: we must check for cycles before checking for const properties. |
1177 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 1154 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
1178 ASSERT(cls.is_const()); | 1155 ASSERT(cls.is_const()); |
1179 const Class& super = Class::Handle(cls.SuperClass()); | 1156 const Class& super = Class::Handle(cls.SuperClass()); |
1180 if (!super.IsNull() && !super.is_const()) { | 1157 if (!super.IsNull() && !super.is_const()) { |
1181 String& name = String::Handle(super.Name()); | 1158 String& name = String::Handle(super.Name()); |
1182 const Script& script = Script::Handle(cls.script()); | 1159 const Script& script = Script::Handle(cls.script()); |
1183 ReportError(script, -1, | 1160 ReportError(script, cls.token_index(), |
1184 "superclass '%s' must be const.\n", name.ToCString()); | 1161 "superclass '%s' must be const.\n", name.ToCString()); |
1185 } | 1162 } |
1186 const Array& fields_array = Array::Handle(cls.fields()); | 1163 const Array& fields_array = Array::Handle(cls.fields()); |
1187 intptr_t len = fields_array.Length(); | 1164 intptr_t len = fields_array.Length(); |
1188 Field& field = Field::Handle(); | 1165 Field& field = Field::Handle(); |
1189 for (intptr_t i = 0; i < len; i++) { | 1166 for (intptr_t i = 0; i < len; i++) { |
1190 field ^= fields_array.At(i); | 1167 field ^= fields_array.At(i); |
1191 if (!field.is_static() && !field.is_final()) { | 1168 if (!field.is_static() && !field.is_final()) { |
1192 const String& class_name = String::Handle(cls.Name()); | 1169 const String& class_name = String::Handle(cls.Name()); |
1193 const String& field_name = String::Handle(field.name()); | 1170 const String& field_name = String::Handle(field.name()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 va_end(args); | 1249 va_end(args); |
1273 if (FLAG_warning_as_error) { | 1250 if (FLAG_warning_as_error) { |
1274 Isolate::Current()->long_jump_base()->Jump(1, error); | 1251 Isolate::Current()->long_jump_base()->Jump(1, error); |
1275 UNREACHABLE(); | 1252 UNREACHABLE(); |
1276 } else { | 1253 } else { |
1277 OS::Print("%s", error.ToErrorCString()); | 1254 OS::Print("%s", error.ToErrorCString()); |
1278 } | 1255 } |
1279 } | 1256 } |
1280 | 1257 |
1281 } // namespace dart | 1258 } // namespace dart |
OLD | NEW |