OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 type = function.ParameterTypeAt(i); | 925 type = function.ParameterTypeAt(i); |
926 ResolveType(cls, type, kCanonicalize); | 926 ResolveType(cls, type, kCanonicalize); |
927 type = FinalizeType(cls, type, kCanonicalize); | 927 type = FinalizeType(cls, type, kCanonicalize); |
928 // A malformed parameter type is mapped to dynamic. | 928 // A malformed parameter type is mapped to dynamic. |
929 ASSERT(!type.IsMalformed()); | 929 ASSERT(!type.IsMalformed()); |
930 function.SetParameterTypeAt(i, type); | 930 function.SetParameterTypeAt(i, type); |
931 } | 931 } |
932 } | 932 } |
933 | 933 |
934 | 934 |
935 // Check if an instance field or method of same name exists | 935 // Check if an instance field, getter, or method of same name exists |
936 // in any super class. | 936 // in any super class. |
937 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls, | 937 static RawClass* FindSuperOwnerOfInstanceMember(const Class& cls, |
938 const String& name) { | 938 const String& name, |
| 939 const String& getter_name) { |
939 Class& super_class = Class::Handle(); | 940 Class& super_class = Class::Handle(); |
940 Function& function = Function::Handle(); | 941 Function& function = Function::Handle(); |
941 Field& field = Field::Handle(); | 942 Field& field = Field::Handle(); |
942 super_class = cls.SuperClass(); | 943 super_class = cls.SuperClass(); |
943 while (!super_class.IsNull()) { | 944 while (!super_class.IsNull()) { |
944 function = super_class.LookupFunction(name); | 945 function = super_class.LookupFunction(name); |
945 if (!function.IsNull() && !function.is_static()) { | 946 if (!function.IsNull() && !function.is_static()) { |
946 return super_class.raw(); | 947 return super_class.raw(); |
947 } | 948 } |
| 949 function = super_class.LookupFunction(getter_name); |
| 950 if (!function.IsNull() && !function.is_static()) { |
| 951 return super_class.raw(); |
| 952 } |
948 field = super_class.LookupField(name); | 953 field = super_class.LookupField(name); |
949 if (!field.IsNull() && !field.is_static()) { | 954 if (!field.IsNull() && !field.is_static()) { |
950 return super_class.raw(); | 955 return super_class.raw(); |
951 } | 956 } |
952 super_class = super_class.SuperClass(); | 957 super_class = super_class.SuperClass(); |
953 } | 958 } |
954 return Class::null(); | 959 return Class::null(); |
955 } | 960 } |
956 | 961 |
957 | 962 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 bound = FinalizeType(cls, bound, kCanonicalize); | 1017 bound = FinalizeType(cls, bound, kCanonicalize); |
1013 type_param.set_bound(bound); | 1018 type_param.set_bound(bound); |
1014 } | 1019 } |
1015 } | 1020 } |
1016 | 1021 |
1017 | 1022 |
1018 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { | 1023 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
1019 // Note that getters and setters are explicitly listed as such in the list of | 1024 // Note that getters and setters are explicitly listed as such in the list of |
1020 // functions of a class, so we do not need to consider fields as implicitly | 1025 // functions of a class, so we do not need to consider fields as implicitly |
1021 // generating getters and setters. | 1026 // generating getters and setters. |
1022 // The only compile errors we report are therefore: | 1027 // Most overriding conflicts are only static warnings, i.e. they are not |
1023 // - a getter having the same name as a method (but not a getter) in a super | 1028 // reported as compile-time errors by the vm. However, signature conflicts in |
1024 // class or in a subclass. | 1029 // overrides can be reported if the flag --error_on_bad_override is specified. |
1025 // - a static field, instance field, or static method (but not an instance | 1030 // Static warning examples are: |
1026 // method) having the same name as an instance member in a super class. | 1031 // - a static getter 'v' conflicting with an inherited instance setter 'v='. |
| 1032 // - a static setter 'v=' conflicting with an inherited instance member 'v'. |
| 1033 // - an instance member 'v' conflicting with an accessible static member 'v' |
| 1034 // or 'v=' of a super class (except that an instance method 'v' does not |
| 1035 // conflict with an accessible static setter 'v=' of a super class). |
| 1036 // The compile-time errors we report are: |
| 1037 // - a static member 'v' conflicting with an inherited instance member 'v'. |
| 1038 // - a static setter 'v=' conflicting with an inherited instance setter 'v='. |
| 1039 // - an instance method conflicting with an inherited instance field or |
| 1040 // instance getter. |
| 1041 // - an instance field or instance getter conflicting with an inherited |
| 1042 // instance method. |
1027 | 1043 |
1028 // Resolve type of fields and check for conflicts in super classes. | 1044 // Resolve type of fields and check for conflicts in super classes. |
1029 Array& array = Array::Handle(cls.fields()); | 1045 Array& array = Array::Handle(cls.fields()); |
1030 Field& field = Field::Handle(); | 1046 Field& field = Field::Handle(); |
1031 AbstractType& type = AbstractType::Handle(); | 1047 AbstractType& type = AbstractType::Handle(); |
1032 String& name = String::Handle(); | 1048 String& name = String::Handle(); |
| 1049 String& getter_name = String::Handle(); |
1033 Class& super_class = Class::Handle(); | 1050 Class& super_class = Class::Handle(); |
1034 const intptr_t num_fields = array.Length(); | 1051 const intptr_t num_fields = array.Length(); |
1035 for (intptr_t i = 0; i < num_fields; i++) { | 1052 for (intptr_t i = 0; i < num_fields; i++) { |
1036 field ^= array.At(i); | 1053 field ^= array.At(i); |
1037 type = field.type(); | 1054 type = field.type(); |
1038 ResolveType(cls, type, kCanonicalize); | 1055 ResolveType(cls, type, kCanonicalize); |
1039 type = FinalizeType(cls, type, kCanonicalize); | 1056 type = FinalizeType(cls, type, kCanonicalize); |
1040 field.set_type(type); | 1057 field.set_type(type); |
1041 name = field.name(); | 1058 name = field.name(); |
1042 if (field.is_static()) { | 1059 if (field.is_static()) { |
1043 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 1060 getter_name = Field::GetterSymbol(name); |
| 1061 super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name); |
1044 if (!super_class.IsNull()) { | 1062 if (!super_class.IsNull()) { |
1045 const String& class_name = String::Handle(cls.Name()); | 1063 const String& class_name = String::Handle(cls.Name()); |
1046 const String& super_class_name = String::Handle(super_class.Name()); | 1064 const String& super_class_name = String::Handle(super_class.Name()); |
1047 const Script& script = Script::Handle(cls.script()); | 1065 const Script& script = Script::Handle(cls.script()); |
1048 ReportError(Error::Handle(), // No previous error. | 1066 ReportError(Error::Handle(), // No previous error. |
1049 script, field.token_pos(), | 1067 script, field.token_pos(), |
1050 "static field '%s' of class '%s' conflicts with " | 1068 "static field '%s' of class '%s' conflicts with " |
1051 "instance member '%s' of super class '%s'", | 1069 "instance member '%s' of super class '%s'", |
1052 name.ToCString(), | 1070 name.ToCString(), |
1053 class_name.ToCString(), | 1071 class_name.ToCString(), |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 type_name.ToCString()); | 1123 type_name.ToCString()); |
1106 } else { | 1124 } else { |
1107 // Do not report an error yet, even in checked mode, since the field | 1125 // Do not report an error yet, even in checked mode, since the field |
1108 // may not actually be used. | 1126 // may not actually be used. |
1109 // Also, we may be generating a snapshot in production mode that will | 1127 // Also, we may be generating a snapshot in production mode that will |
1110 // later be executed in checked mode, in which case an error needs to | 1128 // later be executed in checked mode, in which case an error needs to |
1111 // be reported, should the field be accessed. | 1129 // be reported, should the field be accessed. |
1112 // Therefore, we undo the optimization performed by the parser, i.e. | 1130 // Therefore, we undo the optimization performed by the parser, i.e. |
1113 // we create an implicit static final getter and reset the field value | 1131 // we create an implicit static final getter and reset the field value |
1114 // to the sentinel value. | 1132 // to the sentinel value. |
1115 const String& getter_name = String::Handle(Field::GetterSymbol(name)); | |
1116 const Function& getter = Function::Handle( | 1133 const Function& getter = Function::Handle( |
1117 Function::New(getter_name, | 1134 Function::New(getter_name, |
1118 RawFunction::kImplicitStaticFinalGetter, | 1135 RawFunction::kImplicitStaticFinalGetter, |
1119 /* is_static = */ true, | 1136 /* is_static = */ true, |
1120 /* is_const = */ field.is_const(), | 1137 /* is_const = */ field.is_const(), |
1121 /* is_abstract = */ false, | 1138 /* is_abstract = */ false, |
1122 /* is_external = */ false, | 1139 /* is_external = */ false, |
1123 cls, | 1140 cls, |
1124 field.token_pos())); | 1141 field.token_pos())); |
1125 getter.set_result_type(type); | 1142 getter.set_result_type(type); |
(...skipping 13 matching lines...) Expand all Loading... |
1139 interfaces.Add(super_class); | 1156 interfaces.Add(super_class); |
1140 CollectInterfaces(super_class, interfaces); | 1157 CollectInterfaces(super_class, interfaces); |
1141 super_class = super_class.SuperClass(); | 1158 super_class = super_class.SuperClass(); |
1142 } | 1159 } |
1143 // Resolve function signatures and check for conflicts in super classes and | 1160 // Resolve function signatures and check for conflicts in super classes and |
1144 // interfaces. | 1161 // interfaces. |
1145 array = cls.functions(); | 1162 array = cls.functions(); |
1146 Function& function = Function::Handle(); | 1163 Function& function = Function::Handle(); |
1147 Function& overridden_function = Function::Handle(); | 1164 Function& overridden_function = Function::Handle(); |
1148 const intptr_t num_functions = array.Length(); | 1165 const intptr_t num_functions = array.Length(); |
1149 String& function_name = String::Handle(); | |
1150 Error& error = Error::Handle(); | 1166 Error& error = Error::Handle(); |
1151 for (intptr_t i = 0; i < num_functions; i++) { | 1167 for (intptr_t i = 0; i < num_functions; i++) { |
1152 function ^= array.At(i); | 1168 function ^= array.At(i); |
1153 ResolveAndFinalizeSignature(cls, function); | 1169 ResolveAndFinalizeSignature(cls, function); |
1154 function_name = function.name(); | 1170 name = function.name(); |
| 1171 if (FLAG_error_on_bad_override && // Report signature conflicts only. |
| 1172 !function.is_static() && !function.IsConstructor()) { |
| 1173 // A constructor cannot override anything. |
| 1174 for (int i = 0; i < interfaces.Length(); i++) { |
| 1175 super_class ^= interfaces.At(i); |
| 1176 overridden_function = super_class.LookupDynamicFunction(name); |
| 1177 if (!overridden_function.IsNull() && |
| 1178 !function.HasCompatibleParametersWith(overridden_function, |
| 1179 &error)) { |
| 1180 const String& class_name = String::Handle(cls.Name()); |
| 1181 const String& super_class_name = String::Handle(super_class.Name()); |
| 1182 const Script& script = Script::Handle(cls.script()); |
| 1183 ReportError(error, script, function.token_pos(), |
| 1184 "class '%s' overrides method '%s' of super class '%s' " |
| 1185 "with incompatible parameters", |
| 1186 class_name.ToCString(), |
| 1187 name.ToCString(), |
| 1188 super_class_name.ToCString()); |
| 1189 } |
| 1190 } |
| 1191 } |
| 1192 if (function.IsSetterFunction()) { |
| 1193 if (function.is_static()) { |
| 1194 super_class = FindSuperOwnerOfFunction(cls, name); |
| 1195 if (!super_class.IsNull()) { |
| 1196 const String& class_name = String::Handle(cls.Name()); |
| 1197 const String& super_class_name = String::Handle(super_class.Name()); |
| 1198 const Script& script = Script::Handle(cls.script()); |
| 1199 ReportError(Error::Handle(), // No previous error. |
| 1200 script, function.token_pos(), |
| 1201 "static setter '%s' of class '%s' conflicts with " |
| 1202 "instance setter '%s' of super class '%s'", |
| 1203 name.ToCString(), |
| 1204 class_name.ToCString(), |
| 1205 name.ToCString(), |
| 1206 super_class_name.ToCString()); |
| 1207 } |
| 1208 } |
| 1209 continue; |
| 1210 } |
| 1211 if (function.IsGetterFunction()) { |
| 1212 getter_name = name.raw(); |
| 1213 name = Field::NameFromGetter(getter_name); |
| 1214 } else { |
| 1215 getter_name = Field::GetterSymbol(name); |
| 1216 } |
1155 if (function.is_static()) { | 1217 if (function.is_static()) { |
1156 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 1218 super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name); |
1157 if (!super_class.IsNull()) { | 1219 if (!super_class.IsNull()) { |
1158 const String& class_name = String::Handle(cls.Name()); | 1220 const String& class_name = String::Handle(cls.Name()); |
1159 const String& super_class_name = String::Handle(super_class.Name()); | 1221 const String& super_class_name = String::Handle(super_class.Name()); |
1160 const Script& script = Script::Handle(cls.script()); | 1222 const Script& script = Script::Handle(cls.script()); |
1161 ReportError(Error::Handle(), // No previous error. | 1223 ReportError(Error::Handle(), // No previous error. |
1162 script, function.token_pos(), | 1224 script, function.token_pos(), |
1163 "static function '%s' of class '%s' conflicts with " | 1225 "static method '%s' of class '%s' conflicts with " |
1164 "instance member '%s' of super class '%s'", | 1226 "instance member '%s' of super class '%s'", |
1165 function_name.ToCString(), | 1227 name.ToCString(), |
1166 class_name.ToCString(), | 1228 class_name.ToCString(), |
1167 function_name.ToCString(), | 1229 name.ToCString(), |
1168 super_class_name.ToCString()); | 1230 super_class_name.ToCString()); |
1169 } | 1231 } |
1170 // The function may be a still unresolved redirecting factory. Do not yet | 1232 // The function may be a still unresolved redirecting factory. Do not yet |
1171 // try to resolve it in order to avoid cycles in class finalization. | 1233 // try to resolve it in order to avoid cycles in class finalization. |
1172 } else if (FLAG_error_on_bad_override && !function.IsConstructor()) { | 1234 } else if (function.IsGetterFunction()) { |
1173 // A constructor cannot override anything. | |
1174 for (int i = 0; i < interfaces.Length(); i++) { | |
1175 super_class ^= interfaces.At(i); | |
1176 overridden_function = super_class.LookupDynamicFunction(function_name); | |
1177 if (!overridden_function.IsNull() && | |
1178 !function.HasCompatibleParametersWith(overridden_function, | |
1179 &error)) { | |
1180 // Function types are purposely not checked for subtyping. | |
1181 const String& class_name = String::Handle(cls.Name()); | |
1182 const String& super_class_name = String::Handle(super_class.Name()); | |
1183 const Script& script = Script::Handle(cls.script()); | |
1184 ReportError(error, script, function.token_pos(), | |
1185 "class '%s' overrides function '%s' of super class '%s' " | |
1186 "with incompatible parameters", | |
1187 class_name.ToCString(), | |
1188 function_name.ToCString(), | |
1189 super_class_name.ToCString()); | |
1190 } | |
1191 } | |
1192 } | |
1193 if (function.IsGetterFunction()) { | |
1194 name = Field::NameFromGetter(function_name); | |
1195 super_class = FindSuperOwnerOfFunction(cls, name); | 1235 super_class = FindSuperOwnerOfFunction(cls, name); |
1196 if (!super_class.IsNull()) { | 1236 if (!super_class.IsNull()) { |
1197 const String& class_name = String::Handle(cls.Name()); | 1237 const String& class_name = String::Handle(cls.Name()); |
1198 const String& super_class_name = String::Handle(super_class.Name()); | 1238 const String& super_class_name = String::Handle(super_class.Name()); |
1199 const Script& script = Script::Handle(cls.script()); | 1239 const Script& script = Script::Handle(cls.script()); |
1200 ReportError(Error::Handle(), // No previous error. | 1240 ReportError(Error::Handle(), // No previous error. |
1201 script, function.token_pos(), | 1241 script, function.token_pos(), |
1202 "getter '%s' of class '%s' conflicts with " | 1242 "getter '%s' of class '%s' conflicts with " |
1203 "function '%s' of super class '%s'", | 1243 "method '%s' of super class '%s'", |
1204 name.ToCString(), | 1244 name.ToCString(), |
1205 class_name.ToCString(), | 1245 class_name.ToCString(), |
1206 name.ToCString(), | 1246 name.ToCString(), |
1207 super_class_name.ToCString()); | 1247 super_class_name.ToCString()); |
1208 } | 1248 } |
1209 } else if (!function.IsSetterFunction()) { | 1249 } else if (!function.IsSetterFunction()) { |
1210 // A function cannot conflict with a setter, since they cannot | 1250 // A function cannot conflict with a setter, since they cannot |
1211 // have the same name. Thus, we do not need to check setters. | 1251 // have the same name. Thus, we do not need to check setters. |
1212 name = Field::GetterName(function_name); | 1252 super_class = FindSuperOwnerOfFunction(cls, getter_name); |
1213 super_class = FindSuperOwnerOfFunction(cls, name); | |
1214 if (!super_class.IsNull()) { | 1253 if (!super_class.IsNull()) { |
1215 const String& class_name = String::Handle(cls.Name()); | 1254 const String& class_name = String::Handle(cls.Name()); |
1216 const String& super_class_name = String::Handle(super_class.Name()); | 1255 const String& super_class_name = String::Handle(super_class.Name()); |
1217 const Script& script = Script::Handle(cls.script()); | 1256 const Script& script = Script::Handle(cls.script()); |
1218 ReportError(Error::Handle(), // No previous error. | 1257 ReportError(Error::Handle(), // No previous error. |
1219 script, function.token_pos(), | 1258 script, function.token_pos(), |
1220 "function '%s' of class '%s' conflicts with " | 1259 "method '%s' of class '%s' conflicts with " |
1221 "getter '%s' of super class '%s'", | 1260 "getter '%s' of super class '%s'", |
1222 function_name.ToCString(), | 1261 name.ToCString(), |
1223 class_name.ToCString(), | 1262 class_name.ToCString(), |
1224 function_name.ToCString(), | 1263 name.ToCString(), |
1225 super_class_name.ToCString()); | 1264 super_class_name.ToCString()); |
1226 } | 1265 } |
1227 } | 1266 } |
1228 } | 1267 } |
1229 } | 1268 } |
1230 | 1269 |
1231 | 1270 |
1232 // Copy the type parameters of the super and mixin classes to the | 1271 // Copy the type parameters of the super and mixin classes to the |
1233 // mixin application class. Change type arguments of super type and of | 1272 // mixin application class. Change type arguments of super type and of |
1234 // interfaces to refer to the respective type parameters of the mixin | 1273 // interfaces to refer to the respective type parameters of the mixin |
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2245 expected_name ^= String::New("_offset"); | 2284 expected_name ^= String::New("_offset"); |
2246 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2285 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
2247 field ^= fields_array.At(2); | 2286 field ^= fields_array.At(2); |
2248 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2287 ASSERT(field.Offset() == TypedDataView::length_offset()); |
2249 name ^= field.name(); | 2288 name ^= field.name(); |
2250 ASSERT(name.Equals("length")); | 2289 ASSERT(name.Equals("length")); |
2251 #endif | 2290 #endif |
2252 } | 2291 } |
2253 | 2292 |
2254 } // namespace dart | 2293 } // namespace dart |
OLD | NEW |