| OLD | NEW |
| 1 // Copyright (c) 2011, 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 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); | 16 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
| 17 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 17 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
| 18 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 18 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
| 19 DEFINE_FLAG(bool, verify_implements, false, | 19 DEFINE_FLAG(bool, verify_implements, false, |
| 20 "Verify that all classes implement their interface."); | 20 "Verify that all classes implement their interface."); |
| 21 DECLARE_FLAG(bool, enable_type_checks); | 21 DECLARE_FLAG(bool, enable_type_checks); |
| 22 DECLARE_FLAG(bool, silent_warnings); | |
| 23 DECLARE_FLAG(bool, warning_as_error); | |
| 24 | 22 |
| 25 void ClassFinalizer::AddPendingClasses( | 23 void ClassFinalizer::AddPendingClasses( |
| 26 const GrowableArray<const Class*>& classes) { | 24 const GrowableArray<const Class*>& classes) { |
| 27 if (!classes.is_empty()) { | 25 if (!classes.is_empty()) { |
| 28 ObjectStore* object_store = Isolate::Current()->object_store(); | 26 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 29 const Array& old_array = Array::Handle(object_store->pending_classes()); | 27 const Array& old_array = Array::Handle(object_store->pending_classes()); |
| 30 const intptr_t old_length = old_array.Length(); | 28 const intptr_t old_length = old_array.Length(); |
| 31 const int new_length = old_length + classes.length(); | 29 const int new_length = old_length + classes.length(); |
| 32 const Array& new_array = Array::Handle(Array::Grow(old_array, new_length)); | 30 const Array& new_array = Array::Handle(Array::Grow(old_array, new_length)); |
| 33 // Add new classes. | 31 // Add new classes. |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 err.ToErrorCString()); | 248 err.ToErrorCString()); |
| 251 OS::Exit(255); | 249 OS::Exit(255); |
| 252 } | 250 } |
| 253 if (FLAG_trace_class_finalization) { | 251 if (FLAG_trace_class_finalization) { |
| 254 OS::Print("VerifyBootstrapClasses END.\n"); | 252 OS::Print("VerifyBootstrapClasses END.\n"); |
| 255 } | 253 } |
| 256 Isolate::Current()->heap()->Verify(); | 254 Isolate::Current()->heap()->Verify(); |
| 257 } | 255 } |
| 258 | 256 |
| 259 | 257 |
| 260 // Resolve unresolved_class in the library of cls. | 258 // Resolve unresolved_class in the library of cls, or return null. |
| 261 RawClass* ClassFinalizer::ResolveClass( | 259 RawClass* ClassFinalizer::ResolveClass( |
| 262 const Class& cls, const UnresolvedClass& unresolved_class) { | 260 const Class& cls, const UnresolvedClass& unresolved_class) { |
| 263 const String& class_name = String::Handle(unresolved_class.ident()); | 261 const String& class_name = String::Handle(unresolved_class.ident()); |
| 264 Library& lib = Library::Handle(); | 262 Library& lib = Library::Handle(); |
| 265 Class& resolved_class = Class::Handle(); | 263 Class& resolved_class = Class::Handle(); |
| 266 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { | 264 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { |
| 267 lib = cls.library(); | 265 lib = cls.library(); |
| 268 ASSERT(!lib.IsNull()); | 266 ASSERT(!lib.IsNull()); |
| 269 resolved_class = lib.LookupClass(class_name); | 267 resolved_class = lib.LookupClass(class_name); |
| 270 } else { | 268 } else { |
| 271 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); | 269 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); |
| 272 lib_prefix = unresolved_class.library_prefix(); | 270 lib_prefix = unresolved_class.library_prefix(); |
| 273 ASSERT(!lib_prefix.IsNull()); | 271 ASSERT(!lib_prefix.IsNull()); |
| 274 resolved_class = lib_prefix.LookupLocalClass(class_name); | 272 resolved_class = lib_prefix.LookupLocalClass(class_name); |
| 275 } | 273 } |
| 276 if (resolved_class.IsNull()) { | |
| 277 const Script& script = Script::Handle(cls.script()); | |
| 278 ReportError(script, unresolved_class.token_index(), | |
| 279 "cannot resolve class name '%s' from '%s'.\n", | |
| 280 String::Handle(unresolved_class.Name()).ToCString(), | |
| 281 String::Handle(cls.Name()).ToCString()); | |
| 282 } | |
| 283 return resolved_class.raw(); | 274 return resolved_class.raw(); |
| 284 } | 275 } |
| 285 | 276 |
| 286 | 277 |
| 287 // Resolve unresolved supertype (String -> Class). | 278 // Resolve unresolved supertype (String -> Class). |
| 288 void ClassFinalizer::ResolveSuperType(const Class& cls) { | 279 void ClassFinalizer::ResolveSuperType(const Class& cls) { |
| 289 if (cls.is_finalized()) { | 280 if (cls.is_finalized()) { |
| 290 return; | 281 return; |
| 291 } | 282 } |
| 292 Type& super_type = Type::Handle(cls.super_type()); | 283 Type& super_type = Type::Handle(cls.super_type()); |
| 293 if (super_type.IsNull()) { | 284 if (super_type.IsNull()) { |
| 294 return; | 285 return; |
| 295 } | 286 } |
| 296 // Resolve failures lead to a longjmp. | 287 // Resolve failures lead to a longjmp. |
| 297 ResolveType(cls, super_type); | 288 ResolveType(cls, super_type, kFinalizeWellFormed); |
| 298 const Class& super_class = Class::Handle(super_type.type_class()); | 289 const Class& super_class = Class::Handle(super_type.type_class()); |
| 299 if (cls.is_interface() != super_class.is_interface()) { | 290 if (cls.is_interface() != super_class.is_interface()) { |
| 300 String& class_name = String::Handle(cls.Name()); | 291 String& class_name = String::Handle(cls.Name()); |
| 301 String& super_class_name = String::Handle(super_class.Name()); | 292 String& super_class_name = String::Handle(super_class.Name()); |
| 302 const Script& script = Script::Handle(cls.script()); | 293 const Script& script = Script::Handle(cls.script()); |
| 303 ReportError(script, cls.token_index(), | 294 ReportError(script, cls.token_index(), |
| 304 "class '%s' and superclass '%s' are not " | 295 "class '%s' and superclass '%s' are not " |
| 305 "both classes or both interfaces.\n", | 296 "both classes or both interfaces", |
| 306 class_name.ToCString(), | 297 class_name.ToCString(), |
| 307 super_class_name.ToCString()); | 298 super_class_name.ToCString()); |
| 308 } | 299 } |
| 309 // If cls belongs to core lib or to core lib's implementation, restrictions | 300 // If cls belongs to core lib or to core lib's implementation, restrictions |
| 310 // about allowed interfaces are lifted. | 301 // about allowed interfaces are lifted. |
| 311 if ((cls.library() != Library::CoreLibrary()) && | 302 if ((cls.library() != Library::CoreLibrary()) && |
| 312 (cls.library() != Library::CoreImplLibrary())) { | 303 (cls.library() != Library::CoreImplLibrary())) { |
| 313 // Prevent extending core implementation classes Bool, Double, ObjectArray, | 304 // Prevent extending core implementation classes Bool, Double, ObjectArray, |
| 314 // ImmutableArray, GrowableObjectArray, IntegerImplementation, Smi, Mint, | 305 // ImmutableArray, GrowableObjectArray, IntegerImplementation, Smi, Mint, |
| 315 // BigInt, OneByteString, TwoByteString, FourByteString. | 306 // BigInt, OneByteString, TwoByteString, FourByteString. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 332 (super_class.raw() == object_store->external_byte_array_class()) || | 323 (super_class.raw() == object_store->external_byte_array_class()) || |
| 333 (super_class.raw() == integer_implementation_class.raw()) || | 324 (super_class.raw() == integer_implementation_class.raw()) || |
| 334 (super_class.raw() == object_store->smi_class()) || | 325 (super_class.raw() == object_store->smi_class()) || |
| 335 (super_class.raw() == object_store->mint_class()) || | 326 (super_class.raw() == object_store->mint_class()) || |
| 336 (super_class.raw() == object_store->bigint_class()) || | 327 (super_class.raw() == object_store->bigint_class()) || |
| 337 (super_class.raw() == object_store->one_byte_string_class()) || | 328 (super_class.raw() == object_store->one_byte_string_class()) || |
| 338 (super_class.raw() == object_store->two_byte_string_class()) || | 329 (super_class.raw() == object_store->two_byte_string_class()) || |
| 339 (super_class.raw() == object_store->four_byte_string_class())) { | 330 (super_class.raw() == object_store->four_byte_string_class())) { |
| 340 const Script& script = Script::Handle(cls.script()); | 331 const Script& script = Script::Handle(cls.script()); |
| 341 ReportError(script, cls.token_index(), | 332 ReportError(script, cls.token_index(), |
| 342 "'%s' is not allowed to extend '%s'\n", | 333 "'%s' is not allowed to extend '%s'", |
| 343 String::Handle(cls.Name()).ToCString(), | 334 String::Handle(cls.Name()).ToCString(), |
| 344 String::Handle(super_class.Name()).ToCString()); | 335 String::Handle(super_class.Name()).ToCString()); |
| 345 } | 336 } |
| 346 } | 337 } |
| 347 return; | 338 return; |
| 348 } | 339 } |
| 349 | 340 |
| 350 | 341 |
| 351 void ClassFinalizer::ResolveDefaultClass(const Class& interface) { | 342 void ClassFinalizer::ResolveDefaultClass(const Class& interface) { |
| 352 ASSERT(interface.is_interface()); | 343 ASSERT(interface.is_interface()); |
| 353 if (interface.is_finalized() || | 344 if (interface.is_finalized() || |
| 354 !interface.HasFactoryClass() || | 345 !interface.HasFactoryClass() || |
| 355 interface.HasResolvedFactoryClass()) { | 346 interface.HasResolvedFactoryClass()) { |
| 356 return; | 347 return; |
| 357 } | 348 } |
| 358 const UnresolvedClass& unresolved_factory_class = | 349 const UnresolvedClass& unresolved_factory_class = |
| 359 UnresolvedClass::Handle(interface.UnresolvedFactoryClass()); | 350 UnresolvedClass::Handle(interface.UnresolvedFactoryClass()); |
| 360 | 351 |
| 361 // Lookup the factory class. | 352 // Lookup the factory class. |
| 362 const Class& factory_class = | 353 const Class& factory_class = |
| 363 Class::Handle(ResolveClass(interface, unresolved_factory_class)); | 354 Class::Handle(ResolveClass(interface, unresolved_factory_class)); |
| 364 ASSERT(!factory_class.IsNull()); | 355 if (factory_class.IsNull()) { |
| 356 const Script& script = Script::Handle(interface.script()); |
| 357 ReportError(script, unresolved_factory_class.token_index(), |
| 358 "cannot resolve factory class name '%s' from '%s'", |
| 359 String::Handle(unresolved_factory_class.Name()).ToCString(), |
| 360 String::Handle(interface.Name()).ToCString()); |
| 361 } |
| 365 if (factory_class.is_interface()) { | 362 if (factory_class.is_interface()) { |
| 366 const String& interface_name = String::Handle(interface.Name()); | 363 const String& interface_name = String::Handle(interface.Name()); |
| 367 const String& factory_name = String::Handle(factory_class.Name()); | 364 const String& factory_name = String::Handle(factory_class.Name()); |
| 368 const Script& script = Script::Handle(interface.script()); | 365 const Script& script = Script::Handle(interface.script()); |
| 369 ReportError(script, unresolved_factory_class.token_index(), | 366 ReportError(script, unresolved_factory_class.token_index(), |
| 370 "default clause of interface '%s' names non-class '%s'.\n", | 367 "default clause of interface '%s' names non-class '%s'", |
| 371 interface_name.ToCString(), | 368 interface_name.ToCString(), |
| 372 factory_name.ToCString()); | 369 factory_name.ToCString()); |
| 373 } | 370 } |
| 374 interface.set_factory_class(factory_class); | 371 interface.set_factory_class(factory_class); |
| 375 ResolveAndFinalizeUpperBounds(factory_class); | 372 ResolveAndFinalizeUpperBounds(factory_class); |
| 376 const Class& factory_signature_class = Class::Handle( | 373 const Class& factory_signature_class = Class::Handle( |
| 377 unresolved_factory_class.factory_signature_class()); | 374 unresolved_factory_class.factory_signature_class()); |
| 378 ASSERT(!factory_signature_class.IsNull()); | 375 ASSERT(!factory_signature_class.IsNull()); |
| 379 // If a type parameter list is included in the default factory clause (it | 376 // If a type parameter list is included in the default factory clause (it |
| 380 // can be omitted), verify that it matches the list of type parameters of | 377 // can be omitted), verify that it matches the list of type parameters of |
| (...skipping 11 matching lines...) Expand all Loading... |
| 392 if (!AbstractTypeArguments::AreEqual(expected_type_parameters, | 389 if (!AbstractTypeArguments::AreEqual(expected_type_parameters, |
| 393 actual_type_parameters) || | 390 actual_type_parameters) || |
| 394 !AbstractTypeArguments::AreEqual(expected_type_parameter_bounds, | 391 !AbstractTypeArguments::AreEqual(expected_type_parameter_bounds, |
| 395 actual_type_parameter_bounds)) { | 392 actual_type_parameter_bounds)) { |
| 396 const String& interface_name = String::Handle(interface.Name()); | 393 const String& interface_name = String::Handle(interface.Name()); |
| 397 const String& factory_name = String::Handle(factory_class.Name()); | 394 const String& factory_name = String::Handle(factory_class.Name()); |
| 398 const Script& script = Script::Handle(interface.script()); | 395 const Script& script = Script::Handle(interface.script()); |
| 399 ReportError(script, unresolved_factory_class.token_index(), | 396 ReportError(script, unresolved_factory_class.token_index(), |
| 400 "mismatch in number, names, or bounds of type parameters " | 397 "mismatch in number, names, or bounds of type parameters " |
| 401 "between default clause of interface '%s' and actual factory " | 398 "between default clause of interface '%s' and actual factory " |
| 402 "class '%s'.\n", | 399 "class '%s'", |
| 403 interface_name.ToCString(), | 400 interface_name.ToCString(), |
| 404 factory_name.ToCString()); | 401 factory_name.ToCString()); |
| 405 } | 402 } |
| 406 } | 403 } |
| 407 // Verify that the type parameters of the factory class and of the interface | 404 // Verify that the type parameters of the factory class and of the interface |
| 408 // have identical names. | 405 // have identical names. |
| 409 const TypeArguments& interface_type_parameters = | 406 const TypeArguments& interface_type_parameters = |
| 410 TypeArguments::Handle(interface.type_parameters()); | 407 TypeArguments::Handle(interface.type_parameters()); |
| 411 const TypeArguments& factory_type_parameters = | 408 const TypeArguments& factory_type_parameters = |
| 412 TypeArguments::Handle(factory_class.type_parameters()); | 409 TypeArguments::Handle(factory_class.type_parameters()); |
| 413 if (!AbstractTypeArguments::AreEqual(interface_type_parameters, | 410 if (!AbstractTypeArguments::AreEqual(interface_type_parameters, |
| 414 factory_type_parameters)) { | 411 factory_type_parameters)) { |
| 415 const String& interface_name = String::Handle(interface.Name()); | 412 const String& interface_name = String::Handle(interface.Name()); |
| 416 const String& factory_name = String::Handle(factory_class.Name()); | 413 const String& factory_name = String::Handle(factory_class.Name()); |
| 417 const Script& script = Script::Handle(interface.script()); | 414 const Script& script = Script::Handle(interface.script()); |
| 418 ReportError(script, unresolved_factory_class.token_index(), | 415 ReportError(script, unresolved_factory_class.token_index(), |
| 419 "mismatch in number or names of type parameters between " | 416 "mismatch in number or names of type parameters between " |
| 420 "interface '%s' and default factory class '%s'.\n", | 417 "interface '%s' and default factory class '%s'", |
| 421 interface_name.ToCString(), | 418 interface_name.ToCString(), |
| 422 factory_name.ToCString()); | 419 factory_name.ToCString()); |
| 423 } | 420 } |
| 424 } | 421 } |
| 425 | 422 |
| 426 | 423 |
| 427 void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) { | 424 void ClassFinalizer::ResolveType(const Class& cls, |
| 428 if (type.IsResolved()) { | 425 const AbstractType& type, |
| 426 FinalizationKind finalization) { |
| 427 if (type.IsResolved() || type.IsFinalized()) { |
| 429 return; | 428 return; |
| 430 } | 429 } |
| 431 if (FLAG_trace_type_finalization) { | 430 if (FLAG_trace_type_finalization) { |
| 432 OS::Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); | 431 OS::Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); |
| 433 } | 432 } |
| 434 | 433 |
| 435 // Resolve the type class. | 434 // Resolve the type class. |
| 436 if (!type.HasResolvedTypeClass()) { | 435 if (!type.HasResolvedTypeClass()) { |
| 437 // Type parameters are always resolved in the parser in the correct | 436 // Type parameters are always resolved in the parser in the correct |
| 438 // non-static scope or factory scope. That resolution scope is unknown here. | 437 // non-static scope or factory scope. That resolution scope is unknown here. |
| 439 // Being able to resolve a type parameter from class cls here would indicate | 438 // Being able to resolve a type parameter from class cls here would indicate |
| 440 // that the type parameter appeared in a static scope. Leaving the type as | 439 // that the type parameter appeared in a static scope. Leaving the type as |
| 441 // unresolved is the correct thing to do. | 440 // unresolved is the correct thing to do. |
| 442 | 441 |
| 443 // Lookup the type class. | 442 // Lookup the type class. |
| 444 const UnresolvedClass& unresolved_class = | 443 const UnresolvedClass& unresolved_class = |
| 445 UnresolvedClass::Handle(type.unresolved_class()); | 444 UnresolvedClass::Handle(type.unresolved_class()); |
| 446 const Class& type_class = | 445 const Class& type_class = |
| 447 Class::Handle(ResolveClass(cls, unresolved_class)); | 446 Class::Handle(ResolveClass(cls, unresolved_class)); |
| 448 | 447 |
| 449 // Replace unresolved class with resolved type class. | 448 // Replace unresolved class with resolved type class. |
| 450 ASSERT(type.IsType()); | 449 ASSERT(type.IsType()); |
| 451 Type& parameterized_type = Type::Handle(); | 450 Type& parameterized_type = Type::Handle(); |
| 452 parameterized_type ^= type.raw(); | 451 parameterized_type ^= type.raw(); |
| 453 parameterized_type.set_type_class(Object::Handle(type_class.raw())); | 452 if (!type_class.IsNull()) { |
| 453 parameterized_type.set_type_class(Object::Handle(type_class.raw())); |
| 454 } else { |
| 455 // The type class could not be resolved. The type is malformed. |
| 456 FinalizeMalformedType(cls, parameterized_type, finalization, |
| 457 "cannot resolve class name '%s' from '%s'", |
| 458 String::Handle(unresolved_class.Name()).ToCString(), |
| 459 String::Handle(cls.Name()).ToCString()); |
| 460 return; |
| 461 } |
| 454 } | 462 } |
| 455 | 463 |
| 456 // Resolve type arguments, if any. | 464 // Resolve type arguments, if any. |
| 457 const AbstractTypeArguments& arguments = | 465 const AbstractTypeArguments& arguments = |
| 458 AbstractTypeArguments::Handle(type.arguments()); | 466 AbstractTypeArguments::Handle(type.arguments()); |
| 459 if (!arguments.IsNull()) { | 467 if (!arguments.IsNull()) { |
| 460 intptr_t num_arguments = arguments.Length(); | 468 intptr_t num_arguments = arguments.Length(); |
| 461 AbstractType& type_argument = AbstractType::Handle(); | 469 AbstractType& type_argument = AbstractType::Handle(); |
| 462 for (intptr_t i = 0; i < num_arguments; i++) { | 470 for (intptr_t i = 0; i < num_arguments; i++) { |
| 463 type_argument = arguments.TypeAt(i); | 471 type_argument = arguments.TypeAt(i); |
| 464 ResolveType(cls, type_argument); | 472 ResolveType(cls, type_argument, finalization); |
| 465 } | 473 } |
| 466 } | 474 } |
| 467 } | 475 } |
| 468 | 476 |
| 469 | 477 |
| 470 // Finalize the type argument vector 'arguments' of the type defined by the | 478 // Finalize the type argument vector 'arguments' of the type defined by the |
| 471 // class 'cls' parameterized with the type arguments 'cls_args'. | 479 // class 'cls' parameterized with the type arguments 'cls_args'. |
| 472 // The vector 'cls_args' is already initialized as a subvector at the correct | 480 // The vector 'cls_args' is already initialized as a subvector at the correct |
| 473 // position in the passed in 'arguments' vector. | 481 // position in the passed in 'arguments' vector. |
| 474 // The subvector 'cls_args' has length cls.NumTypeParameters() and starts at | 482 // The subvector 'cls_args' has length cls.NumTypeParameters() and starts at |
| 475 // offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments' | 483 // offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments' |
| 476 // vector. | 484 // vector. |
| 477 // Example: | 485 // Example: |
| 478 // Declared: class C<K, V> extends B<V> { ... } | 486 // Declared: class C<K, V> extends B<V> { ... } |
| 479 // class B<T> extends A<int> { ... } | 487 // class B<T> extends A<int> { ... } |
| 480 // Input: C<String, double> expressed as | 488 // Input: C<String, double> expressed as |
| 481 // cls = C, arguments = [null, null, String, double], | 489 // cls = C, arguments = [null, null, String, double], |
| 482 // i.e. cls_args = [String, double], offset = 2, length = 2. | 490 // i.e. cls_args = [String, double], offset = 2, length = 2. |
| 483 // Output: arguments = [int, double, String, double] | 491 // Output: arguments = [int, double, String, double] |
| 484 void ClassFinalizer::FinalizeTypeArguments( | 492 void ClassFinalizer::FinalizeTypeArguments( |
| 485 const Class& cls, const AbstractTypeArguments& arguments) { | 493 const Class& cls, |
| 494 const AbstractTypeArguments& arguments, |
| 495 FinalizationKind finalization) { |
| 486 ASSERT(arguments.Length() >= cls.NumTypeArguments()); | 496 ASSERT(arguments.Length() >= cls.NumTypeArguments()); |
| 487 Type& super_type = Type::Handle(cls.super_type()); | 497 Type& super_type = Type::Handle(cls.super_type()); |
| 488 if (!super_type.IsNull()) { | 498 if (!super_type.IsNull()) { |
| 489 super_type ^= FinalizeType(cls, super_type); | 499 super_type ^= FinalizeType(cls, super_type, finalization); |
| 490 cls.set_super_type(super_type); | 500 cls.set_super_type(super_type); |
| 491 const Class& super_class = Class::Handle(super_type.type_class()); | 501 const Class& super_class = Class::Handle(super_type.type_class()); |
| 492 const AbstractTypeArguments& super_type_args = | 502 const AbstractTypeArguments& super_type_args = |
| 493 AbstractTypeArguments::Handle(super_type.arguments()); | 503 AbstractTypeArguments::Handle(super_type.arguments()); |
| 494 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 504 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
| 495 const intptr_t offset = super_class.NumTypeArguments(); | 505 const intptr_t offset = super_class.NumTypeArguments(); |
| 496 const intptr_t super_offset = offset - num_super_type_params; | 506 const intptr_t super_offset = offset - num_super_type_params; |
| 497 ASSERT(offset == (cls.NumTypeArguments() - cls.NumTypeParameters())); | 507 ASSERT(offset == (cls.NumTypeArguments() - cls.NumTypeParameters())); |
| 498 AbstractType& super_type_arg = AbstractType::Handle(); | 508 AbstractType& super_type_arg = AbstractType::Handle(); |
| 499 for (intptr_t i = 0; i < num_super_type_params; i++) { | 509 for (intptr_t i = 0; i < num_super_type_params; i++) { |
| 500 super_type_arg = super_type_args.TypeAt(super_offset + i); | 510 super_type_arg = super_type_args.TypeAt(super_offset + i); |
| 501 if (!super_type_arg.IsInstantiated()) { | 511 if (!super_type_arg.IsInstantiated()) { |
| 502 super_type_arg = super_type_arg.InstantiateFrom(arguments); | 512 super_type_arg = super_type_arg.InstantiateFrom(arguments); |
| 503 } | 513 } |
| 504 super_type_arg = super_type_arg.Canonicalize(); | 514 super_type_arg = super_type_arg.Canonicalize(); |
| 505 arguments.SetTypeAt(super_offset + i, super_type_arg); | 515 arguments.SetTypeAt(super_offset + i, super_type_arg); |
| 506 } | 516 } |
| 507 FinalizeTypeArguments(super_class, arguments); | 517 FinalizeTypeArguments(super_class, arguments, finalization); |
| 508 } | 518 } |
| 509 } | 519 } |
| 510 | 520 |
| 511 | 521 |
| 512 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, | 522 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, |
| 513 const AbstractType& type) { | 523 const AbstractType& type, |
| 514 ASSERT(type.IsResolved()); | 524 FinalizationKind finalization) { |
| 515 if (type.IsFinalized()) { | 525 if (type.IsFinalized()) { |
| 516 return type.raw(); | 526 return type.raw(); |
| 517 } | 527 } |
| 528 ASSERT(type.IsResolved()); |
| 529 |
| 518 if (FLAG_trace_type_finalization) { | 530 if (FLAG_trace_type_finalization) { |
| 519 OS::Print("Finalize type '%s'\n", String::Handle(type.Name()).ToCString()); | 531 OS::Print("Finalize type '%s'\n", String::Handle(type.Name()).ToCString()); |
| 520 } | 532 } |
| 521 | 533 |
| 522 if (type.IsTypeParameter()) { | 534 if (type.IsTypeParameter()) { |
| 523 ASSERT(!cls.IsNull()); | 535 ASSERT(!cls.IsNull()); |
| 524 TypeParameter& type_parameter = TypeParameter::Handle(); | 536 TypeParameter& type_parameter = TypeParameter::Handle(); |
| 525 type_parameter ^= type.raw(); | 537 type_parameter ^= type.raw(); |
| 526 // The index must reflect the position of this type parameter in the type | 538 // The index must reflect the position of this type parameter in the type |
| 527 // arguments vector of the enclosing class. The offset to add is the number | 539 // arguments vector of the enclosing class. The offset to add is the number |
| 528 // of type arguments in the super type, which is equal to the difference in | 540 // of type arguments in the super type, which is equal to the difference in |
| 529 // number of type arguments and type parameters of the enclosing class. | 541 // number of type arguments and type parameters of the enclosing class. |
| 530 const intptr_t offset = cls.NumTypeArguments() - cls.NumTypeParameters(); | 542 const intptr_t offset = cls.NumTypeArguments() - cls.NumTypeParameters(); |
| 531 type_parameter.set_index(type_parameter.Index() + offset); | 543 type_parameter.set_index(type_parameter.Index() + offset); |
| 532 type_parameter.set_is_finalized(); | 544 type_parameter.set_is_finalized(); |
| 533 // We do not canonicalize type parameters. | 545 // We do not canonicalize type parameters. |
| 534 return type_parameter.raw(); | 546 return type_parameter.raw(); |
| 535 } | 547 } |
| 536 | 548 |
| 537 // At this point, we can only have a parameterized_type. | 549 // At this point, we can only have a parameterized_type. |
| 538 Type& parameterized_type = Type::Handle(); | 550 Type& parameterized_type = Type::Handle(); |
| 539 parameterized_type ^= type.raw(); | 551 parameterized_type ^= type.raw(); |
| 540 | 552 |
| 541 if (parameterized_type.IsBeingFinalized()) { | 553 if (parameterized_type.IsBeingFinalized()) { |
| 542 const Script& script = Script::Handle(cls.script()); | 554 // Self reference detected. The type is malformed. |
| 543 ReportError(script, parameterized_type.token_index(), | 555 FinalizeMalformedType( |
| 544 "type '%s' illegally refers to itself\n", | 556 cls, parameterized_type, finalization, |
| 545 String::Handle(parameterized_type.Name()).ToCString()); | 557 "type '%s' illegally refers to itself", |
| 558 String::Handle(parameterized_type.Name()).ToCString()); |
| 559 return parameterized_type.raw(); |
| 546 } | 560 } |
| 547 | 561 |
| 548 // Mark type as being finalized in order to detect illegal self reference. | 562 // Mark type as being finalized in order to detect illegal self reference. |
| 549 parameterized_type.set_is_being_finalized(); | 563 parameterized_type.set_is_being_finalized(); |
| 550 | 564 |
| 551 // Finalize the current type arguments of the type, which are still the | 565 // Finalize the current type arguments of the type, which are still the |
| 552 // parsed type arguments. | 566 // parsed type arguments. |
| 553 AbstractTypeArguments& arguments = | 567 AbstractTypeArguments& arguments = |
| 554 AbstractTypeArguments::Handle(parameterized_type.arguments()); | 568 AbstractTypeArguments::Handle(parameterized_type.arguments()); |
| 555 if (!arguments.IsNull()) { | 569 if (!arguments.IsNull()) { |
| 556 intptr_t num_arguments = arguments.Length(); | 570 intptr_t num_arguments = arguments.Length(); |
| 557 for (intptr_t i = 0; i < num_arguments; i++) { | 571 for (intptr_t i = 0; i < num_arguments; i++) { |
| 558 AbstractType& type_argument = AbstractType::Handle(arguments.TypeAt(i)); | 572 AbstractType& type_argument = AbstractType::Handle(arguments.TypeAt(i)); |
| 559 type_argument = FinalizeType(cls, type_argument); | 573 type_argument = FinalizeType(cls, type_argument, finalization); |
| 560 arguments.SetTypeAt(i, type_argument); | 574 arguments.SetTypeAt(i, type_argument); |
| 561 } | 575 } |
| 562 } | 576 } |
| 563 | 577 |
| 564 // The type class does not need to be finalized in order to finalize the type, | 578 // The type class does not need to be finalized in order to finalize the type, |
| 565 // however, it must at least be resolved (this was done as part of resolving | 579 // however, it must at least be resolved (this was done as part of resolving |
| 566 // the type itself, a precondition to calling FinalizeType) and the upper | 580 // the type itself, a precondition to calling FinalizeType) and the upper |
| 567 // bounds of its type parameters must be finalized (done here). | 581 // bounds of its type parameters must be finalized (done here). |
| 568 Class& type_class = Class::Handle(parameterized_type.type_class()); | 582 Class& type_class = Class::Handle(parameterized_type.type_class()); |
| 569 | 583 |
| 570 // If the type class is a signature class, we are finalizing its signature | 584 // If the type class is a signature class, we are finalizing its signature |
| 571 // type, thereby finalizing the result type and parameter types of its | 585 // type, thereby finalizing the result type and parameter types of its |
| 572 // signature function. | 586 // signature function. |
| 573 // Do this before marking this type as finalized in order to detect cycles. | 587 // Do this before marking this type as finalized in order to detect cycles. |
| 574 if (type_class.IsSignatureClass()) { | 588 if (type_class.IsSignatureClass()) { |
| 575 // Signature classes are finalized upon creation. | 589 // Signature classes are finalized upon creation. |
| 576 ASSERT(type_class.is_finalized()); | 590 ASSERT(type_class.is_finalized()); |
| 577 // Resolve and finalize the result and parameter types of the signature | 591 // Resolve and finalize the result and parameter types of the signature |
| 578 // function of this signature class. | 592 // function of this signature class. |
| 579 ResolveAndFinalizeSignature( | 593 ResolveAndFinalizeSignature( |
| 580 type_class, Function::Handle(type_class.signature_function())); | 594 type_class, Function::Handle(type_class.signature_function())); |
| 581 } | 595 } |
| 582 | 596 |
| 597 // Illegally self referencing function types may get finalized indirectly. |
| 598 if (parameterized_type.IsFinalized()) { |
| 599 ASSERT(parameterized_type.IsMalformed()); |
| 600 return parameterized_type.raw(); |
| 601 } |
| 602 |
| 583 // The finalized type argument vector needs num_type_arguments types. | 603 // The finalized type argument vector needs num_type_arguments types. |
| 584 const intptr_t num_type_arguments = type_class.NumTypeArguments(); | 604 const intptr_t num_type_arguments = type_class.NumTypeArguments(); |
| 585 // The type class has num_type_parameters type parameters. | 605 // The type class has num_type_parameters type parameters. |
| 586 const intptr_t num_type_parameters = type_class.NumTypeParameters(); | 606 const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
| 587 | 607 |
| 588 // Initialize the type argument vector. | 608 // Initialize the type argument vector. |
| 589 // Check the number of parsed type arguments, if any. | 609 // Check the number of parsed type arguments, if any. |
| 590 // Specifying no type arguments indicates a raw type, which is not an error. | 610 // Specifying no type arguments indicates a raw type, which is not an error. |
| 591 // However, type parameter bounds are checked below, even for a raw type. | 611 // However, type parameter bounds are checked below, even for a raw type. |
| 592 if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { | 612 if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
| 593 const Script& script = Script::Handle(cls.script()); | 613 // Wrong number of type arguments. The type is malformed. |
| 594 ReportError(script, type.token_index(), | 614 FinalizeMalformedType( |
| 595 "wrong number of type arguments in type '%s'\n", | 615 cls, parameterized_type, finalization, |
| 596 String::Handle(type.Name()).ToCString()); | 616 "wrong number of type arguments in type '%s'", |
| 617 String::Handle(parameterized_type.Name()).ToCString()); |
| 618 return parameterized_type.raw(); |
| 597 } | 619 } |
| 598 // The full type argument vector consists of the type arguments of the | 620 // The full type argument vector consists of the type arguments of the |
| 599 // super types of type_class, which may be initialized from the parsed | 621 // super types of type_class, which may be initialized from the parsed |
| 600 // type arguments, followed by the parsed type arguments. | 622 // type arguments, followed by the parsed type arguments. |
| 601 if (num_type_arguments > 0) { | 623 if (num_type_arguments > 0) { |
| 602 TypeArguments& full_arguments = TypeArguments::Handle( | 624 TypeArguments& full_arguments = TypeArguments::Handle( |
| 603 TypeArguments::New(num_type_arguments)); | 625 TypeArguments::New(num_type_arguments)); |
| 604 // Copy the parsed type arguments at the correct offset in the full type | 626 // Copy the parsed type arguments at the correct offset in the full type |
| 605 // argument vector. | 627 // argument vector. |
| 606 const intptr_t offset = num_type_arguments - num_type_parameters; | 628 const intptr_t offset = num_type_arguments - num_type_parameters; |
| 607 AbstractType& type = AbstractType::Handle(Type::DynamicType()); | 629 AbstractType& type = AbstractType::Handle(Type::DynamicType()); |
| 608 for (intptr_t i = 0; i < num_type_parameters; i++) { | 630 for (intptr_t i = 0; i < num_type_parameters; i++) { |
| 609 // If no type parameters were provided, a raw type is desired, so we | 631 // If no type parameters were provided, a raw type is desired, so we |
| 610 // create a vector of DynamicType. | 632 // create a vector of DynamicType. |
| 611 if (!arguments.IsNull()) { | 633 if (!arguments.IsNull()) { |
| 612 type = arguments.TypeAt(i); | 634 type = arguments.TypeAt(i); |
| 613 } | 635 } |
| 614 full_arguments.SetTypeAt(offset + i, type); | 636 full_arguments.SetTypeAt(offset + i, type); |
| 615 } | 637 } |
| 616 if (type_class.IsSignatureClass()) { | 638 if (type_class.IsSignatureClass()) { |
| 617 const Function& signature_fun = | 639 const Function& signature_fun = |
| 618 Function::Handle(type_class.signature_function()); | 640 Function::Handle(type_class.signature_function()); |
| 619 ASSERT(!signature_fun.is_static()); | 641 ASSERT(!signature_fun.is_static()); |
| 620 const Class& signature_fun_owner = Class::Handle(signature_fun.owner()); | 642 const Class& signature_fun_owner = Class::Handle(signature_fun.owner()); |
| 621 FinalizeTypeArguments(signature_fun_owner, full_arguments); | 643 FinalizeTypeArguments(signature_fun_owner, full_arguments, finalization); |
| 622 } else { | 644 } else { |
| 623 FinalizeTypeArguments(type_class, full_arguments); | 645 FinalizeTypeArguments(type_class, full_arguments, finalization); |
| 624 } | 646 } |
| 625 // FinalizeTypeArguments can modify 'full_arguments', | 647 // FinalizeTypeArguments can modify 'full_arguments', |
| 626 // canonicalize afterwards. | 648 // canonicalize afterwards. |
| 627 full_arguments ^= full_arguments.Canonicalize(); | 649 full_arguments ^= full_arguments.Canonicalize(); |
| 628 parameterized_type.set_arguments(full_arguments); | 650 parameterized_type.set_arguments(full_arguments); |
| 629 | 651 |
| 630 // Mark the type as finalized before finalizing the upper bounds, because | 652 // Mark the type as finalized. |
| 631 // cycles via upper bounds are legal at compile time. | |
| 632 parameterized_type.set_is_finalized(); | 653 parameterized_type.set_is_finalized(); |
| 633 | 654 |
| 634 ResolveAndFinalizeUpperBounds(type_class); | |
| 635 // No need to verify the upper bounds of the finalized type arguments, since | 655 // No need to verify the upper bounds of the finalized type arguments, since |
| 636 // bound errors are static type errors, which are not reported by the VM. | 656 // bound errors are static type errors, which are not reported by the VM. |
| 637 } else { | 657 } else { |
| 638 parameterized_type.set_is_finalized(); | 658 parameterized_type.set_is_finalized(); |
| 639 } | 659 } |
| 640 return parameterized_type.Canonicalize(); | 660 return parameterized_type.Canonicalize(); |
| 641 } | 661 } |
| 642 | 662 |
| 643 | 663 |
| 644 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, | 664 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, |
| 645 const Function& function) { | 665 const Function& function) { |
| 646 // Resolve result type. | 666 // Resolve result type. |
| 647 AbstractType& type = AbstractType::Handle(function.result_type()); | 667 AbstractType& type = AbstractType::Handle(function.result_type()); |
| 648 ResolveType(cls, type); | 668 FinalizationKind result_finalization = kFinalize; |
| 649 type = FinalizeType(cls, type); | 669 if (function.IsFactory()) { |
| 670 // The name of a factory must always be resolved to a class or interface. |
| 671 // The parser sets the factory result type to a type with an unresolved |
| 672 // class whose name matches the factory name. |
| 673 result_finalization = kFinalizeWellFormed; |
| 674 } |
| 675 ResolveType(cls, type, result_finalization); |
| 676 type = FinalizeType(cls, type, result_finalization); |
| 650 function.set_result_type(type); | 677 function.set_result_type(type); |
| 651 // Resolve formal parameter types. | 678 // Resolve formal parameter types. |
| 652 const intptr_t num_parameters = function.NumberOfParameters(); | 679 const intptr_t num_parameters = function.NumberOfParameters(); |
| 653 for (intptr_t i = 0; i < num_parameters; i++) { | 680 for (intptr_t i = 0; i < num_parameters; i++) { |
| 654 type = function.ParameterTypeAt(i); | 681 type = function.ParameterTypeAt(i); |
| 655 ResolveType(cls, type); | 682 ResolveType(cls, type, kFinalize); |
| 656 type = FinalizeType(cls, type); | 683 type = FinalizeType(cls, type, kFinalize); |
| 657 function.SetParameterTypeAt(i, type); | 684 function.SetParameterTypeAt(i, type); |
| 658 } | 685 } |
| 659 } | 686 } |
| 660 | 687 |
| 661 | 688 |
| 662 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls, | 689 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls, |
| 663 const String& name) { | 690 const String& name) { |
| 664 Class& super_class = Class::Handle(); | 691 Class& super_class = Class::Handle(); |
| 665 Function& function = Function::Handle(); | 692 Function& function = Function::Handle(); |
| 666 Field& field = Field::Handle(); | 693 Field& field = Field::Handle(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 // Resolve and finalize the upper bounds of the type parameters of class cls. | 728 // Resolve and finalize the upper bounds of the type parameters of class cls. |
| 702 void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) { | 729 void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) { |
| 703 const intptr_t num_type_params = cls.NumTypeParameters(); | 730 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 704 AbstractType& bound = AbstractType::Handle(); | 731 AbstractType& bound = AbstractType::Handle(); |
| 705 const AbstractTypeArguments& bounds = | 732 const AbstractTypeArguments& bounds = |
| 706 AbstractTypeArguments::Handle(cls.type_parameter_bounds()); | 733 AbstractTypeArguments::Handle(cls.type_parameter_bounds()); |
| 707 ASSERT((bounds.IsNull() && (num_type_params == 0)) || | 734 ASSERT((bounds.IsNull() && (num_type_params == 0)) || |
| 708 (bounds.Length() == num_type_params)); | 735 (bounds.Length() == num_type_params)); |
| 709 for (intptr_t i = 0; i < num_type_params; i++) { | 736 for (intptr_t i = 0; i < num_type_params; i++) { |
| 710 bound = bounds.TypeAt(i); | 737 bound = bounds.TypeAt(i); |
| 711 ResolveType(cls, bound); | 738 if (bound.IsDynamicType()) { |
| 712 bound = FinalizeType(cls, bound); | 739 continue; |
| 740 } |
| 741 ResolveType(cls, bound, kFinalize); |
| 742 bound = FinalizeType(cls, bound, kFinalize); |
| 713 bounds.SetTypeAt(i, bound); | 743 bounds.SetTypeAt(i, bound); |
| 714 } | 744 } |
| 715 } | 745 } |
| 716 | 746 |
| 717 | 747 |
| 718 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { | 748 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
| 719 // Note that getters and setters are explicitly listed as such in the list of | 749 // Note that getters and setters are explicitly listed as such in the list of |
| 720 // functions of a class, so we do not need to consider fields as implicitly | 750 // functions of a class, so we do not need to consider fields as implicitly |
| 721 // generating getters and setters. | 751 // generating getters and setters. |
| 722 // The only compile errors we report are therefore: | 752 // The only compile errors we report are therefore: |
| 723 // - a getter having the same name as a method (but not a getter) in a super | 753 // - a getter having the same name as a method (but not a getter) in a super |
| 724 // class or in a subclass. | 754 // class or in a subclass. |
| 725 // - a setter having the same name as a method (but not a setter) in a super | 755 // - a setter having the same name as a method (but not a setter) in a super |
| 726 // class or in a subclass. | 756 // class or in a subclass. |
| 727 // - a static field, instance field, or static method (but not an instance | 757 // - a static field, instance field, or static method (but not an instance |
| 728 // method) having the same name as an instance member in a super class. | 758 // method) having the same name as an instance member in a super class. |
| 729 | 759 |
| 730 // Resolve type of fields and check for conflicts in super classes. | 760 // Resolve type of fields and check for conflicts in super classes. |
| 731 Array& array = Array::Handle(cls.fields()); | 761 Array& array = Array::Handle(cls.fields()); |
| 732 Field& field = Field::Handle(); | 762 Field& field = Field::Handle(); |
| 733 AbstractType& type = AbstractType::Handle(); | 763 AbstractType& type = AbstractType::Handle(); |
| 734 String& name = String::Handle(); | 764 String& name = String::Handle(); |
| 735 Class& super_class = Class::Handle(); | 765 Class& super_class = Class::Handle(); |
| 736 intptr_t num_fields = array.Length(); | 766 intptr_t num_fields = array.Length(); |
| 737 for (intptr_t i = 0; i < num_fields; i++) { | 767 for (intptr_t i = 0; i < num_fields; i++) { |
| 738 field ^= array.At(i); | 768 field ^= array.At(i); |
| 739 type = field.type(); | 769 type = field.type(); |
| 740 ResolveType(cls, type); | 770 ResolveType(cls, type, kFinalize); |
| 741 type = FinalizeType(cls, type); | 771 type = FinalizeType(cls, type, kFinalize); |
| 742 field.set_type(type); | 772 field.set_type(type); |
| 743 name = field.name(); | 773 name = field.name(); |
| 744 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 774 super_class = FindSuperOwnerOfInstanceMember(cls, name); |
| 745 if (!super_class.IsNull()) { | 775 if (!super_class.IsNull()) { |
| 746 const String& class_name = String::Handle(cls.Name()); | 776 const String& class_name = String::Handle(cls.Name()); |
| 747 const String& super_class_name = String::Handle(super_class.Name()); | 777 const String& super_class_name = String::Handle(super_class.Name()); |
| 748 const Script& script = Script::Handle(cls.script()); | 778 const Script& script = Script::Handle(cls.script()); |
| 749 ReportError(script, field.token_index(), | 779 ReportError(script, field.token_index(), |
| 750 "field '%s' of class '%s' conflicts with instance " | 780 "field '%s' of class '%s' conflicts with instance " |
| 751 "member '%s' of super class '%s'.\n", | 781 "member '%s' of super class '%s'", |
| 752 name.ToCString(), | 782 name.ToCString(), |
| 753 class_name.ToCString(), | 783 class_name.ToCString(), |
| 754 name.ToCString(), | 784 name.ToCString(), |
| 755 super_class_name.ToCString()); | 785 super_class_name.ToCString()); |
| 756 } | 786 } |
| 757 } | 787 } |
| 758 // Resolve function signatures and check for conflicts in super classes. | 788 // Resolve function signatures and check for conflicts in super classes. |
| 759 array = cls.functions(); | 789 array = cls.functions(); |
| 760 Function& function = Function::Handle(); | 790 Function& function = Function::Handle(); |
| 761 Function& overridden_function = Function::Handle(); | 791 Function& overridden_function = Function::Handle(); |
| 762 intptr_t num_functions = array.Length(); | 792 intptr_t num_functions = array.Length(); |
| 763 String& function_name = String::Handle(); | 793 String& function_name = String::Handle(); |
| 764 for (intptr_t i = 0; i < num_functions; i++) { | 794 for (intptr_t i = 0; i < num_functions; i++) { |
| 765 function ^= array.At(i); | 795 function ^= array.At(i); |
| 766 ResolveAndFinalizeSignature(cls, function); | 796 ResolveAndFinalizeSignature(cls, function); |
| 767 function_name = function.name(); | 797 function_name = function.name(); |
| 768 if (function.is_static()) { | 798 if (function.is_static()) { |
| 769 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 799 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); |
| 770 if (!super_class.IsNull()) { | 800 if (!super_class.IsNull()) { |
| 771 const String& class_name = String::Handle(cls.Name()); | 801 const String& class_name = String::Handle(cls.Name()); |
| 772 const String& super_class_name = String::Handle(super_class.Name()); | 802 const String& super_class_name = String::Handle(super_class.Name()); |
| 773 const Script& script = Script::Handle(cls.script()); | 803 const Script& script = Script::Handle(cls.script()); |
| 774 ReportError(script, function.token_index(), | 804 ReportError(script, function.token_index(), |
| 775 "static function '%s' of class '%s' conflicts with " | 805 "static function '%s' of class '%s' conflicts with " |
| 776 "instance member '%s' of super class '%s'.\n", | 806 "instance member '%s' of super class '%s'", |
| 777 function_name.ToCString(), | 807 function_name.ToCString(), |
| 778 class_name.ToCString(), | 808 class_name.ToCString(), |
| 779 function_name.ToCString(), | 809 function_name.ToCString(), |
| 780 super_class_name.ToCString()); | 810 super_class_name.ToCString()); |
| 781 } | 811 } |
| 782 } else { | 812 } else { |
| 783 // TODO(regis): This arity check is still being debated. Revisit. | 813 // TODO(regis): This arity check is still being debated. Revisit. |
| 784 super_class = cls.SuperClass(); | 814 super_class = cls.SuperClass(); |
| 785 while (!super_class.IsNull()) { | 815 while (!super_class.IsNull()) { |
| 786 overridden_function = super_class.LookupDynamicFunction(function_name); | 816 overridden_function = super_class.LookupDynamicFunction(function_name); |
| 787 if (!overridden_function.IsNull() && | 817 if (!overridden_function.IsNull() && |
| 788 !function.HasCompatibleParametersWith(overridden_function)) { | 818 !function.HasCompatibleParametersWith(overridden_function)) { |
| 789 // Function types are purposely not checked for subtyping. | 819 // Function types are purposely not checked for subtyping. |
| 790 const String& class_name = String::Handle(cls.Name()); | 820 const String& class_name = String::Handle(cls.Name()); |
| 791 const String& super_class_name = String::Handle(super_class.Name()); | 821 const String& super_class_name = String::Handle(super_class.Name()); |
| 792 const Script& script = Script::Handle(cls.script()); | 822 const Script& script = Script::Handle(cls.script()); |
| 793 ReportError(script, function.token_index(), | 823 ReportError(script, function.token_index(), |
| 794 "class '%s' overrides function '%s' of super class '%s' " | 824 "class '%s' overrides function '%s' of super class '%s' " |
| 795 "with incompatible parameters.\n", | 825 "with incompatible parameters", |
| 796 class_name.ToCString(), | 826 class_name.ToCString(), |
| 797 function_name.ToCString(), | 827 function_name.ToCString(), |
| 798 super_class_name.ToCString()); | 828 super_class_name.ToCString()); |
| 799 } | 829 } |
| 800 super_class = super_class.SuperClass(); | 830 super_class = super_class.SuperClass(); |
| 801 } | 831 } |
| 802 } | 832 } |
| 803 if (function.kind() == RawFunction::kGetterFunction) { | 833 if (function.kind() == RawFunction::kGetterFunction) { |
| 804 name = Field::NameFromGetter(function_name); | 834 name = Field::NameFromGetter(function_name); |
| 805 super_class = FindSuperOwnerOfFunction(cls, name); | 835 super_class = FindSuperOwnerOfFunction(cls, name); |
| 806 if (!super_class.IsNull()) { | 836 if (!super_class.IsNull()) { |
| 807 const String& class_name = String::Handle(cls.Name()); | 837 const String& class_name = String::Handle(cls.Name()); |
| 808 const String& super_class_name = String::Handle(super_class.Name()); | 838 const String& super_class_name = String::Handle(super_class.Name()); |
| 809 const Script& script = Script::Handle(cls.script()); | 839 const Script& script = Script::Handle(cls.script()); |
| 810 ReportError(script, function.token_index(), | 840 ReportError(script, function.token_index(), |
| 811 "getter '%s' of class '%s' conflicts with " | 841 "getter '%s' of class '%s' conflicts with " |
| 812 "function '%s' of super class '%s'.\n", | 842 "function '%s' of super class '%s'", |
| 813 name.ToCString(), | 843 name.ToCString(), |
| 814 class_name.ToCString(), | 844 class_name.ToCString(), |
| 815 name.ToCString(), | 845 name.ToCString(), |
| 816 super_class_name.ToCString()); | 846 super_class_name.ToCString()); |
| 817 } | 847 } |
| 818 } else if (function.kind() == RawFunction::kSetterFunction) { | 848 } else if (function.kind() == RawFunction::kSetterFunction) { |
| 819 name = Field::NameFromSetter(function_name); | 849 name = Field::NameFromSetter(function_name); |
| 820 super_class = FindSuperOwnerOfFunction(cls, name); | 850 super_class = FindSuperOwnerOfFunction(cls, name); |
| 821 if (!super_class.IsNull()) { | 851 if (!super_class.IsNull()) { |
| 822 const String& class_name = String::Handle(cls.Name()); | 852 const String& class_name = String::Handle(cls.Name()); |
| 823 const String& super_class_name = String::Handle(super_class.Name()); | 853 const String& super_class_name = String::Handle(super_class.Name()); |
| 824 const Script& script = Script::Handle(cls.script()); | 854 const Script& script = Script::Handle(cls.script()); |
| 825 ReportError(script, function.token_index(), | 855 ReportError(script, function.token_index(), |
| 826 "setter '%s' of class '%s' conflicts with " | 856 "setter '%s' of class '%s' conflicts with " |
| 827 "function '%s' of super class '%s'.\n", | 857 "function '%s' of super class '%s'", |
| 828 name.ToCString(), | 858 name.ToCString(), |
| 829 class_name.ToCString(), | 859 class_name.ToCString(), |
| 830 name.ToCString(), | 860 name.ToCString(), |
| 831 super_class_name.ToCString()); | 861 super_class_name.ToCString()); |
| 832 } | 862 } |
| 833 } else { | 863 } else { |
| 834 name = Field::GetterName(function_name); | 864 name = Field::GetterName(function_name); |
| 835 super_class = FindSuperOwnerOfFunction(cls, name); | 865 super_class = FindSuperOwnerOfFunction(cls, name); |
| 836 if (!super_class.IsNull()) { | 866 if (!super_class.IsNull()) { |
| 837 const String& class_name = String::Handle(cls.Name()); | 867 const String& class_name = String::Handle(cls.Name()); |
| 838 const String& super_class_name = String::Handle(super_class.Name()); | 868 const String& super_class_name = String::Handle(super_class.Name()); |
| 839 const Script& script = Script::Handle(cls.script()); | 869 const Script& script = Script::Handle(cls.script()); |
| 840 ReportError(script, function.token_index(), | 870 ReportError(script, function.token_index(), |
| 841 "function '%s' of class '%s' conflicts with " | 871 "function '%s' of class '%s' conflicts with " |
| 842 "getter '%s' of super class '%s'.\n", | 872 "getter '%s' of super class '%s'", |
| 843 function_name.ToCString(), | 873 function_name.ToCString(), |
| 844 class_name.ToCString(), | 874 class_name.ToCString(), |
| 845 function_name.ToCString(), | 875 function_name.ToCString(), |
| 846 super_class_name.ToCString()); | 876 super_class_name.ToCString()); |
| 847 } | 877 } |
| 848 name = Field::SetterName(function_name); | 878 name = Field::SetterName(function_name); |
| 849 super_class = FindSuperOwnerOfFunction(cls, name); | 879 super_class = FindSuperOwnerOfFunction(cls, name); |
| 850 if (!super_class.IsNull()) { | 880 if (!super_class.IsNull()) { |
| 851 const String& class_name = String::Handle(cls.Name()); | 881 const String& class_name = String::Handle(cls.Name()); |
| 852 const String& super_class_name = String::Handle(super_class.Name()); | 882 const String& super_class_name = String::Handle(super_class.Name()); |
| 853 const Script& script = Script::Handle(cls.script()); | 883 const Script& script = Script::Handle(cls.script()); |
| 854 ReportError(script, function.token_index(), | 884 ReportError(script, function.token_index(), |
| 855 "function '%s' of class '%s' conflicts with " | 885 "function '%s' of class '%s' conflicts with " |
| 856 "setter '%s' of super class '%s'.\n", | 886 "setter '%s' of super class '%s'", |
| 857 function_name.ToCString(), | 887 function_name.ToCString(), |
| 858 class_name.ToCString(), | 888 class_name.ToCString(), |
| 859 function_name.ToCString(), | 889 function_name.ToCString(), |
| 860 super_class_name.ToCString()); | 890 super_class_name.ToCString()); |
| 861 } | 891 } |
| 862 } | 892 } |
| 863 } | 893 } |
| 864 } | 894 } |
| 865 | 895 |
| 866 | 896 |
| 867 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { | 897 void ClassFinalizer::FinalizeClass(const Class& cls, bool generating_snapshot) { |
| 868 if (cls.is_finalized()) { | 898 if (cls.is_finalized()) { |
| 869 return; | 899 return; |
| 870 } | 900 } |
| 871 if (FLAG_trace_class_finalization) { | 901 if (FLAG_trace_class_finalization) { |
| 872 OS::Print("Finalize %s\n", cls.ToCString()); | 902 OS::Print("Finalize %s\n", cls.ToCString()); |
| 873 } | 903 } |
| 874 // Signature classes are finalized upon creation. | 904 // Signature classes are finalized upon creation. |
| 875 ASSERT(!cls.IsSignatureClass()); | 905 ASSERT(!cls.IsSignatureClass()); |
| 876 if (!IsSuperCycleFree(cls)) { | 906 if (!IsSuperCycleFree(cls)) { |
| 877 const String& name = String::Handle(cls.Name()); | 907 const String& name = String::Handle(cls.Name()); |
| 878 const Script& script = Script::Handle(cls.script()); | 908 const Script& script = Script::Handle(cls.script()); |
| 879 ReportError(script, cls.token_index(), | 909 ReportError(script, cls.token_index(), |
| 880 "class '%s' has a cycle in its superclass relationship.\n", | 910 "class '%s' has a cycle in its superclass relationship", |
| 881 name.ToCString()); | 911 name.ToCString()); |
| 882 } | 912 } |
| 883 GrowableArray<const Class*> visited; | 913 GrowableArray<const Class*> visited; |
| 884 ResolveInterfaces(cls, &visited); | 914 ResolveInterfaces(cls, &visited); |
| 885 Type& super_type = Type::Handle(cls.super_type()); | 915 Type& super_type = Type::Handle(cls.super_type()); |
| 886 if (!super_type.IsNull()) { | 916 if (!super_type.IsNull()) { |
| 887 const Class& super_class = Class::Handle(super_type.type_class()); | 917 const Class& super_class = Class::Handle(super_type.type_class()); |
| 888 // Finalize super class and super type. | 918 // Finalize super class and super type. |
| 889 FinalizeClass(super_class, generating_snapshot); | 919 FinalizeClass(super_class, generating_snapshot); |
| 890 super_type ^= FinalizeType(cls, super_type); | 920 super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed); |
| 891 cls.set_super_type(super_type); | 921 cls.set_super_type(super_type); |
| 892 } | 922 } |
| 893 if (cls.is_interface()) { | 923 if (cls.is_interface()) { |
| 894 if (cls.HasFactoryClass()) { | 924 if (cls.HasFactoryClass()) { |
| 895 const Class& factory_class = Class::Handle(cls.FactoryClass()); | 925 const Class& factory_class = Class::Handle(cls.FactoryClass()); |
| 896 // Finalize factory class. | 926 // Finalize factory class. |
| 897 if (!factory_class.is_finalized()) { | 927 if (!factory_class.is_finalized()) { |
| 898 FinalizeClass(factory_class, generating_snapshot); | 928 FinalizeClass(factory_class, generating_snapshot); |
| 899 // Finalizing the factory class may indirectly finalize this interface. | 929 // Finalizing the factory class may indirectly finalize this interface. |
| 900 if (cls.is_finalized()) { | 930 if (cls.is_finalized()) { |
| 901 return; | 931 return; |
| 902 } | 932 } |
| 903 } | 933 } |
| 904 } | 934 } |
| 905 } | 935 } |
| 906 // Finalize interface types (but not necessarily interface classes). | 936 // Finalize interface types (but not necessarily interface classes). |
| 907 Array& interface_types = Array::Handle(cls.interfaces()); | 937 Array& interface_types = Array::Handle(cls.interfaces()); |
| 908 AbstractType& interface_type = AbstractType::Handle(); | 938 AbstractType& interface_type = AbstractType::Handle(); |
| 909 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 939 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
| 910 interface_type ^= interface_types.At(i); | 940 interface_type ^= interface_types.At(i); |
| 911 interface_type = FinalizeType(cls, interface_type); | 941 interface_type = FinalizeType(cls, interface_type, kFinalizeWellFormed); |
| 912 interface_types.SetAt(i, interface_type); | 942 interface_types.SetAt(i, interface_type); |
| 913 } | 943 } |
| 914 // Mark as finalized before resolving type parameter upper bounds and member | 944 // Mark as finalized before resolving type parameter upper bounds and member |
| 915 // types in order to break cycles. | 945 // types in order to break cycles. |
| 916 cls.Finalize(); | 946 cls.Finalize(); |
| 917 ResolveAndFinalizeUpperBounds(cls); | 947 ResolveAndFinalizeUpperBounds(cls); |
| 918 ResolveAndFinalizeMemberTypes(cls); | 948 ResolveAndFinalizeMemberTypes(cls); |
| 919 // Run additional checks after all types are finalized. | 949 // Run additional checks after all types are finalized. |
| 920 if (cls.is_const()) { | 950 if (cls.is_const()) { |
| 921 CheckForLegalConstClass(cls); | 951 CheckForLegalConstClass(cls); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 // we found a loop. | 1035 // we found a loop. |
| 1006 void ClassFinalizer::ResolveInterfaces(const Class& cls, | 1036 void ClassFinalizer::ResolveInterfaces(const Class& cls, |
| 1007 GrowableArray<const Class*>* visited) { | 1037 GrowableArray<const Class*>* visited) { |
| 1008 ASSERT(visited != NULL); | 1038 ASSERT(visited != NULL); |
| 1009 for (int i = 0; i < visited->length(); i++) { | 1039 for (int i = 0; i < visited->length(); i++) { |
| 1010 if ((*visited)[i]->raw() == cls.raw()) { | 1040 if ((*visited)[i]->raw() == cls.raw()) { |
| 1011 // We have already visited interface class 'cls'. We found a cycle. | 1041 // We have already visited interface class 'cls'. We found a cycle. |
| 1012 const String& interface_name = String::Handle(cls.Name()); | 1042 const String& interface_name = String::Handle(cls.Name()); |
| 1013 const Script& script = Script::Handle(cls.script()); | 1043 const Script& script = Script::Handle(cls.script()); |
| 1014 ReportError(script, cls.token_index(), | 1044 ReportError(script, cls.token_index(), |
| 1015 "Cyclic reference found for interface '%s'\n", | 1045 "cyclic reference found for interface '%s'", |
| 1016 interface_name.ToCString()); | 1046 interface_name.ToCString()); |
| 1017 } | 1047 } |
| 1018 } | 1048 } |
| 1019 | 1049 |
| 1020 // If the class/interface has no explicit interfaces, we are done. | 1050 // If the class/interface has no explicit interfaces, we are done. |
| 1021 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1051 Array& super_interfaces = Array::Handle(cls.interfaces()); |
| 1022 if (super_interfaces.Length() == 0) { | 1052 if (super_interfaces.Length() == 0) { |
| 1023 return; | 1053 return; |
| 1024 } | 1054 } |
| 1025 | 1055 |
| 1026 // If cls belongs to core lib or to core lib's implementation, restrictions | 1056 // If cls belongs to core lib or to core lib's implementation, restrictions |
| 1027 // about allowed interfaces are lifted. | 1057 // about allowed interfaces are lifted. |
| 1028 const bool cls_belongs_to_core_lib = | 1058 const bool cls_belongs_to_core_lib = |
| 1029 (cls.library() == Library::CoreLibrary()) || | 1059 (cls.library() == Library::CoreLibrary()) || |
| 1030 (cls.library() == Library::CoreImplLibrary()); | 1060 (cls.library() == Library::CoreImplLibrary()); |
| 1031 | 1061 |
| 1032 // Resolve and check the interfaces of cls. | 1062 // Resolve and check the interfaces of cls. |
| 1033 visited->Add(&cls); | 1063 visited->Add(&cls); |
| 1034 AbstractType& interface = AbstractType::Handle(); | 1064 AbstractType& interface = AbstractType::Handle(); |
| 1035 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { | 1065 for (intptr_t i = 0; i < super_interfaces.Length(); i++) { |
| 1036 interface ^= super_interfaces.At(i); | 1066 interface ^= super_interfaces.At(i); |
| 1037 ResolveType(cls, interface); | 1067 ResolveType(cls, interface, kFinalizeWellFormed); |
| 1038 if (interface.IsTypeParameter()) { | 1068 if (interface.IsTypeParameter()) { |
| 1039 const Script& script = Script::Handle(cls.script()); | 1069 const Script& script = Script::Handle(cls.script()); |
| 1040 ReportError(script, cls.token_index(), | 1070 ReportError(script, cls.token_index(), |
| 1041 "Type parameter '%s' cannot be used as interface\n", | 1071 "type parameter '%s' cannot be used as interface", |
| 1042 String::Handle(interface.Name()).ToCString()); | 1072 String::Handle(interface.Name()).ToCString()); |
| 1043 } | 1073 } |
| 1044 const Class& interface_class = Class::Handle(interface.type_class()); | 1074 const Class& interface_class = Class::Handle(interface.type_class()); |
| 1045 if (!interface_class.is_interface()) { | 1075 if (!interface_class.is_interface()) { |
| 1046 const Script& script = Script::Handle(cls.script()); | 1076 const Script& script = Script::Handle(cls.script()); |
| 1047 ReportError(script, cls.token_index(), | 1077 ReportError(script, cls.token_index(), |
| 1048 "Class '%s' is used where an interface is expected\n", | 1078 "class '%s' is used where an interface is expected", |
| 1049 String::Handle(interface_class.Name()).ToCString()); | 1079 String::Handle(interface_class.Name()).ToCString()); |
| 1050 } | 1080 } |
| 1051 // Verify that unless cls belongs to core lib, it cannot extend or implement | 1081 // Verify that unless cls belongs to core lib, it cannot extend or implement |
| 1052 // any of bool, num, int, double, String, Function, Dynamic. | 1082 // any of bool, num, int, double, String, Function, Dynamic. |
| 1053 // The exception is signature classes, which are compiler generated and | 1083 // The exception is signature classes, which are compiler generated and |
| 1054 // represent a function type, therefore implementing the Function interface. | 1084 // represent a function type, therefore implementing the Function interface. |
| 1055 if (!cls_belongs_to_core_lib) { | 1085 if (!cls_belongs_to_core_lib) { |
| 1056 if (interface.IsBoolInterface() || | 1086 if (interface.IsBoolInterface() || |
| 1057 interface.IsNumberInterface() || | 1087 interface.IsNumberInterface() || |
| 1058 interface.IsIntInterface() || | 1088 interface.IsIntInterface() || |
| 1059 interface.IsDoubleInterface() || | 1089 interface.IsDoubleInterface() || |
| 1060 interface.IsStringInterface() || | 1090 interface.IsStringInterface() || |
| 1061 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || | 1091 (interface.IsFunctionInterface() && !cls.IsSignatureClass()) || |
| 1062 interface.IsDynamicType()) { | 1092 interface.IsDynamicType()) { |
| 1063 const Script& script = Script::Handle(cls.script()); | 1093 const Script& script = Script::Handle(cls.script()); |
| 1064 ReportError(script, cls.token_index(), | 1094 ReportError(script, cls.token_index(), |
| 1065 "'%s' is not allowed to extend or implement '%s'\n", | 1095 "'%s' is not allowed to extend or implement '%s'", |
| 1066 String::Handle(cls.Name()).ToCString(), | 1096 String::Handle(cls.Name()).ToCString(), |
| 1067 String::Handle(interface_class.Name()).ToCString()); | 1097 String::Handle(interface_class.Name()).ToCString()); |
| 1068 } | 1098 } |
| 1069 } | 1099 } |
| 1070 // Now resolve the super interfaces. | 1100 // Now resolve the super interfaces. |
| 1071 ResolveInterfaces(interface_class, visited); | 1101 ResolveInterfaces(interface_class, visited); |
| 1072 } | 1102 } |
| 1073 visited->RemoveLast(); | 1103 visited->RemoveLast(); |
| 1074 } | 1104 } |
| 1075 | 1105 |
| 1076 | 1106 |
| 1077 // A class is marked as constant if it has one constant constructor. | 1107 // A class is marked as constant if it has one constant constructor. |
| 1078 // A constant class: | 1108 // A constant class: |
| 1079 // - may extend only const classes. | 1109 // - may extend only const classes. |
| 1080 // - has only const instance fields. | 1110 // - has only const instance fields. |
| 1081 // Note: we must check for cycles before checking for const properties. | 1111 // Note: we must check for cycles before checking for const properties. |
| 1082 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 1112 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
| 1083 ASSERT(cls.is_const()); | 1113 ASSERT(cls.is_const()); |
| 1084 const Class& super = Class::Handle(cls.SuperClass()); | 1114 const Class& super = Class::Handle(cls.SuperClass()); |
| 1085 if (!super.IsNull() && !super.is_const()) { | 1115 if (!super.IsNull() && !super.is_const()) { |
| 1086 String& name = String::Handle(super.Name()); | 1116 String& name = String::Handle(super.Name()); |
| 1087 const Script& script = Script::Handle(cls.script()); | 1117 const Script& script = Script::Handle(cls.script()); |
| 1088 ReportError(script, cls.token_index(), | 1118 ReportError(script, cls.token_index(), |
| 1089 "superclass '%s' must be const.\n", name.ToCString()); | 1119 "superclass '%s' must be const", name.ToCString()); |
| 1090 } | 1120 } |
| 1091 const Array& fields_array = Array::Handle(cls.fields()); | 1121 const Array& fields_array = Array::Handle(cls.fields()); |
| 1092 intptr_t len = fields_array.Length(); | 1122 intptr_t len = fields_array.Length(); |
| 1093 Field& field = Field::Handle(); | 1123 Field& field = Field::Handle(); |
| 1094 for (intptr_t i = 0; i < len; i++) { | 1124 for (intptr_t i = 0; i < len; i++) { |
| 1095 field ^= fields_array.At(i); | 1125 field ^= fields_array.At(i); |
| 1096 if (!field.is_static() && !field.is_final()) { | 1126 if (!field.is_static() && !field.is_final()) { |
| 1097 const String& class_name = String::Handle(cls.Name()); | 1127 const String& class_name = String::Handle(cls.Name()); |
| 1098 const String& field_name = String::Handle(field.name()); | 1128 const String& field_name = String::Handle(field.name()); |
| 1099 const Script& script = Script::Handle(cls.script()); | 1129 const Script& script = Script::Handle(cls.script()); |
| 1100 ReportError(script, field.token_index(), | 1130 ReportError(script, field.token_index(), |
| 1101 "const class '%s' has non-final field '%s'\n", | 1131 "const class '%s' has non-final field '%s'", |
| 1102 class_name.ToCString(), field_name.ToCString()); | 1132 class_name.ToCString(), field_name.ToCString()); |
| 1103 } | 1133 } |
| 1104 } | 1134 } |
| 1105 } | 1135 } |
| 1106 | 1136 |
| 1107 | 1137 |
| 1108 void ClassFinalizer::PrintClassInformation(const Class& cls) { | 1138 void ClassFinalizer::PrintClassInformation(const Class& cls) { |
| 1109 HANDLESCOPE(Isolate::Current()); | 1139 HANDLESCOPE(Isolate::Current()); |
| 1110 const String& class_name = String::Handle(cls.Name()); | 1140 const String& class_name = String::Handle(cls.Name()); |
| 1111 OS::Print("%s '%s'", | 1141 OS::Print("%s '%s'", |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1136 const Array& fields_array = Array::Handle(cls.fields()); | 1166 const Array& fields_array = Array::Handle(cls.fields()); |
| 1137 Field& field = Field::Handle(); | 1167 Field& field = Field::Handle(); |
| 1138 len = fields_array.Length(); | 1168 len = fields_array.Length(); |
| 1139 for (intptr_t i = 0; i < len; i++) { | 1169 for (intptr_t i = 0; i < len; i++) { |
| 1140 field ^= fields_array.At(i); | 1170 field ^= fields_array.At(i); |
| 1141 OS::Print(" %s\n", field.ToCString()); | 1171 OS::Print(" %s\n", field.ToCString()); |
| 1142 } | 1172 } |
| 1143 } | 1173 } |
| 1144 | 1174 |
| 1145 | 1175 |
| 1176 void ClassFinalizer::FinalizeMalformedType(const Class& cls, |
| 1177 const Type& type, |
| 1178 FinalizationKind finalization, |
| 1179 const char* format, ...) { |
| 1180 va_list args; |
| 1181 va_start(args, format); |
| 1182 LanguageError& error = LanguageError::Handle(); |
| 1183 if ((finalization == kFinalizeWellFormed) || FLAG_enable_type_checks) { |
| 1184 const Script& script = Script::Handle(cls.script()); |
| 1185 error ^= |
| 1186 Parser::FormatError(script, type.token_index(), "Error", format, args); |
| 1187 if (finalization == kFinalizeWellFormed) { |
| 1188 ReportError(error); |
| 1189 } |
| 1190 } |
| 1191 // Replace malformed type with Dynamic type. |
| 1192 type.set_type_class(Class::Handle(Object::dynamic_class())); |
| 1193 type.set_arguments(AbstractTypeArguments::Handle()); |
| 1194 if (FLAG_enable_type_checks) { |
| 1195 // In checked mode, mark type as malformed. |
| 1196 type.set_malformed_error(error); |
| 1197 } |
| 1198 type.set_is_finalized(); |
| 1199 type.Canonicalize(); |
| 1200 } |
| 1201 |
| 1202 |
| 1203 void ClassFinalizer::ReportError(const Error& error) { |
| 1204 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1205 UNREACHABLE(); |
| 1206 } |
| 1207 |
| 1208 |
| 1146 void ClassFinalizer::ReportError(const Script& script, | 1209 void ClassFinalizer::ReportError(const Script& script, |
| 1147 intptr_t token_index, | 1210 intptr_t token_index, |
| 1148 const char* format, ...) { | 1211 const char* format, ...) { |
| 1149 va_list args; | 1212 va_list args; |
| 1150 va_start(args, format); | 1213 va_start(args, format); |
| 1151 const Error& error = Error::Handle( | 1214 const Error& error = Error::Handle( |
| 1152 Parser::FormatError(script, token_index, "Error", format, args)); | 1215 Parser::FormatError(script, token_index, "Error", format, args)); |
| 1153 Isolate::Current()->long_jump_base()->Jump(1, error); | 1216 ReportError(error); |
| 1154 UNREACHABLE(); | |
| 1155 } | 1217 } |
| 1156 | 1218 |
| 1157 | 1219 |
| 1158 void ClassFinalizer::ReportError(const char* format, ...) { | 1220 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1159 va_list args; | 1221 va_list args; |
| 1160 va_start(args, format); | 1222 va_start(args, format); |
| 1161 const Error& error = Error::Handle( | 1223 const Error& error = Error::Handle( |
| 1162 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1224 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1163 va_end(args); | 1225 va_end(args); |
| 1164 Isolate::Current()->long_jump_base()->Jump(1, error); | 1226 ReportError(error); |
| 1165 UNREACHABLE(); | |
| 1166 } | |
| 1167 | |
| 1168 | |
| 1169 void ClassFinalizer::ReportWarning(const Script& script, | |
| 1170 intptr_t token_index, | |
| 1171 const char* format, ...) { | |
| 1172 if (FLAG_silent_warnings) return; | |
| 1173 va_list args; | |
| 1174 va_start(args, format); | |
| 1175 const Error& error = Error::Handle( | |
| 1176 Parser::FormatError(script, token_index, "Warning", format, args)); | |
| 1177 va_end(args); | |
| 1178 if (FLAG_warning_as_error) { | |
| 1179 Isolate::Current()->long_jump_base()->Jump(1, error); | |
| 1180 UNREACHABLE(); | |
| 1181 } else { | |
| 1182 OS::Print("%s", error.ToErrorCString()); | |
| 1183 } | |
| 1184 } | 1227 } |
| 1185 | 1228 |
| 1186 } // namespace dart | 1229 } // namespace dart |
| OLD | NEW |