OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/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_malformed_type, false, |
| 18 "Report error for malformed types."); |
17 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); | 19 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
18 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 20 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
19 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 21 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
20 DEFINE_FLAG(bool, verify_implements, false, | |
21 "Verify that all classes implement their interface."); | |
22 DECLARE_FLAG(bool, enable_type_checks); | 22 DECLARE_FLAG(bool, enable_type_checks); |
23 | 23 |
24 | 24 |
25 bool ClassFinalizer::AllClassesFinalized() { | 25 bool ClassFinalizer::AllClassesFinalized() { |
26 ObjectStore* object_store = Isolate::Current()->object_store(); | 26 ObjectStore* object_store = Isolate::Current()->object_store(); |
27 const GrowableObjectArray& classes = | 27 const GrowableObjectArray& classes = |
28 GrowableObjectArray::Handle(object_store->pending_classes()); | 28 GrowableObjectArray::Handle(object_store->pending_classes()); |
29 return classes.Length() == 0; | 29 return classes.Length() == 0; |
30 } | 30 } |
31 | 31 |
32 | 32 |
33 // Class finalization occurs: | 33 // Class finalization occurs: |
34 // a) when bootstrap process completes (VerifyBootstrapClasses). | 34 // a) when bootstrap process completes (VerifyBootstrapClasses). |
35 // b) after the user classes are loaded (dart_api). | 35 // b) after the user classes are loaded (dart_api). |
36 bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) { | 36 bool ClassFinalizer::FinalizePendingClasses() { |
37 bool retval = true; | 37 bool retval = true; |
38 Isolate* isolate = Isolate::Current(); | 38 Isolate* isolate = Isolate::Current(); |
39 ASSERT(isolate != NULL); | 39 ASSERT(isolate != NULL); |
40 ObjectStore* object_store = isolate->object_store(); | 40 ObjectStore* object_store = isolate->object_store(); |
41 const Error& error = Error::Handle(object_store->sticky_error()); | 41 const Error& error = Error::Handle(object_store->sticky_error()); |
42 if (!error.IsNull()) { | 42 if (!error.IsNull()) { |
43 return false; | 43 return false; |
44 } | 44 } |
| 45 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
| 46 class_array = object_store->pending_classes(); |
| 47 ASSERT(!class_array.IsNull()); |
| 48 if (class_array.Length() == 0) { |
| 49 return true; |
| 50 } |
45 LongJump* base = isolate->long_jump_base(); | 51 LongJump* base = isolate->long_jump_base(); |
46 LongJump jump; | 52 LongJump jump; |
47 isolate->set_long_jump_base(&jump); | 53 isolate->set_long_jump_base(&jump); |
48 if (setjmp(*jump.Set()) == 0) { | 54 if (setjmp(*jump.Set()) == 0) { |
49 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); | |
50 class_array = object_store->pending_classes(); | |
51 ASSERT(!class_array.IsNull()); | |
52 Class& cls = Class::Handle(); | 55 Class& cls = Class::Handle(); |
53 // First resolve all superclasses. | 56 // First resolve all superclasses. |
54 for (intptr_t i = 0; i < class_array.Length(); i++) { | 57 for (intptr_t i = 0; i < class_array.Length(); i++) { |
55 cls ^= class_array.At(i); | 58 cls ^= class_array.At(i); |
56 if (FLAG_trace_class_finalization) { | 59 if (FLAG_trace_class_finalization) { |
57 OS::Print("Resolving super and default: %s\n", cls.ToCString()); | 60 OS::Print("Resolving super and default: %s\n", cls.ToCString()); |
58 } | 61 } |
59 ResolveSuperType(cls); | 62 ResolveSuperType(cls); |
60 if (cls.is_interface()) { | 63 if (cls.is_interface()) { |
61 ResolveFactoryClass(cls); | 64 ResolveFactoryClass(cls); |
62 } | 65 } |
63 } | 66 } |
64 // Finalize all classes. | 67 // Finalize all classes. |
65 for (intptr_t i = 0; i < class_array.Length(); i++) { | 68 for (intptr_t i = 0; i < class_array.Length(); i++) { |
66 cls ^= class_array.At(i); | 69 cls ^= class_array.At(i); |
67 FinalizeClass(cls, generating_snapshot); | 70 FinalizeClass(cls); |
68 } | 71 } |
69 if (FLAG_print_classes) { | 72 if (FLAG_print_classes) { |
70 for (intptr_t i = 0; i < class_array.Length(); i++) { | 73 for (intptr_t i = 0; i < class_array.Length(); i++) { |
71 cls ^= class_array.At(i); | 74 cls ^= class_array.At(i); |
72 PrintClassInformation(cls); | 75 PrintClassInformation(cls); |
73 } | 76 } |
74 } | 77 } |
75 if (FLAG_verify_implements) { | |
76 for (intptr_t i = 0; i < class_array.Length(); i++) { | |
77 cls ^= class_array.At(i); | |
78 if (!cls.is_interface()) { | |
79 VerifyClassImplements(cls); | |
80 } | |
81 } | |
82 } | |
83 // Clear pending classes array. | 78 // Clear pending classes array. |
84 class_array = GrowableObjectArray::New(); | 79 class_array = GrowableObjectArray::New(); |
85 object_store->set_pending_classes(class_array); | 80 object_store->set_pending_classes(class_array); |
86 } else { | 81 } else { |
87 retval = false; | 82 retval = false; |
88 } | 83 } |
89 isolate->set_long_jump_base(base); | 84 isolate->set_long_jump_base(base); |
90 return retval; | 85 return retval; |
91 } | 86 } |
92 | 87 |
93 | 88 |
94 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. | 89 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. |
95 // No cycles are allowed. | 90 // No cycles are allowed. |
96 void ClassFinalizer::CollectInterfaces(const Class& cls, | 91 void ClassFinalizer::CollectInterfaces(const Class& cls, |
97 const GrowableObjectArray& collected) { | 92 const GrowableObjectArray& collected) { |
98 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); | 93 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); |
99 AbstractType& interface = AbstractType::Handle(); | 94 AbstractType& interface = AbstractType::Handle(); |
100 Class& interface_class = Class::Handle(); | 95 Class& interface_class = Class::Handle(); |
101 for (intptr_t i = 0; i < interface_array.Length(); i++) { | 96 for (intptr_t i = 0; i < interface_array.Length(); i++) { |
102 interface ^= interface_array.At(i); | 97 interface ^= interface_array.At(i); |
103 interface_class = interface.type_class(); | 98 interface_class = interface.type_class(); |
104 collected.Add(interface_class); | 99 collected.Add(interface_class); |
105 CollectInterfaces(interface_class, collected); | 100 CollectInterfaces(interface_class, collected); |
106 } | 101 } |
107 } | 102 } |
108 | 103 |
109 | 104 |
110 #if defined (DEBUG) | |
111 // Collect all interfaces of the class 'cls' and check that every function | |
112 // defined in each interface can be found in the class. | |
113 // No need to check instance fields since they have been turned into | |
114 // getters/setters. | |
115 void ClassFinalizer::VerifyClassImplements(const Class& cls) { | |
116 ASSERT(!cls.is_interface()); | |
117 const GrowableObjectArray& interfaces = | |
118 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
119 CollectInterfaces(cls, interfaces); | |
120 const String& class_name = String::Handle(cls.Name()); | |
121 Class& interface_class = Class::Handle(); | |
122 String& interface_name = String::Handle(); | |
123 Array& interface_functions = Array::Handle(); | |
124 for (int i = 0; i < interfaces.Length(); i++) { | |
125 interface_class ^= interfaces.At(i); | |
126 interface_name = interface_class.Name(); | |
127 interface_functions = interface_class.functions(); | |
128 for (intptr_t f = 0; f < interface_functions.Length(); f++) { | |
129 Function& interface_function = Function::Handle(); | |
130 interface_function ^= interface_functions.At(f); | |
131 const String& function_name = String::Handle(interface_function.name()); | |
132 // Check for constructor/factory. | |
133 if (function_name.StartsWith(interface_name)) { | |
134 // TODO(srdjan): convert 'InterfaceName.' to 'ClassName.' and check. | |
135 continue; | |
136 } | |
137 if (interface_function.kind() == RawFunction::kConstImplicitGetter) { | |
138 // This interface constants are not overridable. | |
139 continue; | |
140 } | |
141 // Lookup function in 'cls' and all its super classes. | |
142 Class& test_class = Class::Handle(cls.raw()); | |
143 Function& class_function = | |
144 Function::Handle(test_class.LookupDynamicFunction(function_name)); | |
145 while (class_function.IsNull()) { | |
146 test_class = test_class.SuperClass(); | |
147 if (test_class.IsNull()) break; | |
148 class_function = test_class.LookupDynamicFunction(function_name); | |
149 } | |
150 if (class_function.IsNull()) { | |
151 OS::PrintErr("%s implements '%s' missing: '%s'\n", | |
152 class_name.ToCString(), | |
153 interface_name.ToCString(), | |
154 function_name.ToCString()); | |
155 } else { | |
156 Error& malformed_error = Error::Handle(); | |
157 if (!class_function.IsSubtypeOf(TypeArguments::Handle(), | |
158 interface_function, | |
159 TypeArguments::Handle(), | |
160 &malformed_error)) { | |
161 if (!malformed_error.IsNull()) { | |
162 OS::PrintErr("%s\n", malformed_error.ToErrorCString()); | |
163 } | |
164 OS::PrintErr("The type of instance method '%s' in class '%s' is not " | |
165 "a subtype of the type of '%s' in interface '%s'\n", | |
166 function_name.ToCString(), | |
167 class_name.ToCString(), | |
168 function_name.ToCString(), | |
169 interface_name.ToCString()); | |
170 } | |
171 } | |
172 } | |
173 } | |
174 } | |
175 #else | |
176 | |
177 void ClassFinalizer::VerifyClassImplements(const Class& cls) {} | |
178 | |
179 #endif | |
180 | |
181 | |
182 void ClassFinalizer::VerifyBootstrapClasses() { | 105 void ClassFinalizer::VerifyBootstrapClasses() { |
183 if (FLAG_trace_class_finalization) { | 106 if (FLAG_trace_class_finalization) { |
184 OS::Print("VerifyBootstrapClasses START.\n"); | 107 OS::Print("VerifyBootstrapClasses START.\n"); |
185 } | 108 } |
186 ObjectStore* object_store = Isolate::Current()->object_store(); | 109 ObjectStore* object_store = Isolate::Current()->object_store(); |
187 | 110 |
188 Class& cls = Class::Handle(); | 111 Class& cls = Class::Handle(); |
189 #if defined(DEBUG) | 112 #if defined(DEBUG) |
190 // Basic checking. | 113 // Basic checking. |
191 cls = object_store->object_class(); | 114 cls = object_store->object_class(); |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 594 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
672 if (!arguments.IsNull()) { | 595 if (!arguments.IsNull()) { |
673 intptr_t num_arguments = arguments.Length(); | 596 intptr_t num_arguments = arguments.Length(); |
674 AbstractType& type_argument = AbstractType::Handle(); | 597 AbstractType& type_argument = AbstractType::Handle(); |
675 for (intptr_t i = 0; i < num_arguments; i++) { | 598 for (intptr_t i = 0; i < num_arguments; i++) { |
676 type_argument = arguments.TypeAt(i); | 599 type_argument = arguments.TypeAt(i); |
677 type_argument = FinalizeType(cls, type_argument, finalization); | 600 type_argument = FinalizeType(cls, type_argument, finalization); |
678 if (type_argument.IsMalformed()) { | 601 if (type_argument.IsMalformed()) { |
679 // In production mode, malformed type arguments are mapped to Dynamic. | 602 // In production mode, malformed type arguments are mapped to Dynamic. |
680 // In checked mode, a type with malformed type arguments is malformed. | 603 // In checked mode, a type with malformed type arguments is malformed. |
681 if (FLAG_enable_type_checks) { | 604 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { |
682 const Error& error = Error::Handle(type_argument.malformed_error()); | 605 const Error& error = Error::Handle(type_argument.malformed_error()); |
683 const String& type_name = | 606 const String& type_name = |
684 String::Handle(parameterized_type.UserVisibleName()); | 607 String::Handle(parameterized_type.UserVisibleName()); |
685 FinalizeMalformedType(error, cls, parameterized_type, finalization, | 608 FinalizeMalformedType(error, cls, parameterized_type, finalization, |
686 "type '%s' has malformed type argument", | 609 "type '%s' has malformed type argument", |
687 type_name.ToCString()); | 610 type_name.ToCString()); |
688 return parameterized_type.raw(); | 611 return parameterized_type.raw(); |
689 } else { | 612 } else { |
690 type_argument = Type::DynamicType(); | 613 type_argument = Type::DynamicType(); |
691 } | 614 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 if (type_class.IsCanonicalSignatureClass()) { | 729 if (type_class.IsCanonicalSignatureClass()) { |
807 ASSERT(type_class.is_finalized()); | 730 ASSERT(type_class.is_finalized()); |
808 // Resolve and finalize the result and parameter types of the signature | 731 // Resolve and finalize the result and parameter types of the signature |
809 // function of this signature class. | 732 // function of this signature class. |
810 ASSERT(type_class.SignatureType() == type.raw()); | 733 ASSERT(type_class.SignatureType() == type.raw()); |
811 ResolveAndFinalizeSignature( | 734 ResolveAndFinalizeSignature( |
812 type_class, Function::Handle(type_class.signature_function())); | 735 type_class, Function::Handle(type_class.signature_function())); |
813 } else { | 736 } else { |
814 // This type is a function type alias. Its class may need to be finalized | 737 // This type is a function type alias. Its class may need to be finalized |
815 // and checked for illegal self reference. | 738 // and checked for illegal self reference. |
816 FinalizeClass(type_class, false); | 739 FinalizeClass(type_class); |
817 // Finalizing the signature function here (as in the canonical case above) | 740 // Finalizing the signature function here (as in the canonical case above) |
818 // would not mark the canonical signature type as finalized. | 741 // would not mark the canonical signature type as finalized. |
819 const Type& signature_type = Type::Handle(type_class.SignatureType()); | 742 const Type& signature_type = Type::Handle(type_class.SignatureType()); |
820 FinalizeType(cls, signature_type, finalization); | 743 FinalizeType(cls, signature_type, finalization); |
821 } | 744 } |
822 } | 745 } |
823 | 746 |
824 if (finalization >= kCanonicalize) { | 747 if (finalization >= kCanonicalize) { |
825 return parameterized_type.Canonicalize(); | 748 return parameterized_type.Canonicalize(); |
826 } else { | 749 } else { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 function_name.ToCString(), | 995 function_name.ToCString(), |
1073 class_name.ToCString(), | 996 class_name.ToCString(), |
1074 function_name.ToCString(), | 997 function_name.ToCString(), |
1075 super_class_name.ToCString()); | 998 super_class_name.ToCString()); |
1076 } | 999 } |
1077 } | 1000 } |
1078 } | 1001 } |
1079 } | 1002 } |
1080 | 1003 |
1081 | 1004 |
1082 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { | 1005 void ClassFinalizer::FinalizeClass(const Class& cls) { |
1083 if (cls.is_finalized()) { | 1006 if (cls.is_finalized()) { |
1084 return; | 1007 return; |
1085 } | 1008 } |
1086 if (FLAG_trace_class_finalization) { | 1009 if (FLAG_trace_class_finalization) { |
1087 OS::Print("Finalize %s\n", cls.ToCString()); | 1010 OS::Print("Finalize %s\n", cls.ToCString()); |
1088 } | 1011 } |
1089 if (!IsSuperCycleFree(cls)) { | 1012 if (!IsSuperCycleFree(cls)) { |
1090 const String& name = String::Handle(cls.Name()); | 1013 const String& name = String::Handle(cls.Name()); |
1091 const Script& script = Script::Handle(cls.script()); | 1014 const Script& script = Script::Handle(cls.script()); |
1092 ReportError(script, cls.token_pos(), | 1015 ReportError(script, cls.token_pos(), |
1093 "class '%s' has a cycle in its superclass relationship", | 1016 "class '%s' has a cycle in its superclass relationship", |
1094 name.ToCString()); | 1017 name.ToCString()); |
1095 } | 1018 } |
1096 GrowableArray<intptr_t> visited_interfaces; | 1019 GrowableArray<intptr_t> visited_interfaces; |
1097 ResolveInterfaces(cls, &visited_interfaces); | 1020 ResolveInterfaces(cls, &visited_interfaces); |
1098 // Finalize super class. | 1021 // Finalize super class. |
1099 const Class& super_class = Class::Handle(cls.SuperClass()); | 1022 const Class& super_class = Class::Handle(cls.SuperClass()); |
1100 if (!super_class.IsNull()) { | 1023 if (!super_class.IsNull()) { |
1101 FinalizeClass(super_class, generating_snapshot); | 1024 FinalizeClass(super_class); |
1102 } | 1025 } |
1103 // Finalize type parameters before finalizing the super type. | 1026 // Finalize type parameters before finalizing the super type. |
1104 FinalizeTypeParameters(cls); | 1027 FinalizeTypeParameters(cls); |
1105 // Finalize super type. | 1028 // Finalize super type. |
1106 Type& super_type = Type::Handle(cls.super_type()); | 1029 Type& super_type = Type::Handle(cls.super_type()); |
1107 if (!super_type.IsNull()) { | 1030 if (!super_type.IsNull()) { |
1108 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1031 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
1109 cls.set_super_type(super_type); | 1032 cls.set_super_type(super_type); |
1110 } | 1033 } |
1111 // Signature classes are finalized upon creation, except function type | 1034 // Signature classes are finalized upon creation, except function type |
(...skipping 13 matching lines...) Expand all Loading... |
1125 // Signature classes extend Object. No need to add this class to the direct | 1048 // Signature classes extend Object. No need to add this class to the direct |
1126 // subclasses of Object. | 1049 // subclasses of Object. |
1127 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1050 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
1128 return; | 1051 return; |
1129 } | 1052 } |
1130 // Finalize factory class, if any. | 1053 // Finalize factory class, if any. |
1131 if (cls.is_interface()) { | 1054 if (cls.is_interface()) { |
1132 if (cls.HasFactoryClass()) { | 1055 if (cls.HasFactoryClass()) { |
1133 const Class& factory_class = Class::Handle(cls.FactoryClass()); | 1056 const Class& factory_class = Class::Handle(cls.FactoryClass()); |
1134 if (!factory_class.is_finalized()) { | 1057 if (!factory_class.is_finalized()) { |
1135 FinalizeClass(factory_class, generating_snapshot); | 1058 FinalizeClass(factory_class); |
1136 // Finalizing the factory class may indirectly finalize this interface. | 1059 // Finalizing the factory class may indirectly finalize this interface. |
1137 if (cls.is_finalized()) { | 1060 if (cls.is_finalized()) { |
1138 return; | 1061 return; |
1139 } | 1062 } |
1140 } | 1063 } |
1141 } | 1064 } |
1142 } | 1065 } |
1143 // Finalize interface types (but not necessarily interface classes). | 1066 // Finalize interface types (but not necessarily interface classes). |
1144 Array& interface_types = Array::Handle(cls.interfaces()); | 1067 Array& interface_types = Array::Handle(cls.interfaces()); |
1145 AbstractType& interface_type = AbstractType::Handle(); | 1068 AbstractType& interface_type = AbstractType::Handle(); |
1146 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 1069 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
1147 interface_type ^= interface_types.At(i); | 1070 interface_type ^= interface_types.At(i); |
1148 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1071 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
1149 interface_types.SetAt(i, interface_type); | 1072 interface_types.SetAt(i, interface_type); |
1150 } | 1073 } |
1151 // Mark as finalized before resolving type parameter upper bounds and member | 1074 // Mark as finalized before resolving type parameter upper bounds and member |
1152 // types in order to break cycles. | 1075 // types in order to break cycles. |
1153 cls.Finalize(); | 1076 cls.Finalize(); |
1154 ResolveAndFinalizeUpperBounds(cls); | 1077 ResolveAndFinalizeUpperBounds(cls); |
1155 ResolveAndFinalizeMemberTypes(cls); | 1078 ResolveAndFinalizeMemberTypes(cls); |
1156 // Run additional checks after all types are finalized. | 1079 // Run additional checks after all types are finalized. |
1157 if (cls.is_const()) { | 1080 if (cls.is_const()) { |
1158 CheckForLegalConstClass(cls); | 1081 CheckForLegalConstClass(cls); |
1159 } | 1082 } |
1160 // Check to ensure we don't have classes with native fields in libraries | 1083 // Check to ensure we don't have classes with native fields in libraries |
1161 // which do not have a native resolver. | 1084 // which do not have a native resolver. |
1162 if (!generating_snapshot && cls.num_native_fields() != 0) { | 1085 if (cls.num_native_fields() != 0) { |
1163 const Library& lib = Library::Handle(cls.library()); | 1086 const Library& lib = Library::Handle(cls.library()); |
1164 if (lib.native_entry_resolver() == NULL) { | 1087 if (lib.native_entry_resolver() == NULL) { |
1165 const String& cls_name = String::Handle(cls.Name()); | 1088 const String& cls_name = String::Handle(cls.Name()); |
1166 const String& lib_name = String::Handle(lib.url()); | 1089 const String& lib_name = String::Handle(lib.url()); |
1167 const Script& script = Script::Handle(cls.script()); | 1090 const Script& script = Script::Handle(cls.script()); |
1168 ReportError(script, cls.token_pos(), | 1091 ReportError(script, cls.token_pos(), |
1169 "class '%s' is trying to extend a native fields class, " | 1092 "class '%s' is trying to extend a native fields class, " |
1170 "but library '%s' has no native resolvers", | 1093 "but library '%s' has no native resolvers", |
1171 cls_name.ToCString(), lib_name.ToCString()); | 1094 cls_name.ToCString(), lib_name.ToCString()); |
1172 } | 1095 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 return false; | 1170 return false; |
1248 } | 1171 } |
1249 } | 1172 } |
1250 } | 1173 } |
1251 } | 1174 } |
1252 visited->RemoveLast(); | 1175 visited->RemoveLast(); |
1253 return true; | 1176 return true; |
1254 } | 1177 } |
1255 | 1178 |
1256 | 1179 |
1257 bool ClassFinalizer::AddInterfaceIfUnique( | |
1258 const GrowableObjectArray& interface_list, | |
1259 const AbstractType& interface, | |
1260 AbstractType* conflicting) { | |
1261 String& interface_class_name = String::Handle(interface.ClassName()); | |
1262 String& existing_interface_class_name = String::Handle(); | |
1263 String& interface_name = String::Handle(); | |
1264 String& existing_interface_name = String::Handle(); | |
1265 AbstractType& other_interface = AbstractType::Handle(); | |
1266 for (intptr_t i = 0; i < interface_list.Length(); i++) { | |
1267 other_interface ^= interface_list.At(i); | |
1268 existing_interface_class_name = other_interface.ClassName(); | |
1269 if (interface_class_name.Equals(existing_interface_class_name)) { | |
1270 // Same interface class name, now check names of type arguments. | |
1271 interface_name = interface.Name(); | |
1272 existing_interface_name = other_interface.Name(); | |
1273 // TODO(regis): Revisit depending on the outcome of issue 4905685. | |
1274 if (!interface_name.Equals(existing_interface_name)) { | |
1275 *conflicting = other_interface.raw(); | |
1276 return false; | |
1277 } else { | |
1278 return true; | |
1279 } | |
1280 } | |
1281 } | |
1282 interface_list.Add(interface); | |
1283 return true; | |
1284 } | |
1285 | |
1286 | |
1287 // Walks the graph of explicitly declared interfaces of classes and | 1180 // Walks the graph of explicitly declared interfaces of classes and |
1288 // interfaces recursively. Resolves unresolved interfaces. | 1181 // interfaces recursively. Resolves unresolved interfaces. |
1289 // Returns false if there is an interface reference that cannot be | 1182 // Returns false if there is an interface reference that cannot be |
1290 // resolved, or if there is a cycle in the graph. We detect cycles by | 1183 // resolved, or if there is a cycle in the graph. We detect cycles by |
1291 // remembering interfaces we've visited in each path through the | 1184 // remembering interfaces we've visited in each path through the |
1292 // graph. If we visit an interface a second time on a given path, | 1185 // graph. If we visit an interface a second time on a given path, |
1293 // we found a loop. | 1186 // we found a loop. |
1294 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1187 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
1295 GrowableArray<intptr_t>* visited) { | 1188 GrowableArray<intptr_t>* visited) { |
1296 ASSERT(visited != NULL); | 1189 ASSERT(visited != NULL); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, | 1340 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
1448 const Class& cls, | 1341 const Class& cls, |
1449 const Type& type, | 1342 const Type& type, |
1450 FinalizationKind finalization, | 1343 FinalizationKind finalization, |
1451 const char* format, ...) { | 1344 const char* format, ...) { |
1452 va_list args; | 1345 va_list args; |
1453 va_start(args, format); | 1346 va_start(args, format); |
1454 LanguageError& error = LanguageError::Handle(); | 1347 LanguageError& error = LanguageError::Handle(); |
1455 if (FLAG_enable_type_checks || | 1348 if (FLAG_enable_type_checks || |
1456 !type.HasResolvedTypeClass() || | 1349 !type.HasResolvedTypeClass() || |
1457 (finalization == kCanonicalizeWellFormed)) { | 1350 (finalization == kCanonicalizeWellFormed) || |
| 1351 FLAG_error_on_malformed_type) { |
1458 const Script& script = Script::Handle(cls.script()); | 1352 const Script& script = Script::Handle(cls.script()); |
1459 if (prev_error.IsNull()) { | 1353 if (prev_error.IsNull()) { |
1460 error ^= Parser::FormatError( | 1354 error ^= Parser::FormatError( |
1461 script, type.token_pos(), "Error", format, args); | 1355 script, type.token_pos(), "Error", format, args); |
1462 } else { | 1356 } else { |
1463 error ^= Parser::FormatErrorWithAppend( | 1357 error ^= Parser::FormatErrorWithAppend( |
1464 prev_error, script, type.token_pos(), "Error", format, args); | 1358 prev_error, script, type.token_pos(), "Error", format, args); |
1465 } | 1359 } |
1466 if (finalization == kCanonicalizeWellFormed) { | 1360 if ((finalization == kCanonicalizeWellFormed) || |
| 1361 FLAG_error_on_malformed_type) { |
1467 ReportError(error); | 1362 ReportError(error); |
1468 } | 1363 } |
1469 } | 1364 } |
1470 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { | 1365 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
1471 // In check mode, always mark the type as malformed. | 1366 // In check mode, always mark the type as malformed. |
1472 // In production mode, mark the type as malformed only if its type class is | 1367 // In production mode, mark the type as malformed only if its type class is |
1473 // not resolved. | 1368 // not resolved. |
1474 type.set_malformed_error(error); | 1369 type.set_malformed_error(error); |
1475 } else { | 1370 } else { |
1476 // In production mode, do not mark the type with a resolved type class as | 1371 // In production mode, do not mark the type with a resolved type class as |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1509 void ClassFinalizer::ReportError(const char* format, ...) { | 1404 void ClassFinalizer::ReportError(const char* format, ...) { |
1510 va_list args; | 1405 va_list args; |
1511 va_start(args, format); | 1406 va_start(args, format); |
1512 const Error& error = Error::Handle( | 1407 const Error& error = Error::Handle( |
1513 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1408 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1514 va_end(args); | 1409 va_end(args); |
1515 ReportError(error); | 1410 ReportError(error); |
1516 } | 1411 } |
1517 | 1412 |
1518 } // namespace dart | 1413 } // namespace dart |
OLD | NEW |