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

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 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 const intptr_t num_parameters = function.NumberOfParameters(); 553 const intptr_t num_parameters = function.NumberOfParameters();
554 for (intptr_t i = 0; i < num_parameters; i++) { 554 for (intptr_t i = 0; i < num_parameters; i++) {
555 type = function.ParameterTypeAt(i); 555 type = function.ParameterTypeAt(i);
556 type = ResolveType(cls, type); 556 type = ResolveType(cls, type);
557 function.SetParameterTypeAt(i, type); 557 function.SetParameterTypeAt(i, type);
558 FinalizeType(type); 558 FinalizeType(type);
559 } 559 }
560 } 560 }
561 561
562 562
563 static bool FuncNameExistsInSuper(const Class& cls, 563 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls,
564 const String& name) { 564 const String& name) {
565 Class& super_class = Class::Handle();
566 Function& function = Function::Handle();
567 Field& field = Field::Handle();
568 super_class = cls.SuperClass();
569 while (!super_class.IsNull()) {
570 // Check if an instance member of same name exists in any super class.
571 function = super_class.LookupFunction(name);
572 if (!function.IsNull() && !function.is_static()) {
573 return super_class.raw();
574 }
575 field = super_class.LookupField(name);
576 if (!field.IsNull() && !field.is_static()) {
577 return super_class.raw();
578 }
579 super_class = super_class.SuperClass();
580 }
581 return Class::null();
582 }
583
584
585 static RawClass* FindSuperOwnerOfFunction(const Class& cls,
586 const String& name) {
565 Class& super_class = Class::Handle(); 587 Class& super_class = Class::Handle();
566 Function& function = Function::Handle(); 588 Function& function = Function::Handle();
567 super_class = cls.SuperClass(); 589 super_class = cls.SuperClass();
568 while (!super_class.IsNull()) { 590 while (!super_class.IsNull()) {
569 // Check if a field of same name exists in any super class. 591 // Check if a function of same name exists in any super class.
570 function = super_class.LookupFunction(name); 592 function = super_class.LookupFunction(name);
571 if (!function.IsNull()) { 593 if (!function.IsNull()) {
572 return true; 594 return super_class.raw();
573 } 595 }
574 super_class = super_class.SuperClass(); 596 super_class = super_class.SuperClass();
575 } 597 }
576 return false; 598 return Class::null();
577 }
578
579
580 static bool FieldNameExistsInSuper(const Class& cls, const String& name) {
581 Class& super_class = Class::Handle();
582 Field& field = Field::Handle();
583 super_class = cls.SuperClass();
584 while (!super_class.IsNull()) {
585 // Check if a function of same name exists in any super class.
586 field = super_class.LookupField(name);
587 if (!field.IsNull()) {
588 return true;
589 }
590 super_class = super_class.SuperClass();
591 }
592 return false;
593 } 599 }
594 600
595 601
596 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { 602 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
597 // Resolve type of fields. 603 // Note that getters and setters are explicitly listed as such in the list of
604 // functions of a class, so we do not need to consider fields as implicitly
605 // generating getters and setters.
606 // The only compile errors we report are therefore:
607 // - a getter having the same name as a method (but not a getter) in a super
608 // class or in a subclass.
609 // - a setter having the same name as a method (but not a setter) in a super
610 // class or in a subclass.
611 // - a static field, instance field, or static method (but not an instance
612 // method) having the same name as an instance member in a super class.
613
614 // Resolve type of fields and check for conflicts in super classes.
598 Array& array = Array::Handle(cls.fields()); 615 Array& array = Array::Handle(cls.fields());
599 Field& field = Field::Handle(); 616 Field& field = Field::Handle();
600 Type& type = Type::Handle(); 617 Type& type = Type::Handle();
618 String& name = String::Handle();
619 Class& super_class = Class::Handle();
601 intptr_t num_fields = array.Length(); 620 intptr_t num_fields = array.Length();
602 String& name = String::Handle();
603 for (intptr_t i = 0; i < num_fields; i++) { 621 for (intptr_t i = 0; i < num_fields; i++) {
604 field ^= array.At(i); 622 field ^= array.At(i);
605 type = field.type(); 623 type = field.type();
606 type = ResolveType(cls, type); 624 type = ResolveType(cls, type);
607 field.set_type(type); 625 field.set_type(type);
608 FinalizeType(type); 626 FinalizeType(type);
609 name = field.name(); 627 name = field.name();
610 if (FuncNameExistsInSuper(cls, name)) { 628 super_class = FindSuperOwnerOfInstanceMember(cls, name);
611 ReportError("field '%s' overrides a function in the super class.\n", 629 if (!super_class.IsNull()) {
612 name.ToCString()); 630 const String& class_name = String::Handle(cls.Name());
631 const String& super_class_name = String::Handle(super_class.Name());
632 ReportError("field '%s' of class '%s' conflicts with instance "
633 "member '%s' of super class '%s'.\n",
634 name.ToCString(),
635 class_name.ToCString(),
636 name.ToCString(),
637 super_class_name.ToCString());
613 } 638 }
614 } 639 }
615 // Resolve function signatures. 640 // Resolve function signatures and check for conflicts in super classes.
616 array = cls.functions(); 641 array = cls.functions();
617 Function& function = Function::Handle(); 642 Function& function = Function::Handle();
643 Function& overridden_function = Function::Handle();
618 intptr_t num_functions = array.Length(); 644 intptr_t num_functions = array.Length();
619 String& func_name = String::Handle(); 645 String& function_name = String::Handle();
620 for (intptr_t i = 0; i < num_functions; i++) { 646 for (intptr_t i = 0; i < num_functions; i++) {
621 function ^= array.At(i); 647 function ^= array.At(i);
622 ResolveAndFinalizeSignature(cls, function); 648 ResolveAndFinalizeSignature(cls, function);
623 func_name = function.name(); 649 function_name = function.name();
624 if (FieldNameExistsInSuper(cls, func_name)) { 650 if (function.is_static()) {
625 ReportError("function '%s' overrides a field in the super class.\n", 651 super_class = FindSuperOwnerOfInstanceMember(cls, function_name);
626 func_name.ToCString()); 652 if (!super_class.IsNull()) {
627 } 653 const String& class_name = String::Handle(cls.Name());
628 name = Field::GetterName(func_name); 654 const String& super_class_name = String::Handle(super_class.Name());
629 if (FuncNameExistsInSuper(cls, name)) { 655 ReportError("static function '%s' of class '%s' conflicts with "
630 ReportError("function '%s' overrides a getter in the super class.\n", 656 "instance member '%s' of super class '%s'.\n",
631 name.ToCString()); 657 function_name.ToCString(),
632 } 658 class_name.ToCString(),
633 name = Field::SetterName(func_name); 659 function_name.ToCString(),
634 if (FuncNameExistsInSuper(cls, name)) { 660 super_class_name.ToCString());
635 ReportError("function '%s' overrides a setter in the super class.\n", 661 }
636 name.ToCString()); 662 } else {
663 // TODO(regis): This arity check is still being debated. Revisit.
664 super_class = cls.SuperClass();
665 while (!super_class.IsNull()) {
666 overridden_function = super_class.LookupDynamicFunction(function_name);
667 if (!overridden_function.IsNull() &&
668 !function.HasCompatibleParametersWith(overridden_function)) {
669 // Function types are purposely not checked for subtyping.
670 const String& class_name = String::Handle(cls.Name());
671 const String& super_class_name = String::Handle(super_class.Name());
672 ReportError("class '%s' overrides function '%s' of super class '%s' "
673 "with incompatible parameters.\n",
674 class_name.ToCString(),
675 function_name.ToCString(),
676 super_class_name.ToCString());
677 }
678 super_class = super_class.SuperClass();
679 }
637 } 680 }
638 if (function.kind() == RawFunction::kGetterFunction) { 681 if (function.kind() == RawFunction::kGetterFunction) {
639 name = String::New("get:"); 682 name = Field::NameFromGetter(function_name);
640 name = String::SubString(func_name, name.Length()); 683 super_class = FindSuperOwnerOfFunction(cls, name);
641 if (FuncNameExistsInSuper(cls, name)) { 684 if (!super_class.IsNull()) {
642 ReportError("'%s' overrides a function in the super class.\n", 685 const String& class_name = String::Handle(cls.Name());
643 func_name.ToCString()); 686 const String& super_class_name = String::Handle(super_class.Name());
687 ReportError("getter '%s' of class '%s' conflicts with "
688 "function '%s' of super class '%s'.\n",
689 name.ToCString(),
690 class_name.ToCString(),
691 name.ToCString(),
692 super_class_name.ToCString());
644 } 693 }
645 } 694 } else if (function.kind() == RawFunction::kSetterFunction) {
646 if (function.kind() == RawFunction::kSetterFunction) { 695 name = Field::NameFromSetter(function_name);
647 name = String::New("set:"); 696 super_class = FindSuperOwnerOfFunction(cls, name);
648 name = String::SubString(func_name, name.Length()); 697 if (!super_class.IsNull()) {
649 if (FuncNameExistsInSuper(cls, name)) { 698 const String& class_name = String::Handle(cls.Name());
650 ReportError("'%s' overrides a function in the super class.\n", 699 const String& super_class_name = String::Handle(super_class.Name());
651 func_name.ToCString()); 700 ReportError("setter '%s' of class '%s' conflicts with "
701 "function '%s' of super class '%s'.\n",
702 name.ToCString(),
703 class_name.ToCString(),
704 name.ToCString(),
705 super_class_name.ToCString());
706 }
707 } else {
708 name = Field::GetterName(function_name);
709 super_class = FindSuperOwnerOfFunction(cls, name);
710 if (!super_class.IsNull()) {
711 const String& class_name = String::Handle(cls.Name());
712 const String& super_class_name = String::Handle(super_class.Name());
713 ReportError("function '%s' of class '%s' conflicts with "
714 "getter '%s' of super class '%s'.\n",
715 function_name.ToCString(),
716 class_name.ToCString(),
717 function_name.ToCString(),
718 super_class_name.ToCString());
719 }
720 name = Field::SetterName(function_name);
721 super_class = FindSuperOwnerOfFunction(cls, name);
722 if (!super_class.IsNull()) {
723 const String& class_name = String::Handle(cls.Name());
724 const String& super_class_name = String::Handle(super_class.Name());
725 ReportError("function '%s' of class '%s' conflicts with "
726 "setter '%s' of super class '%s'.\n",
727 function_name.ToCString(),
728 class_name.ToCString(),
729 function_name.ToCString(),
730 super_class_name.ToCString());
652 } 731 }
653 } 732 }
654 } 733 }
655 // Resolve the signature type if this class is a signature class. 734 // Resolve the signature type if this class is a signature class.
656 if (cls.IsSignatureClass()) { 735 if (cls.IsSignatureClass()) {
657 const Type& signature_type = Type::Handle(cls.SignatureType()); 736 const Type& signature_type = Type::Handle(cls.SignatureType());
658 FinalizeType(signature_type); 737 FinalizeType(signature_type);
659 } 738 }
660 } 739 }
661 740
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 Array& interface_types = Array::Handle(cls.interfaces()); 779 Array& interface_types = Array::Handle(cls.interfaces());
701 Type& interface_type = Type::Handle(); 780 Type& interface_type = Type::Handle();
702 for (intptr_t i = 0; i < interface_types.Length(); i++) { 781 for (intptr_t i = 0; i < interface_types.Length(); i++) {
703 interface_type ^= interface_types.At(i); 782 interface_type ^= interface_types.At(i);
704 FinalizeType(interface_type); 783 FinalizeType(interface_type);
705 } 784 }
706 // Mark as finalized before resolving member types in order to break cycles. 785 // Mark as finalized before resolving member types in order to break cycles.
707 cls.Finalize(); 786 cls.Finalize();
708 ResolveAndFinalizeMemberTypes(cls); 787 ResolveAndFinalizeMemberTypes(cls);
709 // Run additional checks after all types are finalized. 788 // Run additional checks after all types are finalized.
710 if (!cls.is_interface()) {
711 CheckForLegalOverrides(cls);
712 }
713 if (cls.is_const()) { 789 if (cls.is_const()) {
714 CheckForLegalConstClass(cls); 790 CheckForLegalConstClass(cls);
715 } 791 }
716 } 792 }
717 793
718 794
719 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { 795 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
720 Class& test1 = Class::Handle(cls.raw()); 796 Class& test1 = Class::Handle(cls.raw());
721 Class& test2 = Class::Handle(cls.SuperClass()); 797 Class& test2 = Class::Handle(cls.SuperClass());
722 // A finalized class has been checked for cycles. 798 // A finalized class has been checked for cycles.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 // TODO(regis): Verify that unless cls is in core lib, it cannot implement 893 // TODO(regis): Verify that unless cls is in core lib, it cannot implement
818 // an instance of Number or String. Any other? bool? 894 // an instance of Number or String. Any other? bool?
819 895
820 // Now resolve the super interfaces. 896 // Now resolve the super interfaces.
821 ResolveInterfaces(interface_class, visited); 897 ResolveInterfaces(interface_class, visited);
822 } 898 }
823 visited->RemoveLast(); 899 visited->RemoveLast();
824 } 900 }
825 901
826 902
827 void ClassFinalizer::CheckForLegalOverrides(const Class& cls) {
828 HANDLESCOPE();
829 const Class& super = Class::Handle(cls.SuperClass());
830 if (super.IsNull()) {
831 return;
832 }
833 if (FLAG_enable_type_checks) {
834 // Check functions.
835 const Array& functions_array = Array::Handle(cls.functions());
836 Function& function = Function::Handle();
837 String& function_name = String::Handle();
838 const intptr_t len = functions_array.Length();
839 for (intptr_t i = 0; i < len; i++) {
840 function ^= functions_array.At(i);
841 if (!function.is_static()) {
842 function_name ^= function.name();
843 Function& overridden_function =
844 Function::Handle(super.LookupDynamicFunction(function_name));
845 if (!overridden_function.IsNull() &&
846 !function.IsSubtypeOf(overridden_function)) {
847 const String& class_name = String::Handle(cls.Name());
848 const String& super_class_name = String::Handle(
849 Class::Handle(overridden_function.owner()).Name());
850 ReportError("The type of instance method '%s' in class '%s' is "
851 "not a subtype of the type of overriden instance "
852 "method '%s' in class '%s'\n",
853 function_name.ToCString(),
854 class_name.ToCString(),
855 function_name.ToCString(),
856 super_class_name.ToCString());
857 }
858 }
859 }
860 }
861 // Check fields.
862 const Array& fields_array = Array::Handle(cls.fields());
863 Field& field = Field::Handle();
864 String& field_name = String::Handle();
865 const intptr_t len = fields_array.Length();
866 for (intptr_t i = 0; i < len; i++) {
867 field ^= fields_array.At(i);
868 field_name ^= field.name();
869 Field& super_field = Field::Handle(super.LookupStaticField(field_name));
870 if (super_field.IsNull()) {
871 super_field = super.LookupInstanceField(field_name);
872 }
873 if (!super_field.IsNull()) {
874 // A static field may "override" a static field.
875 if (!super_field.is_static() || !field.is_static()) {
876 const String& class_name = String::Handle(cls.Name());
877 ReportError("class '%s' cannot override field '%s'.\n",
878 class_name.ToCString(), field_name.ToCString());
879 }
880 }
881 }
882 }
883
884
885 // A class is marked as constant if it has one constant constructor. 903 // A class is marked as constant if it has one constant constructor.
886 // A constant class: 904 // A constant class:
887 // - may extend only const classes. 905 // - may extend only const classes.
888 // - has only const instance fields. 906 // - has only const instance fields.
889 // Note: we must check for cycles before checking for const properties. 907 // Note: we must check for cycles before checking for const properties.
890 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { 908 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) {
891 ASSERT(cls.is_const()); 909 ASSERT(cls.is_const());
892 const Class& super = Class::Handle(cls.SuperClass()); 910 const Class& super = Class::Handle(cls.SuperClass());
893 if (!super.IsNull() && !super.is_const()) { 911 if (!super.IsNull() && !super.is_const()) {
894 String& name = String::Handle(super.Name()); 912 String& name = String::Handle(super.Name());
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 ASSERT(msg_buffer != NULL); 1010 ASSERT(msg_buffer != NULL);
993 va_list args; 1011 va_list args;
994 va_start(args, format); 1012 va_start(args, format);
995 OS::VSNPrint(msg_buffer, kBufferLength, format, args); 1013 OS::VSNPrint(msg_buffer, kBufferLength, format, args);
996 va_end(args); 1014 va_end(args);
997 isolate->long_jump_base()->Jump(1, msg_buffer); 1015 isolate->long_jump_base()->Jump(1, msg_buffer);
998 UNREACHABLE(); 1016 UNREACHABLE();
999 } 1017 }
1000 1018
1001 } // namespace dart 1019 } // 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