Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: runtime/vm/class_finalizer.cc

Issue 8360022: Fix member overriding rules in VM according to latest spec. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 const intptr_t num_parameters = function.NumberOfParameters(); 546 const intptr_t num_parameters = function.NumberOfParameters();
547 for (intptr_t i = 0; i < num_parameters; i++) { 547 for (intptr_t i = 0; i < num_parameters; i++) {
548 type = function.ParameterTypeAt(i); 548 type = function.ParameterTypeAt(i);
549 type = ResolveType(cls, type); 549 type = ResolveType(cls, type);
550 function.SetParameterTypeAt(i, type); 550 function.SetParameterTypeAt(i, type);
551 FinalizeType(type); 551 FinalizeType(type);
552 } 552 }
553 } 553 }
554 554
555 555
556 static bool FuncNameExistsInSuper(const Class& cls, 556 static RawClass* InstanceMemberSuperOwner(const Class& cls,
557 const String& name) { 557 const String& name) {
siva 2011/10/21 17:13:32 I would have preferred the name FindSuperOwnerOfIn
regis 2011/10/21 17:33:38 Done.
558 Class& super_class = Class::Handle();
559 Function& function = Function::Handle();
560 Field& field = Field::Handle();
561 super_class = cls.SuperClass();
562 while (!super_class.IsNull()) {
563 // Check if an instance member of same name exists in any super class.
564 function = super_class.LookupFunction(name);
565 if (!function.IsNull() && !function.is_static()) {
566 return super_class.raw();
567 }
568 field = super_class.LookupField(name);
569 if (!field.IsNull() && !field.is_static()) {
570 return super_class.raw();
571 }
572 super_class = super_class.SuperClass();
573 }
574 return Class::null();
575 }
576
577
578 static RawClass* FunctionSuperOwner(const Class& cls, const String& name) {
siva 2011/10/21 17:13:32 Similarly I would have preferred FindSuperOwnerOfF
regis 2011/10/21 17:33:38 Done.
558 Class& super_class = Class::Handle(); 579 Class& super_class = Class::Handle();
559 Function& function = Function::Handle(); 580 Function& function = Function::Handle();
560 super_class = cls.SuperClass(); 581 super_class = cls.SuperClass();
561 while (!super_class.IsNull()) { 582 while (!super_class.IsNull()) {
562 // Check if a field of same name exists in any super class. 583 // Check if a function of same name exists in any super class.
563 function = super_class.LookupFunction(name); 584 function = super_class.LookupFunction(name);
564 if (!function.IsNull()) { 585 if (!function.IsNull()) {
565 return true; 586 return super_class.raw();
566 } 587 }
567 super_class = super_class.SuperClass(); 588 super_class = super_class.SuperClass();
568 } 589 }
569 return false; 590 return Class::null();
570 }
571
572
573 static bool FieldNameExistsInSuper(const Class& cls, const String& name) {
574 Class& super_class = Class::Handle();
575 Field& field = Field::Handle();
576 super_class = cls.SuperClass();
577 while (!super_class.IsNull()) {
578 // Check if a function of same name exists in any super class.
579 field = super_class.LookupField(name);
580 if (!field.IsNull()) {
581 return true;
582 }
583 super_class = super_class.SuperClass();
584 }
585 return false;
586 } 591 }
587 592
588 593
589 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { 594 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
590 // Resolve type of fields. 595 // Note that getters and setters are explicitly listed as such in the list of
596 // functions of a class, so we do not need to consider fields as implicitly
597 // generating getters and setters.
598 // The only compile errors we report are therefore:
599 // - a getter having the same name as a method (but not a getter) in a super
600 // class or in a subclass.
601 // - a setter having the same name as a method (but not a setter) in a super
602 // class or in a subclass.
603 // - a static field, instance field, or static method (but not an instance
604 // method) having the same name as an instance member in a super class.
605
606 // Resolve type of fields and check for conflicts in super classes.
591 Array& array = Array::Handle(cls.fields()); 607 Array& array = Array::Handle(cls.fields());
592 Field& field = Field::Handle(); 608 Field& field = Field::Handle();
593 Type& type = Type::Handle(); 609 Type& type = Type::Handle();
610 String& name = String::Handle();
611 Class& super_class = Class::Handle();
594 intptr_t num_fields = array.Length(); 612 intptr_t num_fields = array.Length();
595 String& name = String::Handle();
596 for (intptr_t i = 0; i < num_fields; i++) { 613 for (intptr_t i = 0; i < num_fields; i++) {
597 field ^= array.At(i); 614 field ^= array.At(i);
598 type = field.type(); 615 type = field.type();
599 type = ResolveType(cls, type); 616 type = ResolveType(cls, type);
600 field.set_type(type); 617 field.set_type(type);
601 FinalizeType(type); 618 FinalizeType(type);
602 name = field.name(); 619 name = field.name();
603 if (FuncNameExistsInSuper(cls, name)) { 620 super_class = InstanceMemberSuperOwner(cls, name);
604 ReportError("field '%s' overrides a function in the super class.\n", 621 if (!super_class.IsNull()) {
605 name.ToCString()); 622 const String& class_name = String::Handle(cls.Name());
623 const String& super_class_name = String::Handle(super_class.Name());
624 ReportError("field '%s' of class '%s' conflicts with instance "
625 "member '%s' of super class '%s'.\n",
626 name.ToCString(),
627 class_name.ToCString(),
628 name.ToCString(),
629 super_class_name.ToCString());
606 } 630 }
607 } 631 }
608 // Resolve function signatures. 632 // Resolve function signatures and check for conflicts in super classes.
609 array = cls.functions(); 633 array = cls.functions();
610 Function& function = Function::Handle(); 634 Function& function = Function::Handle();
635 Function& overridden_function = Function::Handle();
611 intptr_t num_functions = array.Length(); 636 intptr_t num_functions = array.Length();
612 String& func_name = String::Handle(); 637 String& function_name = String::Handle();
613 for (intptr_t i = 0; i < num_functions; i++) { 638 for (intptr_t i = 0; i < num_functions; i++) {
614 function ^= array.At(i); 639 function ^= array.At(i);
615 ResolveAndFinalizeSignature(cls, function); 640 ResolveAndFinalizeSignature(cls, function);
616 func_name = function.name(); 641 function_name = function.name();
617 if (FieldNameExistsInSuper(cls, func_name)) { 642 if (function.is_static()) {
618 ReportError("function '%s' overrides a field in the super class.\n", 643 super_class = InstanceMemberSuperOwner(cls, function_name);
619 func_name.ToCString()); 644 if (!super_class.IsNull()) {
620 } 645 const String& class_name = String::Handle(cls.Name());
621 name = Field::GetterName(func_name); 646 const String& super_class_name = String::Handle(super_class.Name());
622 if (FuncNameExistsInSuper(cls, name)) { 647 ReportError("static function '%s' of class '%s' conflicts with "
623 ReportError("function '%s' overrides a getter in the super class.\n", 648 "instance member '%s' of super class '%s'.\n",
624 name.ToCString()); 649 function_name.ToCString(),
625 } 650 class_name.ToCString(),
626 name = Field::SetterName(func_name); 651 function_name.ToCString(),
627 if (FuncNameExistsInSuper(cls, name)) { 652 super_class_name.ToCString());
628 ReportError("function '%s' overrides a setter in the super class.\n", 653 }
629 name.ToCString()); 654 } else {
655 // TODO(regis): This arity check is still being debated. Revisit.
siva 2011/10/21 17:13:32 Yes this is still being debated, may have to yank
regis 2011/10/21 17:33:38 OK. Keeping the TODO.
656 super_class = cls.SuperClass();
657 while (!super_class.IsNull()) {
658 overridden_function = super_class.LookupDynamicFunction(function_name);
659 if (!overridden_function.IsNull() &&
660 !function.HasCompatibleParametersWith(overridden_function)) {
661 // Function types are purposely not checked for subtyping.
662 const String& class_name = String::Handle(cls.Name());
663 const String& super_class_name = String::Handle(super_class.Name());
664 ReportError("class '%s' overrides function '%s' of super class '%s' "
665 "with incompatible parameters.\n",
666 class_name.ToCString(),
667 function_name.ToCString(),
668 super_class_name.ToCString());
669 }
670 super_class = super_class.SuperClass();
671 }
630 } 672 }
631 if (function.kind() == RawFunction::kGetterFunction) { 673 if (function.kind() == RawFunction::kGetterFunction) {
632 name = String::New("get:"); 674 name = Field::NameFromGetter(function_name);
633 name = String::SubString(func_name, name.Length()); 675 super_class = FunctionSuperOwner(cls, name);
634 if (FuncNameExistsInSuper(cls, name)) { 676 if (!super_class.IsNull()) {
635 ReportError("'%s' overrides a function in the super class.\n", 677 const String& class_name = String::Handle(cls.Name());
636 func_name.ToCString()); 678 const String& super_class_name = String::Handle(super_class.Name());
679 ReportError("getter '%s' of class '%s' conflicts with "
680 "function '%s' of super class '%s'.\n",
681 name.ToCString(),
682 class_name.ToCString(),
683 name.ToCString(),
684 super_class_name.ToCString());
637 } 685 }
638 } 686 } else if (function.kind() == RawFunction::kSetterFunction) {
639 if (function.kind() == RawFunction::kSetterFunction) { 687 name = Field::NameFromSetter(function_name);
640 name = String::New("set:"); 688 super_class = FunctionSuperOwner(cls, name);
641 name = String::SubString(func_name, name.Length()); 689 if (!super_class.IsNull()) {
642 if (FuncNameExistsInSuper(cls, name)) { 690 const String& class_name = String::Handle(cls.Name());
643 ReportError("'%s' overrides a function in the super class.\n", 691 const String& super_class_name = String::Handle(super_class.Name());
644 func_name.ToCString()); 692 ReportError("setter '%s' of class '%s' conflicts with "
693 "function '%s' of super class '%s'.\n",
694 name.ToCString(),
695 class_name.ToCString(),
696 name.ToCString(),
697 super_class_name.ToCString());
698 }
699 } else {
700 name = Field::GetterName(function_name);
701 super_class = FunctionSuperOwner(cls, name);
702 if (!super_class.IsNull()) {
703 const String& class_name = String::Handle(cls.Name());
704 const String& super_class_name = String::Handle(super_class.Name());
705 ReportError("function '%s' of class '%s' conflicts with "
706 "getter '%s' of super class '%s'.\n",
707 name.ToCString(),
siva 2011/10/21 17:13:32 I think this should be function_name.ToCString()
regis 2011/10/21 17:33:38 Good catch.
708 class_name.ToCString(),
709 name.ToCString(),
siva 2011/10/21 17:13:32 I think this should be function_name.ToCString()
regis 2011/10/21 17:33:38 Done.
710 super_class_name.ToCString());
711 }
712 name = Field::SetterName(function_name);
713 super_class = FunctionSuperOwner(cls, name);
714 if (!super_class.IsNull()) {
715 const String& class_name = String::Handle(cls.Name());
716 const String& super_class_name = String::Handle(super_class.Name());
717 ReportError("function '%s' of class '%s' conflicts with "
718 "setter '%s' of super class '%s'.\n",
719 name.ToCString(),
siva 2011/10/21 17:13:32 I think this should be function_name.ToCString()
regis 2011/10/21 17:33:38 Done.
720 class_name.ToCString(),
721 name.ToCString(),
siva 2011/10/21 17:13:32 I think this should be function_name.ToCString()
regis 2011/10/21 17:33:38 Done.
722 super_class_name.ToCString());
645 } 723 }
646 } 724 }
647 } 725 }
648 // Resolve the signature type if this class is a signature class. 726 // Resolve the signature type if this class is a signature class.
649 if (cls.IsSignatureClass()) { 727 if (cls.IsSignatureClass()) {
650 const Type& signature_type = Type::Handle(cls.SignatureType()); 728 const Type& signature_type = Type::Handle(cls.SignatureType());
651 FinalizeType(signature_type); 729 FinalizeType(signature_type);
652 } 730 }
653 } 731 }
654 732
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 Array& interface_types = Array::Handle(cls.interfaces()); 771 Array& interface_types = Array::Handle(cls.interfaces());
694 Type& interface_type = Type::Handle(); 772 Type& interface_type = Type::Handle();
695 for (intptr_t i = 0; i < interface_types.Length(); i++) { 773 for (intptr_t i = 0; i < interface_types.Length(); i++) {
696 interface_type ^= interface_types.At(i); 774 interface_type ^= interface_types.At(i);
697 FinalizeType(interface_type); 775 FinalizeType(interface_type);
698 } 776 }
699 // Mark as finalized before resolving member types in order to break cycles. 777 // Mark as finalized before resolving member types in order to break cycles.
700 cls.Finalize(); 778 cls.Finalize();
701 ResolveAndFinalizeMemberTypes(cls); 779 ResolveAndFinalizeMemberTypes(cls);
702 // Run additional checks after all types are finalized. 780 // Run additional checks after all types are finalized.
703 if (!cls.is_interface()) {
704 CheckForLegalOverrides(cls);
705 }
706 if (cls.is_const()) { 781 if (cls.is_const()) {
707 CheckForLegalConstClass(cls); 782 CheckForLegalConstClass(cls);
708 } 783 }
709 } 784 }
710 785
711 786
712 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { 787 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
713 Class& test1 = Class::Handle(cls.raw()); 788 Class& test1 = Class::Handle(cls.raw());
714 Class& test2 = Class::Handle(cls.SuperClass()); 789 Class& test2 = Class::Handle(cls.SuperClass());
715 // A finalized class has been checked for cycles. 790 // A finalized class has been checked for cycles.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 // TODO(regis): Verify that unless cls is in core lib, it cannot implement 885 // TODO(regis): Verify that unless cls is in core lib, it cannot implement
811 // an instance of Number or String. Any other? bool? 886 // an instance of Number or String. Any other? bool?
812 887
813 // Now resolve the super interfaces. 888 // Now resolve the super interfaces.
814 ResolveInterfaces(interface_class, visited); 889 ResolveInterfaces(interface_class, visited);
815 } 890 }
816 visited->RemoveLast(); 891 visited->RemoveLast();
817 } 892 }
818 893
819 894
820 void ClassFinalizer::CheckForLegalOverrides(const Class& cls) {
821 HANDLESCOPE();
822 const Class& super = Class::Handle(cls.SuperClass());
823 if (super.IsNull()) {
824 return;
825 }
826 if (FLAG_enable_type_checks) {
827 // Check functions.
828 const Array& functions_array = Array::Handle(cls.functions());
829 Function& function = Function::Handle();
830 String& function_name = String::Handle();
831 const intptr_t len = functions_array.Length();
832 for (intptr_t i = 0; i < len; i++) {
833 function ^= functions_array.At(i);
834 if (!function.is_static()) {
835 function_name ^= function.name();
836 Function& overridden_function =
837 Function::Handle(super.LookupDynamicFunction(function_name));
838 if (!overridden_function.IsNull() &&
839 !function.IsSubtypeOf(overridden_function)) {
840 const String& class_name = String::Handle(cls.Name());
841 const String& super_class_name = String::Handle(
842 Class::Handle(overridden_function.owner()).Name());
843 ReportError("The type of instance method '%s' in class '%s' is "
844 "not a subtype of the type of overriden instance "
845 "method '%s' in class '%s'\n",
846 function_name.ToCString(),
847 class_name.ToCString(),
848 function_name.ToCString(),
849 super_class_name.ToCString());
850 }
851 }
852 }
853 }
854 // Check fields.
855 const Array& fields_array = Array::Handle(cls.fields());
856 Field& field = Field::Handle();
857 String& field_name = String::Handle();
858 const intptr_t len = fields_array.Length();
859 for (intptr_t i = 0; i < len; i++) {
860 field ^= fields_array.At(i);
861 field_name ^= field.name();
862 Field& super_field = Field::Handle(super.LookupStaticField(field_name));
863 if (super_field.IsNull()) {
864 super_field = super.LookupInstanceField(field_name);
865 }
866 if (!super_field.IsNull()) {
867 // A static field may "override" a static field.
868 if (!super_field.is_static() || !field.is_static()) {
869 const String& class_name = String::Handle(cls.Name());
870 ReportError("class '%s' cannot override field '%s'.\n",
871 class_name.ToCString(), field_name.ToCString());
872 }
873 }
874 }
875 }
876
877
878 // A class is marked as constant if it has one constant constructor. 895 // A class is marked as constant if it has one constant constructor.
879 // A constant class: 896 // A constant class:
880 // - may extend only const classes. 897 // - may extend only const classes.
881 // - has only const instance fields. 898 // - has only const instance fields.
882 // Note: we must check for cycles before checking for const properties. 899 // Note: we must check for cycles before checking for const properties.
883 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { 900 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) {
884 ASSERT(cls.is_const()); 901 ASSERT(cls.is_const());
885 const Class& super = Class::Handle(cls.SuperClass()); 902 const Class& super = Class::Handle(cls.SuperClass());
886 if (!super.IsNull() && !super.is_const()) { 903 if (!super.IsNull() && !super.is_const()) {
887 String& name = String::Handle(super.Name()); 904 String& name = String::Handle(super.Name());
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 ASSERT(msg_buffer != NULL); 1002 ASSERT(msg_buffer != NULL);
986 va_list args; 1003 va_list args;
987 va_start(args, format); 1004 va_start(args, format);
988 OS::VSNPrint(msg_buffer, kBufferLength, format, args); 1005 OS::VSNPrint(msg_buffer, kBufferLength, format, args);
989 va_end(args); 1006 va_end(args);
990 isolate->long_jump_base()->Jump(1, msg_buffer); 1007 isolate->long_jump_base()->Jump(1, msg_buffer);
991 UNREACHABLE(); 1008 UNREACHABLE();
992 } 1009 }
993 1010
994 } // namespace dart 1011 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698