| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 static void CollectFinalizedSuperClasses( | 91 static void CollectFinalizedSuperClasses( |
| 92 const GrowableObjectArray& pending_classes, | 92 const GrowableObjectArray& pending_classes, |
| 93 GrowableArray<intptr_t>* finalized_super_classes) { | 93 GrowableArray<intptr_t>* finalized_super_classes) { |
| 94 Class& cls = Class::Handle(); | 94 Class& cls = Class::Handle(); |
| 95 Type& super_type = Type::Handle(); | 95 Type& super_type = Type::Handle(); |
| 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { | 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { |
| 97 cls ^= pending_classes.At(i); | 97 cls ^= pending_classes.At(i); |
| 98 ASSERT(!cls.is_finalized()); | 98 ASSERT(!cls.is_finalized()); |
| 99 super_type ^= cls.super_type(); | 99 super_type ^= cls.super_type(); |
| 100 if (!super_type.IsNull()) { | 100 if (!super_type.IsNull()) { |
| 101 if (!super_type.IsMalformed() && | 101 if (super_type.HasResolvedTypeClass() && |
| 102 super_type.HasResolvedTypeClass() && | |
| 103 Class::Handle(super_type.type_class()).is_finalized()) { | 102 Class::Handle(super_type.type_class()).is_finalized()) { |
| 104 AddSuperType(super_type, finalized_super_classes); | 103 AddSuperType(super_type, finalized_super_classes); |
| 105 } | 104 } |
| 106 } | 105 } |
| 107 } | 106 } |
| 108 } | 107 } |
| 109 | 108 |
| 110 | 109 |
| 111 // Class finalization occurs: | 110 // Class finalization occurs: |
| 112 // a) when bootstrap process completes (VerifyBootstrapClasses). | 111 // a) when bootstrap process completes (VerifyBootstrapClasses). |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 | 469 |
| 471 // Lookup the type class. | 470 // Lookup the type class. |
| 472 const UnresolvedClass& unresolved_class = | 471 const UnresolvedClass& unresolved_class = |
| 473 UnresolvedClass::Handle(type.unresolved_class()); | 472 UnresolvedClass::Handle(type.unresolved_class()); |
| 474 const Class& type_class = | 473 const Class& type_class = |
| 475 Class::Handle(ResolveClass(cls, unresolved_class)); | 474 Class::Handle(ResolveClass(cls, unresolved_class)); |
| 476 | 475 |
| 477 // Replace unresolved class with resolved type class. | 476 // Replace unresolved class with resolved type class. |
| 478 const Type& parameterized_type = Type::Cast(type); | 477 const Type& parameterized_type = Type::Cast(type); |
| 479 if (!type_class.IsNull()) { | 478 if (!type_class.IsNull()) { |
| 480 parameterized_type.set_type_class(type_class); | 479 parameterized_type.set_type_class(Object::Handle(type_class.raw())); |
| 481 } else { | 480 } else { |
| 482 // The type class could not be resolved. The type is malformed. | 481 // The type class could not be resolved. The type is malformed. |
| 483 FinalizeMalformedType(Error::Handle(), // No previous error. | 482 FinalizeMalformedType(Error::Handle(), // No previous error. |
| 484 cls, parameterized_type, finalization, | 483 cls, parameterized_type, finalization, |
| 485 "cannot resolve class name '%s' from '%s'", | 484 "cannot resolve class name '%s' from '%s'", |
| 486 String::Handle(unresolved_class.Name()).ToCString(), | 485 String::Handle(unresolved_class.Name()).ToCString(), |
| 487 String::Handle(cls.Name()).ToCString()); | 486 String::Handle(cls.Name()).ToCString()); |
| 488 return; | 487 return; |
| 489 } | 488 } |
| 490 } | 489 } |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 AbstractType& type_arg = AbstractType::Handle(Type::DynamicType()); | 728 AbstractType& type_arg = AbstractType::Handle(Type::DynamicType()); |
| 730 for (intptr_t i = 0; i < num_type_parameters; i++) { | 729 for (intptr_t i = 0; i < num_type_parameters; i++) { |
| 731 // If no type parameters were provided, a raw type is desired, so we | 730 // If no type parameters were provided, a raw type is desired, so we |
| 732 // create a vector of DynamicType. | 731 // create a vector of DynamicType. |
| 733 if (!arguments.IsNull()) { | 732 if (!arguments.IsNull()) { |
| 734 type_arg = arguments.TypeAt(i); | 733 type_arg = arguments.TypeAt(i); |
| 735 } | 734 } |
| 736 ASSERT(type_arg.IsFinalized()); // Index of type parameter is adjusted. | 735 ASSERT(type_arg.IsFinalized()); // Index of type parameter is adjusted. |
| 737 full_arguments.SetTypeAt(offset + i, type_arg); | 736 full_arguments.SetTypeAt(offset + i, type_arg); |
| 738 } | 737 } |
| 739 // If the type class is a signature class, the full argument vector | |
| 740 // must include the argument vector of the super type. | |
| 741 // If the signature class is a function type alias, it is also the owner | |
| 742 // of its signature function and no super type is involved. | |
| 743 // If the signature class is canonical (not an alias), the owner of its | |
| 744 // signature function may either be an alias or the enclosing class of a | |
| 745 // local function, in which case the super type of the enclosing class is | |
| 746 // also considered when filling up the argument vector. | |
| 747 if (type_class.IsSignatureClass()) { | 738 if (type_class.IsSignatureClass()) { |
| 748 const Function& signature_fun = | 739 const Function& signature_fun = |
| 749 Function::Handle(type_class.signature_function()); | 740 Function::Handle(type_class.signature_function()); |
| 750 ASSERT(!signature_fun.is_static()); | 741 ASSERT(!signature_fun.is_static()); |
| 751 const Class& sig_fun_owner = Class::Handle(signature_fun.Owner()); | 742 const Class& sig_fun_owner = Class::Handle(signature_fun.Owner()); |
| 752 FinalizeTypeArguments(sig_fun_owner, full_arguments, finalization); | 743 FinalizeTypeArguments(sig_fun_owner, full_arguments, finalization); |
| 753 } else { | 744 } else { |
| 754 FinalizeTypeArguments(type_class, full_arguments, finalization); | 745 FinalizeTypeArguments(type_class, full_arguments, finalization); |
| 755 } | 746 } |
| 756 if (full_arguments.IsRaw(num_type_arguments)) { | 747 if (full_arguments.IsRaw(num_type_arguments)) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 return parameterized_type.raw(); | 795 return parameterized_type.raw(); |
| 805 } | 796 } |
| 806 } | 797 } |
| 807 | 798 |
| 808 // If the type class is a signature class, we are currently finalizing a | 799 // If the type class is a signature class, we are currently finalizing a |
| 809 // signature type, i.e. finalizing the result type and parameter types of the | 800 // signature type, i.e. finalizing the result type and parameter types of the |
| 810 // signature function of this signature type. | 801 // signature function of this signature type. |
| 811 // We do this after marking this type as finalized in order to allow a | 802 // We do this after marking this type as finalized in order to allow a |
| 812 // function type to refer to itself via its parameter types and result type. | 803 // function type to refer to itself via its parameter types and result type. |
| 813 if (type_class.IsSignatureClass()) { | 804 if (type_class.IsSignatureClass()) { |
| 814 // The class may be created while parsing a function body, after all | 805 // Signature classes are finalized upon creation, except function type |
| 815 // pending classes have already been finalized. | 806 // aliases. |
| 816 FinalizeClass(type_class); | 807 if (type_class.IsCanonicalSignatureClass()) { |
| 808 ASSERT(type_class.is_finalized()); |
| 809 // Resolve and finalize the result and parameter types of the signature |
| 810 // function of this signature class. |
| 811 ASSERT(type_class.SignatureType() == type.raw()); |
| 812 ResolveAndFinalizeSignature( |
| 813 type_class, Function::Handle(type_class.signature_function())); |
| 814 } else { |
| 815 // This type is a function type alias. Its class may need to be finalized |
| 816 // and checked for illegal self reference. |
| 817 FinalizeClass(type_class); |
| 818 // Finalizing the signature function here (as in the canonical case above) |
| 819 // would not mark the canonical signature type as finalized. |
| 820 const Type& signature_type = Type::Handle(type_class.SignatureType()); |
| 821 FinalizeType(cls, signature_type, finalization); |
| 822 } |
| 817 } | 823 } |
| 818 | 824 |
| 819 if (finalization >= kCanonicalize) { | 825 if (finalization >= kCanonicalize) { |
| 820 return parameterized_type.Canonicalize(); | 826 return parameterized_type.Canonicalize(); |
| 821 } else { | 827 } else { |
| 822 return parameterized_type.raw(); | 828 return parameterized_type.raw(); |
| 823 } | 829 } |
| 824 } | 830 } |
| 825 | 831 |
| 826 | 832 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 } | 1008 } |
| 1003 } | 1009 } |
| 1004 // Collect interfaces, super interfaces, and super classes of this class. | 1010 // Collect interfaces, super interfaces, and super classes of this class. |
| 1005 const GrowableObjectArray& interfaces = | 1011 const GrowableObjectArray& interfaces = |
| 1006 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1012 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1007 CollectInterfaces(cls, interfaces); | 1013 CollectInterfaces(cls, interfaces); |
| 1008 // Include superclasses in list of interfaces and super interfaces. | 1014 // Include superclasses in list of interfaces and super interfaces. |
| 1009 super_class = cls.SuperClass(); | 1015 super_class = cls.SuperClass(); |
| 1010 while (!super_class.IsNull()) { | 1016 while (!super_class.IsNull()) { |
| 1011 interfaces.Add(super_class); | 1017 interfaces.Add(super_class); |
| 1012 CollectInterfaces(super_class, interfaces); | |
| 1013 super_class = super_class.SuperClass(); | 1018 super_class = super_class.SuperClass(); |
| 1014 } | 1019 } |
| 1015 // Resolve function signatures and check for conflicts in super classes and | 1020 // Resolve function signatures and check for conflicts in super classes and |
| 1016 // interfaces. | 1021 // interfaces. |
| 1017 array = cls.functions(); | 1022 array = cls.functions(); |
| 1018 Function& function = Function::Handle(); | 1023 Function& function = Function::Handle(); |
| 1019 Function& overridden_function = Function::Handle(); | 1024 Function& overridden_function = Function::Handle(); |
| 1020 intptr_t num_functions = array.Length(); | 1025 intptr_t num_functions = array.Length(); |
| 1021 String& function_name = String::Handle(); | 1026 String& function_name = String::Handle(); |
| 1022 for (intptr_t i = 0; i < num_functions; i++) { | 1027 for (intptr_t i = 0; i < num_functions; i++) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 FinalizeClass(super_class); | 1123 FinalizeClass(super_class); |
| 1119 } | 1124 } |
| 1120 // Finalize type parameters before finalizing the super type. | 1125 // Finalize type parameters before finalizing the super type. |
| 1121 FinalizeTypeParameters(cls); | 1126 FinalizeTypeParameters(cls); |
| 1122 // Finalize super type. | 1127 // Finalize super type. |
| 1123 Type& super_type = Type::Handle(cls.super_type()); | 1128 Type& super_type = Type::Handle(cls.super_type()); |
| 1124 if (!super_type.IsNull()) { | 1129 if (!super_type.IsNull()) { |
| 1125 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1130 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
| 1126 cls.set_super_type(super_type); | 1131 cls.set_super_type(super_type); |
| 1127 } | 1132 } |
| 1133 // Signature classes are finalized upon creation, except function type |
| 1134 // aliases. |
| 1128 if (cls.IsSignatureClass()) { | 1135 if (cls.IsSignatureClass()) { |
| 1136 ASSERT(!cls.IsCanonicalSignatureClass()); |
| 1129 // Check for illegal self references. | 1137 // Check for illegal self references. |
| 1130 GrowableArray<intptr_t> visited_aliases; | 1138 GrowableArray<intptr_t> visited_aliases; |
| 1131 if (!IsAliasCycleFree(cls, &visited_aliases)) { | 1139 if (!IsAliasCycleFree(cls, &visited_aliases)) { |
| 1132 const String& name = String::Handle(cls.Name()); | 1140 const String& name = String::Handle(cls.Name()); |
| 1133 const Script& script = Script::Handle(cls.script()); | 1141 const Script& script = Script::Handle(cls.script()); |
| 1134 ReportError(script, cls.token_pos(), | 1142 ReportError(script, cls.token_pos(), |
| 1135 "typedef '%s' illegally refers to itself", | 1143 "typedef '%s' illegally refers to itself", |
| 1136 name.ToCString()); | 1144 name.ToCString()); |
| 1137 } | 1145 } |
| 1138 cls.Finalize(); | 1146 cls.Finalize(); |
| 1139 // Signature classes extend Object. No need to add this class to the direct | 1147 // Signature classes extend Object. No need to add this class to the direct |
| 1140 // subclasses of Object. | 1148 // subclasses of Object. |
| 1141 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1149 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
| 1142 | |
| 1143 // Resolve and finalize the result and parameter types of the signature | |
| 1144 // function of this signature class. | |
| 1145 const Function& sig_function = Function::Handle(cls.signature_function()); | |
| 1146 ResolveAndFinalizeSignature(cls, sig_function); | |
| 1147 | |
| 1148 // Resolve and finalize the signature type of this signature class. | |
| 1149 const Type& sig_type = Type::Handle(cls.SignatureType()); | |
| 1150 FinalizeType(cls, sig_type, kCanonicalizeWellFormed); | |
| 1151 return; | 1150 return; |
| 1152 } | 1151 } |
| 1153 // Finalize interface types (but not necessarily interface classes). | 1152 // Finalize interface types (but not necessarily interface classes). |
| 1154 Array& interface_types = Array::Handle(cls.interfaces()); | 1153 Array& interface_types = Array::Handle(cls.interfaces()); |
| 1155 AbstractType& interface_type = AbstractType::Handle(); | 1154 AbstractType& interface_type = AbstractType::Handle(); |
| 1156 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 1155 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
| 1157 interface_type ^= interface_types.At(i); | 1156 interface_type ^= interface_types.At(i); |
| 1158 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1157 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
| 1159 interface_types.SetAt(i, interface_type); | 1158 interface_types.SetAt(i, interface_type); |
| 1160 } | 1159 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 } | 1194 } |
| 1196 // No cycles. | 1195 // No cycles. |
| 1197 return true; | 1196 return true; |
| 1198 } | 1197 } |
| 1199 | 1198 |
| 1200 | 1199 |
| 1201 // Returns false if the function type alias illegally refers to itself. | 1200 // Returns false if the function type alias illegally refers to itself. |
| 1202 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, | 1201 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
| 1203 GrowableArray<intptr_t>* visited) { | 1202 GrowableArray<intptr_t>* visited) { |
| 1204 ASSERT(cls.IsSignatureClass()); | 1203 ASSERT(cls.IsSignatureClass()); |
| 1204 ASSERT(!cls.IsCanonicalSignatureClass()); |
| 1205 ASSERT(!cls.is_finalized()); | 1205 ASSERT(!cls.is_finalized()); |
| 1206 ASSERT(visited != NULL); | 1206 ASSERT(visited != NULL); |
| 1207 const intptr_t cls_index = cls.id(); | 1207 const intptr_t cls_index = cls.id(); |
| 1208 for (int i = 0; i < visited->length(); i++) { | 1208 for (int i = 0; i < visited->length(); i++) { |
| 1209 if ((*visited)[i] == cls_index) { | 1209 if ((*visited)[i] == cls_index) { |
| 1210 // We have already visited alias 'cls'. We found a cycle. | 1210 // We have already visited alias 'cls'. We found a cycle. |
| 1211 return false; | 1211 return false; |
| 1212 } | 1212 } |
| 1213 } | 1213 } |
| 1214 | 1214 |
| 1215 // Visit the result type and parameter types of this signature type. | 1215 // Visit the result type and parameter types of this signature type. |
| 1216 visited->Add(cls.id()); | 1216 visited->Add(cls.id()); |
| 1217 const Function& function = Function::Handle(cls.signature_function()); | 1217 const Function& function = Function::Handle(cls.signature_function()); |
| 1218 // Check class of result type. | 1218 // Check class of result type. |
| 1219 AbstractType& type = AbstractType::Handle(function.result_type()); | 1219 AbstractType& type = AbstractType::Handle(function.result_type()); |
| 1220 ResolveType(cls, type, kCanonicalize); | 1220 ResolveType(cls, type, kCanonicalize); |
| 1221 if (type.IsType() && !type.IsMalformed()) { | 1221 if (type.IsType() && !type.IsMalformed()) { |
| 1222 const Class& type_class = Class::Handle(type.type_class()); | 1222 const Class& type_class = Class::Handle(type.type_class()); |
| 1223 if (!type_class.is_finalized() && | 1223 if (!type_class.is_finalized() && |
| 1224 type_class.IsSignatureClass() && | 1224 type_class.IsSignatureClass() && |
| 1225 !IsAliasCycleFree(type_class, visited)) { | 1225 !type_class.IsCanonicalSignatureClass()) { |
| 1226 return false; | 1226 if (!IsAliasCycleFree(type_class, visited)) { |
| 1227 return false; |
| 1228 } |
| 1227 } | 1229 } |
| 1228 } | 1230 } |
| 1229 // Check classes of formal parameter types. | 1231 // Check classes of formal parameter types. |
| 1230 const intptr_t num_parameters = function.NumParameters(); | 1232 const intptr_t num_parameters = function.NumParameters(); |
| 1231 for (intptr_t i = 0; i < num_parameters; i++) { | 1233 for (intptr_t i = 0; i < num_parameters; i++) { |
| 1232 type = function.ParameterTypeAt(i); | 1234 type = function.ParameterTypeAt(i); |
| 1233 ResolveType(cls, type, kCanonicalize); | 1235 ResolveType(cls, type, kCanonicalize); |
| 1234 if (type.IsType() && !type.IsMalformed()) { | 1236 if (type.IsType() && !type.IsMalformed()) { |
| 1235 const Class& type_class = Class::Handle(type.type_class()); | 1237 const Class& type_class = Class::Handle(type.type_class()); |
| 1236 if (!type_class.is_finalized() && | 1238 if (!type_class.is_finalized() && |
| 1237 type_class.IsSignatureClass() && | 1239 type_class.IsSignatureClass() && |
| 1238 !IsAliasCycleFree(type_class, visited)) { | 1240 !type_class.IsCanonicalSignatureClass()) { |
| 1239 return false; | 1241 if (!IsAliasCycleFree(type_class, visited)) { |
| 1242 return false; |
| 1243 } |
| 1240 } | 1244 } |
| 1241 } | 1245 } |
| 1242 } | 1246 } |
| 1243 visited->RemoveLast(); | 1247 visited->RemoveLast(); |
| 1244 return true; | 1248 return true; |
| 1245 } | 1249 } |
| 1246 | 1250 |
| 1247 | 1251 |
| 1248 // Recursively walks the graph of explicitly declared super type and | 1252 // Recursively walks the graph of explicitly declared super type and |
| 1249 // interfaces, resolving unresolved super types and interfaces. | 1253 // interfaces, resolving unresolved super types and interfaces. |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1500 if ((finalization == kCanonicalizeWellFormed) || | 1504 if ((finalization == kCanonicalizeWellFormed) || |
| 1501 FLAG_error_on_malformed_type) { | 1505 FLAG_error_on_malformed_type) { |
| 1502 ReportError(error); | 1506 ReportError(error); |
| 1503 } | 1507 } |
| 1504 } | 1508 } |
| 1505 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { | 1509 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
| 1506 // In check mode, always mark the type as malformed. | 1510 // In check mode, always mark the type as malformed. |
| 1507 // In production mode, mark the type as malformed only if its type class is | 1511 // In production mode, mark the type as malformed only if its type class is |
| 1508 // not resolved. | 1512 // not resolved. |
| 1509 type.set_malformed_error(error); | 1513 type.set_malformed_error(error); |
| 1510 if (!type.HasResolvedTypeClass()) { | |
| 1511 // We do not want an unresolved class to end up in a snapshot. | |
| 1512 type.set_type_class(Object::Handle(Object::null_class())); | |
| 1513 } | |
| 1514 } else { | 1514 } else { |
| 1515 // In production mode, do not mark the type with a resolved type class as | 1515 // In production mode, do not mark the type with a resolved type class as |
| 1516 // malformed, but make it raw. | 1516 // malformed, but make it raw. |
| 1517 ASSERT(type.HasResolvedTypeClass()); |
| 1517 type.set_arguments(AbstractTypeArguments::Handle()); | 1518 type.set_arguments(AbstractTypeArguments::Handle()); |
| 1518 } | 1519 } |
| 1519 ASSERT(type.HasResolvedTypeClass()); | |
| 1520 if (!type.IsFinalized()) { | 1520 if (!type.IsFinalized()) { |
| 1521 type.set_is_finalized_instantiated(); | 1521 type.set_is_finalized_instantiated(); |
| 1522 // Do not canonicalize malformed types, since they may not be resolved. | 1522 // Do not canonicalize malformed types, since they may not be resolved. |
| 1523 } else { | 1523 } else { |
| 1524 // The only case where the malformed type was already finalized is when its | 1524 // The only case where the malformed type was already finalized is when its |
| 1525 // type arguments are not within bounds. In that case, we have a prev_error. | 1525 // type arguments are not within bounds. In that case, we have a prev_error. |
| 1526 ASSERT(!prev_error.IsNull()); | 1526 ASSERT(!prev_error.IsNull()); |
| 1527 } | 1527 } |
| 1528 } | 1528 } |
| 1529 | 1529 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 void ClassFinalizer::ReportError(const char* format, ...) { | 1582 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1583 va_list args; | 1583 va_list args; |
| 1584 va_start(args, format); | 1584 va_start(args, format); |
| 1585 const Error& error = Error::Handle( | 1585 const Error& error = Error::Handle( |
| 1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1586 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1587 va_end(args); | 1587 va_end(args); |
| 1588 ReportError(error); | 1588 ReportError(error); |
| 1589 } | 1589 } |
| 1590 | 1590 |
| 1591 } // namespace dart | 1591 } // namespace dart |
| OLD | NEW |