| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 | 455 |
| 456 // Verify that the target constructor of the redirection exists. | 456 // Verify that the target constructor of the redirection exists. |
| 457 target = target_class.LookupConstructor(target_name); | 457 target = target_class.LookupConstructor(target_name); |
| 458 if (target.IsNull()) { | 458 if (target.IsNull()) { |
| 459 target = target_class.LookupFactory(target_name); | 459 target = target_class.LookupFactory(target_name); |
| 460 } | 460 } |
| 461 if (target.IsNull()) { | 461 if (target.IsNull()) { |
| 462 const String& user_visible_target_name = | 462 const String& user_visible_target_name = |
| 463 identifier.IsNull() ? target_class_name : target_name; | 463 identifier.IsNull() ? target_class_name : target_name; |
| 464 // Replace the type with a malformed type and compile a throw when called. | 464 // Replace the type with a malformed type and compile a throw when called. |
| 465 FinalizeMalformedType(Error::Handle(), // No previous error. | 465 type = NewFinalizedMalformedType( |
| 466 cls, type, kCanonicalize, | 466 cls, |
| 467 "class '%s' has no constructor or factory named '%s'", | 467 factory.token_pos(), |
| 468 target_class_name.ToCString(), | 468 "class '%s' has no constructor or factory named '%s'", |
| 469 user_visible_target_name.ToCString()); | 469 target_class_name.ToCString(), |
| 470 user_visible_target_name.ToCString()); |
| 470 factory.SetRedirectionType(type); | 471 factory.SetRedirectionType(type); |
| 471 ASSERT(factory.RedirectionTarget() == Function::null()); | 472 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 472 return; | 473 return; |
| 473 } | 474 } |
| 474 | 475 |
| 475 // Verify that the target is compatible with the redirecting factory. | 476 // Verify that the target is compatible with the redirecting factory. |
| 476 if (!target.HasCompatibleParametersWith(factory)) { | 477 if (!target.HasCompatibleParametersWith(factory)) { |
| 477 FinalizeMalformedType(Error::Handle(), // No previous error. | 478 type = NewFinalizedMalformedType( |
| 478 cls, type, kCanonicalize, | 479 cls, |
| 479 "constructor '%s' has incompatible parameters with " | 480 factory.token_pos(), |
| 480 "redirecting factory '%s'", | 481 "constructor '%s' has incompatible parameters with " |
| 481 String::Handle(target.name()).ToCString(), | 482 "redirecting factory '%s'", |
| 482 String::Handle(factory.name()).ToCString()); | 483 String::Handle(target.name()).ToCString(), |
| 484 String::Handle(factory.name()).ToCString()); |
| 483 factory.SetRedirectionType(type); | 485 factory.SetRedirectionType(type); |
| 484 ASSERT(factory.RedirectionTarget() == Function::null()); | 486 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 485 return; | 487 return; |
| 486 } | 488 } |
| 487 | 489 |
| 488 // Verify that the target is const if the the redirecting factory is const. | 490 // Verify that the target is const if the the redirecting factory is const. |
| 489 if (factory.is_const() && !target.is_const()) { | 491 if (factory.is_const() && !target.is_const()) { |
| 490 const Script& script = Script::Handle(cls.script()); | 492 const Script& script = Script::Handle(cls.script()); |
| 491 ReportError(script, factory.token_pos(), | 493 ReportError(script, factory.token_pos(), |
| 492 "constructor '%s' must be const as required by redirecting" | 494 "constructor '%s' must be const as required by redirecting" |
| (...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 } | 1467 } |
| 1466 const Array& fields_array = Array::Handle(cls.fields()); | 1468 const Array& fields_array = Array::Handle(cls.fields()); |
| 1467 Field& field = Field::Handle(); | 1469 Field& field = Field::Handle(); |
| 1468 len = fields_array.Length(); | 1470 len = fields_array.Length(); |
| 1469 for (intptr_t i = 0; i < len; i++) { | 1471 for (intptr_t i = 0; i < len; i++) { |
| 1470 field ^= fields_array.At(i); | 1472 field ^= fields_array.At(i); |
| 1471 OS::Print(" %s\n", field.ToCString()); | 1473 OS::Print(" %s\n", field.ToCString()); |
| 1472 } | 1474 } |
| 1473 } | 1475 } |
| 1474 | 1476 |
| 1475 | 1477 // Either report an error or mark the type as malformed. |
| 1476 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, | 1478 void ClassFinalizer::ReportMalformedType(const Error& prev_error, |
| 1477 const Class& cls, | 1479 const Class& cls, |
| 1478 const Type& type, | 1480 const Type& type, |
| 1479 FinalizationKind finalization, | 1481 FinalizationKind finalization, |
| 1480 const char* format, ...) { | 1482 const char* format, |
| 1481 va_list args; | 1483 va_list args) { |
| 1482 va_start(args, format); | |
| 1483 LanguageError& error = LanguageError::Handle(); | 1484 LanguageError& error = LanguageError::Handle(); |
| 1484 if (FLAG_enable_type_checks || | 1485 if (FLAG_enable_type_checks || |
| 1485 !type.HasResolvedTypeClass() || | 1486 !type.HasResolvedTypeClass() || |
| 1486 (finalization == kCanonicalizeWellFormed) || | 1487 (finalization == kCanonicalizeWellFormed) || |
| 1487 FLAG_error_on_malformed_type) { | 1488 FLAG_error_on_malformed_type) { |
| 1488 const Script& script = Script::Handle(cls.script()); | 1489 const Script& script = Script::Handle(cls.script()); |
| 1489 if (prev_error.IsNull()) { | 1490 if (prev_error.IsNull()) { |
| 1490 error ^= Parser::FormatError( | 1491 error ^= Parser::FormatError( |
| 1491 script, type.token_pos(), "Error", format, args); | 1492 script, type.token_pos(), "Error", format, args); |
| 1492 } else { | 1493 } else { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1513 type.set_is_finalized_instantiated(); | 1514 type.set_is_finalized_instantiated(); |
| 1514 // Do not canonicalize malformed types, since they may not be resolved. | 1515 // Do not canonicalize malformed types, since they may not be resolved. |
| 1515 } else { | 1516 } else { |
| 1516 // The only case where the malformed type was already finalized is when its | 1517 // The only case where the malformed type was already finalized is when its |
| 1517 // type arguments are not within bounds. In that case, we have a prev_error. | 1518 // type arguments are not within bounds. In that case, we have a prev_error. |
| 1518 ASSERT(!prev_error.IsNull()); | 1519 ASSERT(!prev_error.IsNull()); |
| 1519 } | 1520 } |
| 1520 } | 1521 } |
| 1521 | 1522 |
| 1522 | 1523 |
| 1524 RawType* ClassFinalizer::NewFinalizedMalformedType(const Class& cls, |
| 1525 intptr_t type_pos, |
| 1526 const char* format, ...) { |
| 1527 va_list args; |
| 1528 va_start(args, format); |
| 1529 const String& no_name = String::Handle(Symbols::Empty()); |
| 1530 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( |
| 1531 UnresolvedClass::New(LibraryPrefix::Handle(), no_name, type_pos)); |
| 1532 const Type& type = Type::Handle( |
| 1533 Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); |
| 1534 ReportMalformedType(Error::Handle(), cls, type, kTryResolve, format, args); |
| 1535 va_end(args); |
| 1536 ASSERT(type.IsMalformed()); |
| 1537 return type.raw(); |
| 1538 } |
| 1539 |
| 1540 |
| 1541 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
| 1542 const Class& cls, |
| 1543 const Type& type, |
| 1544 FinalizationKind finalization, |
| 1545 const char* format, ...) { |
| 1546 va_list args; |
| 1547 va_start(args, format); |
| 1548 ReportMalformedType(prev_error, cls, type, finalization, format, args); |
| 1549 va_end(args); |
| 1550 } |
| 1551 |
| 1552 |
| 1523 void ClassFinalizer::ReportError(const Error& error) { | 1553 void ClassFinalizer::ReportError(const Error& error) { |
| 1524 Isolate::Current()->long_jump_base()->Jump(1, error); | 1554 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1525 UNREACHABLE(); | 1555 UNREACHABLE(); |
| 1526 } | 1556 } |
| 1527 | 1557 |
| 1528 | 1558 |
| 1529 void ClassFinalizer::ReportError(const Script& script, | 1559 void ClassFinalizer::ReportError(const Script& script, |
| 1530 intptr_t token_pos, | 1560 intptr_t token_pos, |
| 1531 const char* format, ...) { | 1561 const char* format, ...) { |
| 1532 va_list args; | 1562 va_list args; |
| 1533 va_start(args, format); | 1563 va_start(args, format); |
| 1534 const Error& error = Error::Handle( | 1564 const Error& error = Error::Handle( |
| 1535 Parser::FormatError(script, token_pos, "Error", format, args)); | 1565 Parser::FormatError(script, token_pos, "Error", format, args)); |
| 1566 va_end(args); |
| 1536 ReportError(error); | 1567 ReportError(error); |
| 1537 } | 1568 } |
| 1538 | 1569 |
| 1539 | 1570 |
| 1540 void ClassFinalizer::ReportError(const char* format, ...) { | 1571 void ClassFinalizer::ReportError(const char* format, ...) { |
| 1541 va_list args; | 1572 va_list args; |
| 1542 va_start(args, format); | 1573 va_start(args, format); |
| 1543 const Error& error = Error::Handle( | 1574 const Error& error = Error::Handle( |
| 1544 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1575 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
| 1545 va_end(args); | 1576 va_end(args); |
| 1546 ReportError(error); | 1577 ReportError(error); |
| 1547 } | 1578 } |
| 1548 | 1579 |
| 1549 } // namespace dart | 1580 } // namespace dart |
| OLD | NEW |