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, print_classes, false, "Prints details about loaded classes."); | 17 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
18 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 18 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
19 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 19 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); | 20 DECLARE_FLAG(bool, enable_type_checks); |
23 | 21 |
24 | 22 |
25 bool ClassFinalizer::AllClassesFinalized() { | 23 bool ClassFinalizer::AllClassesFinalized() { |
26 ObjectStore* object_store = Isolate::Current()->object_store(); | 24 ObjectStore* object_store = Isolate::Current()->object_store(); |
27 const GrowableObjectArray& classes = | 25 const GrowableObjectArray& classes = |
28 GrowableObjectArray::Handle(object_store->pending_classes()); | 26 GrowableObjectArray::Handle(object_store->pending_classes()); |
29 return classes.Length() == 0; | 27 return classes.Length() == 0; |
30 } | 28 } |
31 | 29 |
32 | 30 |
| 31 bool ClassFinalizer::FinalizeAllClasses() { |
| 32 ClassFinalizer class_finalizer(kNotGeneratingSnapshot); |
| 33 return class_finalizer.FinalizePendingClasses(); |
| 34 } |
| 35 |
| 36 |
33 // Class finalization occurs: | 37 // Class finalization occurs: |
34 // a) when bootstrap process completes (VerifyBootstrapClasses). | 38 // a) when bootstrap process completes (VerifyBootstrapClasses). |
35 // b) after the user classes are loaded (dart_api). | 39 // b) after the user classes are loaded (dart_api). |
36 bool ClassFinalizer::FinalizePendingClasses(bool generating_snapshot) { | 40 bool ClassFinalizer::FinalizePendingClasses() const { |
37 bool retval = true; | 41 bool retval = true; |
38 Isolate* isolate = Isolate::Current(); | 42 Isolate* isolate = Isolate::Current(); |
39 ASSERT(isolate != NULL); | 43 ASSERT(isolate != NULL); |
40 ObjectStore* object_store = isolate->object_store(); | 44 ObjectStore* object_store = isolate->object_store(); |
41 const Error& error = Error::Handle(object_store->sticky_error()); | 45 const Error& error = Error::Handle(object_store->sticky_error()); |
42 if (!error.IsNull()) { | 46 if (!error.IsNull()) { |
43 return false; | 47 return false; |
44 } | 48 } |
45 LongJump* base = isolate->long_jump_base(); | 49 LongJump* base = isolate->long_jump_base(); |
46 LongJump jump; | 50 LongJump jump; |
(...skipping 10 matching lines...) Expand all Loading... |
57 OS::Print("Resolving super and default: %s\n", cls.ToCString()); | 61 OS::Print("Resolving super and default: %s\n", cls.ToCString()); |
58 } | 62 } |
59 ResolveSuperType(cls); | 63 ResolveSuperType(cls); |
60 if (cls.is_interface()) { | 64 if (cls.is_interface()) { |
61 ResolveFactoryClass(cls); | 65 ResolveFactoryClass(cls); |
62 } | 66 } |
63 } | 67 } |
64 // Finalize all classes. | 68 // Finalize all classes. |
65 for (intptr_t i = 0; i < class_array.Length(); i++) { | 69 for (intptr_t i = 0; i < class_array.Length(); i++) { |
66 cls ^= class_array.At(i); | 70 cls ^= class_array.At(i); |
67 FinalizeClass(cls, generating_snapshot); | 71 FinalizeClass(cls); |
68 } | 72 } |
69 if (FLAG_print_classes) { | 73 if (FLAG_print_classes) { |
70 for (intptr_t i = 0; i < class_array.Length(); i++) { | 74 for (intptr_t i = 0; i < class_array.Length(); i++) { |
71 cls ^= class_array.At(i); | 75 cls ^= class_array.At(i); |
72 PrintClassInformation(cls); | 76 PrintClassInformation(cls); |
73 } | 77 } |
74 } | 78 } |
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. | 79 // Clear pending classes array. |
84 class_array = GrowableObjectArray::New(); | 80 class_array = GrowableObjectArray::New(); |
85 object_store->set_pending_classes(class_array); | 81 object_store->set_pending_classes(class_array); |
86 } else { | 82 } else { |
87 retval = false; | 83 retval = false; |
88 } | 84 } |
89 isolate->set_long_jump_base(base); | 85 isolate->set_long_jump_base(base); |
90 return retval; | 86 return retval; |
91 } | 87 } |
92 | 88 |
93 | 89 |
94 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. | 90 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. |
95 // No cycles are allowed. | 91 // No cycles are allowed. |
96 void ClassFinalizer::CollectInterfaces(const Class& cls, | 92 void ClassFinalizer::CollectInterfaces(const Class& cls, |
97 const GrowableObjectArray& collected) { | 93 const GrowableObjectArray& collected) { |
98 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); | 94 const Array& interface_array = Array::ZoneHandle(cls.interfaces()); |
99 AbstractType& interface = AbstractType::Handle(); | 95 AbstractType& interface = AbstractType::Handle(); |
100 Class& interface_class = Class::Handle(); | 96 Class& interface_class = Class::Handle(); |
101 for (intptr_t i = 0; i < interface_array.Length(); i++) { | 97 for (intptr_t i = 0; i < interface_array.Length(); i++) { |
102 interface ^= interface_array.At(i); | 98 interface ^= interface_array.At(i); |
103 interface_class = interface.type_class(); | 99 interface_class = interface.type_class(); |
104 collected.Add(interface_class); | 100 collected.Add(interface_class); |
105 CollectInterfaces(interface_class, collected); | 101 CollectInterfaces(interface_class, collected); |
106 } | 102 } |
107 } | 103 } |
108 | 104 |
109 | 105 |
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() { | 106 void ClassFinalizer::VerifyBootstrapClasses() { |
183 if (FLAG_trace_class_finalization) { | 107 if (FLAG_trace_class_finalization) { |
184 OS::Print("VerifyBootstrapClasses START.\n"); | 108 OS::Print("VerifyBootstrapClasses START.\n"); |
185 } | 109 } |
186 ObjectStore* object_store = Isolate::Current()->object_store(); | 110 ObjectStore* object_store = Isolate::Current()->object_store(); |
187 | 111 |
188 Class& cls = Class::Handle(); | 112 Class& cls = Class::Handle(); |
189 #if defined(DEBUG) | 113 #if defined(DEBUG) |
190 // Basic checking. | 114 // Basic checking. |
191 cls = object_store->object_class(); | 115 cls = object_store->object_class(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 for (intptr_t i = 0; i < class_array.Length(); i++) { | 190 for (intptr_t i = 0; i < class_array.Length(); i++) { |
267 // TODO(iposva): Add real checks. | 191 // TODO(iposva): Add real checks. |
268 cls ^= class_array.At(i); | 192 cls ^= class_array.At(i); |
269 if (cls.is_finalized() || cls.is_prefinalized()) { | 193 if (cls.is_finalized() || cls.is_prefinalized()) { |
270 // Pre-finalized bootstrap classes must not define any fields. | 194 // Pre-finalized bootstrap classes must not define any fields. |
271 ASSERT(!cls.HasInstanceFields()); | 195 ASSERT(!cls.HasInstanceFields()); |
272 } | 196 } |
273 } | 197 } |
274 | 198 |
275 // Finalize classes that aren't pre-finalized by Object::Init(). | 199 // Finalize classes that aren't pre-finalized by Object::Init(). |
276 if (!FinalizePendingClasses()) { | 200 ClassFinalizer class_finalizer(kGeneratingSnapshot); |
| 201 if (!class_finalizer.FinalizePendingClasses()) { |
277 // TODO(srdjan): Exit like a real VM instead. | 202 // TODO(srdjan): Exit like a real VM instead. |
278 const Error& err = Error::Handle(object_store->sticky_error()); | 203 const Error& err = Error::Handle(object_store->sticky_error()); |
279 OS::PrintErr("Could not verify bootstrap classes : %s\n", | 204 OS::PrintErr("Could not verify bootstrap classes : %s\n", |
280 err.ToErrorCString()); | 205 err.ToErrorCString()); |
281 OS::Exit(255); | 206 OS::Exit(255); |
282 } | 207 } |
283 if (FLAG_trace_class_finalization) { | 208 if (FLAG_trace_class_finalization) { |
284 OS::Print("VerifyBootstrapClasses END.\n"); | 209 OS::Print("VerifyBootstrapClasses END.\n"); |
285 } | 210 } |
286 Isolate::Current()->heap()->Verify(); | 211 Isolate::Current()->heap()->Verify(); |
(...skipping 14 matching lines...) Expand all Loading... |
301 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); | 226 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); |
302 lib_prefix = unresolved_class.library_prefix(); | 227 lib_prefix = unresolved_class.library_prefix(); |
303 ASSERT(!lib_prefix.IsNull()); | 228 ASSERT(!lib_prefix.IsNull()); |
304 resolved_class = lib_prefix.LookupLocalClass(class_name); | 229 resolved_class = lib_prefix.LookupLocalClass(class_name); |
305 } | 230 } |
306 return resolved_class.raw(); | 231 return resolved_class.raw(); |
307 } | 232 } |
308 | 233 |
309 | 234 |
310 // Resolve unresolved supertype (String -> Class). | 235 // Resolve unresolved supertype (String -> Class). |
311 void ClassFinalizer::ResolveSuperType(const Class& cls) { | 236 void ClassFinalizer::ResolveSuperType(const Class& cls) const { |
312 if (cls.is_finalized()) { | 237 if (cls.is_finalized()) { |
313 return; | 238 return; |
314 } | 239 } |
315 Type& super_type = Type::Handle(cls.super_type()); | 240 Type& super_type = Type::Handle(cls.super_type()); |
316 if (super_type.IsNull()) { | 241 if (super_type.IsNull()) { |
317 return; | 242 return; |
318 } | 243 } |
319 // Resolve failures lead to a longjmp. | 244 // Resolve failures lead to a longjmp. |
320 ResolveType(cls, super_type, kCanonicalizeWellFormed); | 245 ResolveType(cls, super_type, kCanonicalizeWellFormed); |
321 const Class& super_class = Class::Handle(super_type.type_class()); | 246 const Class& super_class = Class::Handle(super_type.type_class()); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 "mismatch in number or names of type parameters between " | 385 "mismatch in number or names of type parameters between " |
461 "interface '%s' and default factory class '%s'", | 386 "interface '%s' and default factory class '%s'", |
462 interface_name.ToCString(), | 387 interface_name.ToCString(), |
463 factory_name.ToCString()); | 388 factory_name.ToCString()); |
464 } | 389 } |
465 } | 390 } |
466 | 391 |
467 | 392 |
468 void ClassFinalizer::ResolveType(const Class& cls, | 393 void ClassFinalizer::ResolveType(const Class& cls, |
469 const AbstractType& type, | 394 const AbstractType& type, |
470 FinalizationKind finalization) { | 395 FinalizationKind finalization) const { |
471 if (type.IsResolved() || type.IsFinalized()) { | 396 if (type.IsResolved() || type.IsFinalized()) { |
472 return; | 397 return; |
473 } | 398 } |
474 if (FLAG_trace_type_finalization) { | 399 if (FLAG_trace_type_finalization) { |
475 OS::Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); | 400 OS::Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); |
476 } | 401 } |
477 | 402 |
478 // Resolve the type class. | 403 // Resolve the type class. |
479 if (!type.HasResolvedTypeClass()) { | 404 if (!type.HasResolvedTypeClass()) { |
480 // Type parameters are always resolved in the parser in the correct | 405 // Type parameters are always resolved in the parser in the correct |
(...skipping 30 matching lines...) Expand all Loading... |
511 intptr_t num_arguments = arguments.Length(); | 436 intptr_t num_arguments = arguments.Length(); |
512 AbstractType& type_argument = AbstractType::Handle(); | 437 AbstractType& type_argument = AbstractType::Handle(); |
513 for (intptr_t i = 0; i < num_arguments; i++) { | 438 for (intptr_t i = 0; i < num_arguments; i++) { |
514 type_argument = arguments.TypeAt(i); | 439 type_argument = arguments.TypeAt(i); |
515 ResolveType(cls, type_argument, finalization); | 440 ResolveType(cls, type_argument, finalization); |
516 } | 441 } |
517 } | 442 } |
518 } | 443 } |
519 | 444 |
520 | 445 |
521 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { | 446 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) const { |
522 const TypeArguments& type_parameters = | 447 const TypeArguments& type_parameters = |
523 TypeArguments::Handle(cls.type_parameters()); | 448 TypeArguments::Handle(cls.type_parameters()); |
524 if (!type_parameters.IsNull()) { | 449 if (!type_parameters.IsNull()) { |
525 TypeParameter& type_parameter = TypeParameter::Handle(); | 450 TypeParameter& type_parameter = TypeParameter::Handle(); |
526 const intptr_t num_types = type_parameters.Length(); | 451 const intptr_t num_types = type_parameters.Length(); |
527 for (intptr_t i = 0; i < num_types; i++) { | 452 for (intptr_t i = 0; i < num_types; i++) { |
528 type_parameter ^= type_parameters.TypeAt(i); | 453 type_parameter ^= type_parameters.TypeAt(i); |
529 type_parameter ^= FinalizeType(cls, | 454 type_parameter ^= FinalizeType(cls, |
530 type_parameter, | 455 type_parameter, |
531 kCanonicalizeWellFormed); | 456 kCanonicalizeWellFormed); |
(...skipping 13 matching lines...) Expand all Loading... |
545 // Example: | 470 // Example: |
546 // Declared: class C<K, V> extends B<V> { ... } | 471 // Declared: class C<K, V> extends B<V> { ... } |
547 // class B<T> extends A<int> { ... } | 472 // class B<T> extends A<int> { ... } |
548 // Input: C<String, double> expressed as | 473 // Input: C<String, double> expressed as |
549 // cls = C, arguments = [null, null, String, double], | 474 // cls = C, arguments = [null, null, String, double], |
550 // i.e. cls_args = [String, double], offset = 2, length = 2. | 475 // i.e. cls_args = [String, double], offset = 2, length = 2. |
551 // Output: arguments = [int, double, String, double] | 476 // Output: arguments = [int, double, String, double] |
552 void ClassFinalizer::FinalizeTypeArguments( | 477 void ClassFinalizer::FinalizeTypeArguments( |
553 const Class& cls, | 478 const Class& cls, |
554 const AbstractTypeArguments& arguments, | 479 const AbstractTypeArguments& arguments, |
555 FinalizationKind finalization) { | 480 FinalizationKind finalization) const { |
556 ASSERT(arguments.Length() >= cls.NumTypeArguments()); | 481 ASSERT(arguments.Length() >= cls.NumTypeArguments()); |
557 if (!cls.is_finalized()) { | 482 if (!cls.is_finalized()) { |
558 GrowableArray<intptr_t> visited_interfaces; | 483 GrowableArray<intptr_t> visited_interfaces; |
559 ResolveInterfaces(cls, &visited_interfaces); | 484 ResolveInterfaces(cls, &visited_interfaces); |
560 FinalizeTypeParameters(cls); | 485 FinalizeTypeParameters(cls); |
561 } | 486 } |
562 Type& super_type = Type::Handle(cls.super_type()); | 487 Type& super_type = Type::Handle(cls.super_type()); |
563 if (!super_type.IsNull()) { | 488 if (!super_type.IsNull()) { |
564 const Class& super_class = Class::Handle(super_type.type_class()); | 489 const Class& super_class = Class::Handle(super_type.type_class()); |
565 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); | 490 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 super_type_arg = super_type_arg.Canonicalize(); | 524 super_type_arg = super_type_arg.Canonicalize(); |
600 } | 525 } |
601 } | 526 } |
602 arguments.SetTypeAt(super_offset + i, super_type_arg); | 527 arguments.SetTypeAt(super_offset + i, super_type_arg); |
603 } | 528 } |
604 FinalizeTypeArguments(super_class, arguments, finalization); | 529 FinalizeTypeArguments(super_class, arguments, finalization); |
605 } | 530 } |
606 } | 531 } |
607 | 532 |
608 | 533 |
609 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, | 534 RawAbstractType* ClassFinalizer::FinalizeType( |
610 const AbstractType& type, | 535 const Class& cls, |
611 FinalizationKind finalization) { | 536 const AbstractType& type, |
| 537 FinalizationKind finalization) const { |
612 if (type.IsFinalized()) { | 538 if (type.IsFinalized()) { |
613 return type.raw(); | 539 return type.raw(); |
614 } | 540 } |
615 ASSERT(type.IsResolved()); | 541 ASSERT(type.IsResolved()); |
616 ASSERT(finalization >= kFinalize); | 542 ASSERT(finalization >= kFinalize); |
617 | 543 |
618 if (FLAG_trace_type_finalization) { | 544 if (FLAG_trace_type_finalization) { |
619 OS::Print("Finalize type '%s'\n", String::Handle(type.Name()).ToCString()); | 545 OS::Print("Finalize type '%s'\n", String::Handle(type.Name()).ToCString()); |
620 } | 546 } |
621 | 547 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 597 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
672 if (!arguments.IsNull()) { | 598 if (!arguments.IsNull()) { |
673 intptr_t num_arguments = arguments.Length(); | 599 intptr_t num_arguments = arguments.Length(); |
674 AbstractType& type_argument = AbstractType::Handle(); | 600 AbstractType& type_argument = AbstractType::Handle(); |
675 for (intptr_t i = 0; i < num_arguments; i++) { | 601 for (intptr_t i = 0; i < num_arguments; i++) { |
676 type_argument = arguments.TypeAt(i); | 602 type_argument = arguments.TypeAt(i); |
677 type_argument = FinalizeType(cls, type_argument, finalization); | 603 type_argument = FinalizeType(cls, type_argument, finalization); |
678 if (type_argument.IsMalformed()) { | 604 if (type_argument.IsMalformed()) { |
679 // In production mode, malformed type arguments are mapped to Dynamic. | 605 // In production mode, malformed type arguments are mapped to Dynamic. |
680 // In checked mode, a type with malformed type arguments is malformed. | 606 // In checked mode, a type with malformed type arguments is malformed. |
681 if (FLAG_enable_type_checks) { | 607 if (FLAG_enable_type_checks || generating_snapshot_) { |
682 const Error& error = Error::Handle(type_argument.malformed_error()); | 608 const Error& error = Error::Handle(type_argument.malformed_error()); |
683 const String& type_name = | 609 const String& type_name = |
684 String::Handle(parameterized_type.UserVisibleName()); | 610 String::Handle(parameterized_type.UserVisibleName()); |
685 FinalizeMalformedType(error, cls, parameterized_type, finalization, | 611 FinalizeMalformedType(error, cls, parameterized_type, finalization, |
686 "type '%s' has malformed type argument", | 612 "type '%s' has malformed type argument", |
687 type_name.ToCString()); | 613 type_name.ToCString()); |
688 return parameterized_type.raw(); | 614 return parameterized_type.raw(); |
689 } else { | 615 } else { |
690 type_argument = Type::DynamicType(); | 616 type_argument = Type::DynamicType(); |
691 } | 617 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 if (type_class.IsCanonicalSignatureClass()) { | 732 if (type_class.IsCanonicalSignatureClass()) { |
807 ASSERT(type_class.is_finalized()); | 733 ASSERT(type_class.is_finalized()); |
808 // Resolve and finalize the result and parameter types of the signature | 734 // Resolve and finalize the result and parameter types of the signature |
809 // function of this signature class. | 735 // function of this signature class. |
810 ASSERT(type_class.SignatureType() == type.raw()); | 736 ASSERT(type_class.SignatureType() == type.raw()); |
811 ResolveAndFinalizeSignature( | 737 ResolveAndFinalizeSignature( |
812 type_class, Function::Handle(type_class.signature_function())); | 738 type_class, Function::Handle(type_class.signature_function())); |
813 } else { | 739 } else { |
814 // This type is a function type alias. Its class may need to be finalized | 740 // This type is a function type alias. Its class may need to be finalized |
815 // and checked for illegal self reference. | 741 // and checked for illegal self reference. |
816 FinalizeClass(type_class, false); | 742 FinalizeClass(type_class); |
817 // Finalizing the signature function here (as in the canonical case above) | 743 // Finalizing the signature function here (as in the canonical case above) |
818 // would not mark the canonical signature type as finalized. | 744 // would not mark the canonical signature type as finalized. |
819 const Type& signature_type = Type::Handle(type_class.SignatureType()); | 745 const Type& signature_type = Type::Handle(type_class.SignatureType()); |
820 FinalizeType(cls, signature_type, finalization); | 746 FinalizeType(cls, signature_type, finalization); |
821 } | 747 } |
822 } | 748 } |
823 | 749 |
824 if (finalization >= kCanonicalize) { | 750 if (finalization >= kCanonicalize) { |
825 return parameterized_type.Canonicalize(); | 751 return parameterized_type.Canonicalize(); |
826 } else { | 752 } else { |
827 return parameterized_type.raw(); | 753 return parameterized_type.raw(); |
828 } | 754 } |
829 } | 755 } |
830 | 756 |
831 | 757 |
832 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, | 758 void ClassFinalizer::ResolveAndFinalizeSignature( |
833 const Function& function) { | 759 const Class& cls, |
| 760 const Function& function) const { |
834 // Resolve result type. | 761 // Resolve result type. |
835 AbstractType& type = AbstractType::Handle(function.result_type()); | 762 AbstractType& type = AbstractType::Handle(function.result_type()); |
836 // In case of a factory, the parser sets the factory result type to a type | 763 // In case of a factory, the parser sets the factory result type to a type |
837 // with an unresolved class whose name matches the factory name. | 764 // with an unresolved class whose name matches the factory name. |
838 // It is not a compile time error if this name does not resolve to a class or | 765 // It is not a compile time error if this name does not resolve to a class or |
839 // interface. | 766 // interface. |
840 ResolveType(cls, type, kCanonicalize); | 767 ResolveType(cls, type, kCanonicalize); |
841 type = FinalizeType(cls, type, kCanonicalize); | 768 type = FinalizeType(cls, type, kCanonicalize); |
842 // In production mode, a malformed result type is mapped to Dynamic. | 769 // In production mode, a malformed result type is mapped to Dynamic. |
843 if (!FLAG_enable_type_checks && type.IsMalformed()) { | 770 if (!FLAG_enable_type_checks && type.IsMalformed()) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 if (!function.IsNull()) { | 819 if (!function.IsNull()) { |
893 return super_class.raw(); | 820 return super_class.raw(); |
894 } | 821 } |
895 super_class = super_class.SuperClass(); | 822 super_class = super_class.SuperClass(); |
896 } | 823 } |
897 return Class::null(); | 824 return Class::null(); |
898 } | 825 } |
899 | 826 |
900 | 827 |
901 // Resolve and finalize the upper bounds of the type parameters of class cls. | 828 // Resolve and finalize the upper bounds of the type parameters of class cls. |
902 void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) { | 829 void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) const { |
903 const intptr_t num_type_params = cls.NumTypeParameters(); | 830 const intptr_t num_type_params = cls.NumTypeParameters(); |
904 TypeParameter& type_param = TypeParameter::Handle(); | 831 TypeParameter& type_param = TypeParameter::Handle(); |
905 AbstractType& bound = AbstractType::Handle(); | 832 AbstractType& bound = AbstractType::Handle(); |
906 const AbstractTypeArguments& type_params = | 833 const AbstractTypeArguments& type_params = |
907 AbstractTypeArguments::Handle(cls.type_parameters()); | 834 AbstractTypeArguments::Handle(cls.type_parameters()); |
908 ASSERT((type_params.IsNull() && (num_type_params == 0)) || | 835 ASSERT((type_params.IsNull() && (num_type_params == 0)) || |
909 (type_params.Length() == num_type_params)); | 836 (type_params.Length() == num_type_params)); |
910 for (intptr_t i = 0; i < num_type_params; i++) { | 837 for (intptr_t i = 0; i < num_type_params; i++) { |
911 type_param ^= type_params.TypeAt(i); | 838 type_param ^= type_params.TypeAt(i); |
912 bound = type_param.bound(); | 839 bound = type_param.bound(); |
913 if (bound.IsFinalized()) { | 840 if (bound.IsFinalized()) { |
914 continue; | 841 continue; |
915 } | 842 } |
916 ResolveType(cls, bound, kCanonicalize); | 843 ResolveType(cls, bound, kCanonicalize); |
917 bound = FinalizeType(cls, bound, kCanonicalize); | 844 bound = FinalizeType(cls, bound, kCanonicalize); |
918 type_param.set_bound(bound); | 845 type_param.set_bound(bound); |
919 } | 846 } |
920 } | 847 } |
921 | 848 |
922 | 849 |
923 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { | 850 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) const { |
924 // Note that getters and setters are explicitly listed as such in the list of | 851 // Note that getters and setters are explicitly listed as such in the list of |
925 // functions of a class, so we do not need to consider fields as implicitly | 852 // functions of a class, so we do not need to consider fields as implicitly |
926 // generating getters and setters. | 853 // generating getters and setters. |
927 // The only compile errors we report are therefore: | 854 // The only compile errors we report are therefore: |
928 // - a getter having the same name as a method (but not a getter) in a super | 855 // - a getter having the same name as a method (but not a getter) in a super |
929 // class or in a subclass. | 856 // class or in a subclass. |
930 // - a setter having the same name as a method (but not a setter) in a super | 857 // - a setter having the same name as a method (but not a setter) in a super |
931 // class or in a subclass. | 858 // class or in a subclass. |
932 // - a static field, instance field, or static method (but not an instance | 859 // - a static field, instance field, or static method (but not an instance |
933 // method) having the same name as an instance member in a super class. | 860 // method) having the same name as an instance member in a super class. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 function_name.ToCString(), | 999 function_name.ToCString(), |
1073 class_name.ToCString(), | 1000 class_name.ToCString(), |
1074 function_name.ToCString(), | 1001 function_name.ToCString(), |
1075 super_class_name.ToCString()); | 1002 super_class_name.ToCString()); |
1076 } | 1003 } |
1077 } | 1004 } |
1078 } | 1005 } |
1079 } | 1006 } |
1080 | 1007 |
1081 | 1008 |
1082 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { | 1009 void ClassFinalizer::FinalizeClass(const Class& cls) const { |
1083 if (cls.is_finalized()) { | 1010 if (cls.is_finalized()) { |
1084 return; | 1011 return; |
1085 } | 1012 } |
1086 if (FLAG_trace_class_finalization) { | 1013 if (FLAG_trace_class_finalization) { |
1087 OS::Print("Finalize %s\n", cls.ToCString()); | 1014 OS::Print("Finalize %s\n", cls.ToCString()); |
1088 } | 1015 } |
1089 if (!IsSuperCycleFree(cls)) { | 1016 if (!IsSuperCycleFree(cls)) { |
1090 const String& name = String::Handle(cls.Name()); | 1017 const String& name = String::Handle(cls.Name()); |
1091 const Script& script = Script::Handle(cls.script()); | 1018 const Script& script = Script::Handle(cls.script()); |
1092 ReportError(script, cls.token_pos(), | 1019 ReportError(script, cls.token_pos(), |
1093 "class '%s' has a cycle in its superclass relationship", | 1020 "class '%s' has a cycle in its superclass relationship", |
1094 name.ToCString()); | 1021 name.ToCString()); |
1095 } | 1022 } |
1096 GrowableArray<intptr_t> visited_interfaces; | 1023 GrowableArray<intptr_t> visited_interfaces; |
1097 ResolveInterfaces(cls, &visited_interfaces); | 1024 ResolveInterfaces(cls, &visited_interfaces); |
1098 // Finalize super class. | 1025 // Finalize super class. |
1099 const Class& super_class = Class::Handle(cls.SuperClass()); | 1026 const Class& super_class = Class::Handle(cls.SuperClass()); |
1100 if (!super_class.IsNull()) { | 1027 if (!super_class.IsNull()) { |
1101 FinalizeClass(super_class, generating_snapshot); | 1028 FinalizeClass(super_class); |
1102 } | 1029 } |
1103 // Finalize type parameters before finalizing the super type. | 1030 // Finalize type parameters before finalizing the super type. |
1104 FinalizeTypeParameters(cls); | 1031 FinalizeTypeParameters(cls); |
1105 // Finalize super type. | 1032 // Finalize super type. |
1106 Type& super_type = Type::Handle(cls.super_type()); | 1033 Type& super_type = Type::Handle(cls.super_type()); |
1107 if (!super_type.IsNull()) { | 1034 if (!super_type.IsNull()) { |
1108 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1035 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
1109 cls.set_super_type(super_type); | 1036 cls.set_super_type(super_type); |
1110 } | 1037 } |
1111 // Signature classes are finalized upon creation, except function type | 1038 // 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 | 1052 // Signature classes extend Object. No need to add this class to the direct |
1126 // subclasses of Object. | 1053 // subclasses of Object. |
1127 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1054 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
1128 return; | 1055 return; |
1129 } | 1056 } |
1130 // Finalize factory class, if any. | 1057 // Finalize factory class, if any. |
1131 if (cls.is_interface()) { | 1058 if (cls.is_interface()) { |
1132 if (cls.HasFactoryClass()) { | 1059 if (cls.HasFactoryClass()) { |
1133 const Class& factory_class = Class::Handle(cls.FactoryClass()); | 1060 const Class& factory_class = Class::Handle(cls.FactoryClass()); |
1134 if (!factory_class.is_finalized()) { | 1061 if (!factory_class.is_finalized()) { |
1135 FinalizeClass(factory_class, generating_snapshot); | 1062 FinalizeClass(factory_class); |
1136 // Finalizing the factory class may indirectly finalize this interface. | 1063 // Finalizing the factory class may indirectly finalize this interface. |
1137 if (cls.is_finalized()) { | 1064 if (cls.is_finalized()) { |
1138 return; | 1065 return; |
1139 } | 1066 } |
1140 } | 1067 } |
1141 } | 1068 } |
1142 } | 1069 } |
1143 // Finalize interface types (but not necessarily interface classes). | 1070 // Finalize interface types (but not necessarily interface classes). |
1144 Array& interface_types = Array::Handle(cls.interfaces()); | 1071 Array& interface_types = Array::Handle(cls.interfaces()); |
1145 AbstractType& interface_type = AbstractType::Handle(); | 1072 AbstractType& interface_type = AbstractType::Handle(); |
1146 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 1073 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
1147 interface_type ^= interface_types.At(i); | 1074 interface_type ^= interface_types.At(i); |
1148 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1075 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
1149 interface_types.SetAt(i, interface_type); | 1076 interface_types.SetAt(i, interface_type); |
1150 } | 1077 } |
1151 // Mark as finalized before resolving type parameter upper bounds and member | 1078 // Mark as finalized before resolving type parameter upper bounds and member |
1152 // types in order to break cycles. | 1079 // types in order to break cycles. |
1153 cls.Finalize(); | 1080 cls.Finalize(); |
1154 ResolveAndFinalizeUpperBounds(cls); | 1081 ResolveAndFinalizeUpperBounds(cls); |
1155 ResolveAndFinalizeMemberTypes(cls); | 1082 ResolveAndFinalizeMemberTypes(cls); |
1156 // Run additional checks after all types are finalized. | 1083 // Run additional checks after all types are finalized. |
1157 if (cls.is_const()) { | 1084 if (cls.is_const()) { |
1158 CheckForLegalConstClass(cls); | 1085 CheckForLegalConstClass(cls); |
1159 } | 1086 } |
1160 // Check to ensure we don't have classes with native fields in libraries | 1087 // Check to ensure we don't have classes with native fields in libraries |
1161 // which do not have a native resolver. | 1088 // which do not have a native resolver. |
1162 if (!generating_snapshot && cls.num_native_fields() != 0) { | 1089 if (!generating_snapshot_ && cls.num_native_fields() != 0) { |
1163 const Library& lib = Library::Handle(cls.library()); | 1090 const Library& lib = Library::Handle(cls.library()); |
1164 if (lib.native_entry_resolver() == NULL) { | 1091 if (lib.native_entry_resolver() == NULL) { |
1165 const String& cls_name = String::Handle(cls.Name()); | 1092 const String& cls_name = String::Handle(cls.Name()); |
1166 const String& lib_name = String::Handle(lib.url()); | 1093 const String& lib_name = String::Handle(lib.url()); |
1167 const Script& script = Script::Handle(cls.script()); | 1094 const Script& script = Script::Handle(cls.script()); |
1168 ReportError(script, cls.token_pos(), | 1095 ReportError(script, cls.token_pos(), |
1169 "class '%s' is trying to extend a native fields class, " | 1096 "class '%s' is trying to extend a native fields class, " |
1170 "but library '%s' has no native resolvers", | 1097 "but library '%s' has no native resolvers", |
1171 cls_name.ToCString(), lib_name.ToCString()); | 1098 cls_name.ToCString(), lib_name.ToCString()); |
1172 } | 1099 } |
(...skipping 24 matching lines...) Expand all Loading... |
1197 test2 = test2.SuperClass(); | 1124 test2 = test2.SuperClass(); |
1198 } | 1125 } |
1199 } | 1126 } |
1200 // No cycles. | 1127 // No cycles. |
1201 return true; | 1128 return true; |
1202 } | 1129 } |
1203 | 1130 |
1204 | 1131 |
1205 // Returns false if the function type alias illegally refers to itself. | 1132 // Returns false if the function type alias illegally refers to itself. |
1206 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, | 1133 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
1207 GrowableArray<intptr_t>* visited) { | 1134 GrowableArray<intptr_t>* visited) const { |
1208 ASSERT(cls.IsSignatureClass()); | 1135 ASSERT(cls.IsSignatureClass()); |
1209 ASSERT(!cls.IsCanonicalSignatureClass()); | 1136 ASSERT(!cls.IsCanonicalSignatureClass()); |
1210 ASSERT(!cls.is_finalized()); | 1137 ASSERT(!cls.is_finalized()); |
1211 ASSERT(visited != NULL); | 1138 ASSERT(visited != NULL); |
1212 const intptr_t cls_index = cls.id(); | 1139 const intptr_t cls_index = cls.id(); |
1213 for (int i = 0; i < visited->length(); i++) { | 1140 for (int i = 0; i < visited->length(); i++) { |
1214 if ((*visited)[i] == cls_index) { | 1141 if ((*visited)[i] == cls_index) { |
1215 // We have already visited alias 'cls'. We found a cycle. | 1142 // We have already visited alias 'cls'. We found a cycle. |
1216 return false; | 1143 return false; |
1217 } | 1144 } |
(...skipping 29 matching lines...) Expand all Loading... |
1247 return false; | 1174 return false; |
1248 } | 1175 } |
1249 } | 1176 } |
1250 } | 1177 } |
1251 } | 1178 } |
1252 visited->RemoveLast(); | 1179 visited->RemoveLast(); |
1253 return true; | 1180 return true; |
1254 } | 1181 } |
1255 | 1182 |
1256 | 1183 |
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 | 1184 // Walks the graph of explicitly declared interfaces of classes and |
1288 // interfaces recursively. Resolves unresolved interfaces. | 1185 // interfaces recursively. Resolves unresolved interfaces. |
1289 // Returns false if there is an interface reference that cannot be | 1186 // 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 | 1187 // 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 | 1188 // remembering interfaces we've visited in each path through the |
1292 // graph. If we visit an interface a second time on a given path, | 1189 // graph. If we visit an interface a second time on a given path, |
1293 // we found a loop. | 1190 // we found a loop. |
1294 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1191 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
1295 GrowableArray<intptr_t>* visited) { | 1192 GrowableArray<intptr_t>* visited) const { |
1296 ASSERT(visited != NULL); | 1193 ASSERT(visited != NULL); |
1297 const intptr_t cls_index = cls.id(); | 1194 const intptr_t cls_index = cls.id(); |
1298 for (int i = 0; i < visited->length(); i++) { | 1195 for (int i = 0; i < visited->length(); i++) { |
1299 if ((*visited)[i] == cls_index) { | 1196 if ((*visited)[i] == cls_index) { |
1300 // We have already visited interface class 'cls'. We found a cycle. | 1197 // We have already visited interface class 'cls'. We found a cycle. |
1301 const String& interface_name = String::Handle(cls.Name()); | 1198 const String& interface_name = String::Handle(cls.Name()); |
1302 const Script& script = Script::Handle(cls.script()); | 1199 const Script& script = Script::Handle(cls.script()); |
1303 ReportError(script, cls.token_pos(), | 1200 ReportError(script, cls.token_pos(), |
1304 "cyclic reference found for interface '%s'", | 1201 "cyclic reference found for interface '%s'", |
1305 interface_name.ToCString()); | 1202 interface_name.ToCString()); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1441 field ^= fields_array.At(i); | 1338 field ^= fields_array.At(i); |
1442 OS::Print(" %s\n", field.ToCString()); | 1339 OS::Print(" %s\n", field.ToCString()); |
1443 } | 1340 } |
1444 } | 1341 } |
1445 | 1342 |
1446 | 1343 |
1447 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, | 1344 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
1448 const Class& cls, | 1345 const Class& cls, |
1449 const Type& type, | 1346 const Type& type, |
1450 FinalizationKind finalization, | 1347 FinalizationKind finalization, |
1451 const char* format, ...) { | 1348 const char* format, ...) const { |
1452 va_list args; | 1349 va_list args; |
1453 va_start(args, format); | 1350 va_start(args, format); |
1454 LanguageError& error = LanguageError::Handle(); | 1351 LanguageError& error = LanguageError::Handle(); |
1455 if (FLAG_enable_type_checks || | 1352 if (FLAG_enable_type_checks || |
1456 !type.HasResolvedTypeClass() || | 1353 !type.HasResolvedTypeClass() || |
1457 (finalization == kCanonicalizeWellFormed)) { | 1354 (finalization == kCanonicalizeWellFormed) || |
| 1355 generating_snapshot_) { |
1458 const Script& script = Script::Handle(cls.script()); | 1356 const Script& script = Script::Handle(cls.script()); |
1459 if (prev_error.IsNull()) { | 1357 if (prev_error.IsNull()) { |
1460 error ^= Parser::FormatError( | 1358 error ^= Parser::FormatError( |
1461 script, type.token_pos(), "Error", format, args); | 1359 script, type.token_pos(), "Error", format, args); |
1462 } else { | 1360 } else { |
1463 error ^= Parser::FormatErrorWithAppend( | 1361 error ^= Parser::FormatErrorWithAppend( |
1464 prev_error, script, type.token_pos(), "Error", format, args); | 1362 prev_error, script, type.token_pos(), "Error", format, args); |
1465 } | 1363 } |
1466 if (finalization == kCanonicalizeWellFormed) { | 1364 if ((finalization == kCanonicalizeWellFormed) || generating_snapshot_) { |
1467 ReportError(error); | 1365 ReportError(error); |
1468 } | 1366 } |
1469 } | 1367 } |
1470 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { | 1368 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
1471 // In check mode, always mark the type as malformed. | 1369 // In check mode, always mark the type as malformed. |
1472 // In production mode, mark the type as malformed only if its type class is | 1370 // In production mode, mark the type as malformed only if its type class is |
1473 // not resolved. | 1371 // not resolved. |
1474 type.set_malformed_error(error); | 1372 type.set_malformed_error(error); |
1475 } else { | 1373 } else { |
1476 // In production mode, do not mark the type with a resolved type class as | 1374 // 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, ...) { | 1407 void ClassFinalizer::ReportError(const char* format, ...) { |
1510 va_list args; | 1408 va_list args; |
1511 va_start(args, format); | 1409 va_start(args, format); |
1512 const Error& error = Error::Handle( | 1410 const Error& error = Error::Handle( |
1513 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1411 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1514 va_end(args); | 1412 va_end(args); |
1515 ReportError(error); | 1413 ReportError(error); |
1516 } | 1414 } |
1517 | 1415 |
1518 } // namespace dart | 1416 } // namespace dart |
OLD | NEW |