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(); |
| 1050 String& setter_name = String::Handle(); |
1033 Class& super_class = Class::Handle(); | 1051 Class& super_class = Class::Handle(); |
1034 const intptr_t num_fields = array.Length(); | 1052 const intptr_t num_fields = array.Length(); |
1035 for (intptr_t i = 0; i < num_fields; i++) { | 1053 for (intptr_t i = 0; i < num_fields; i++) { |
1036 field ^= array.At(i); | 1054 field ^= array.At(i); |
1037 type = field.type(); | 1055 type = field.type(); |
1038 ResolveType(cls, type, kCanonicalize); | 1056 ResolveType(cls, type, kCanonicalize); |
1039 type = FinalizeType(cls, type, kCanonicalize); | 1057 type = FinalizeType(cls, type, kCanonicalize); |
1040 field.set_type(type); | 1058 field.set_type(type); |
1041 name = field.name(); | 1059 name = field.name(); |
1042 if (field.is_static()) { | 1060 if (field.is_static()) { |
1043 super_class = FindSuperOwnerOfInstanceMember(cls, name); | 1061 getter_name = Field::GetterSymbol(name); |
| 1062 super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name); |
1044 if (!super_class.IsNull()) { | 1063 if (!super_class.IsNull()) { |
1045 const String& class_name = String::Handle(cls.Name()); | 1064 const String& class_name = String::Handle(cls.Name()); |
1046 const String& super_class_name = String::Handle(super_class.Name()); | 1065 const String& super_class_name = String::Handle(super_class.Name()); |
1047 const Script& script = Script::Handle(cls.script()); | 1066 const Script& script = Script::Handle(cls.script()); |
1048 ReportError(Error::Handle(), // No previous error. | 1067 ReportError(Error::Handle(), // No previous error. |
1049 script, field.token_pos(), | 1068 script, field.token_pos(), |
1050 "static field '%s' of class '%s' conflicts with " | 1069 "static field '%s' of class '%s' conflicts with " |
1051 "instance member '%s' of super class '%s'", | 1070 "instance member '%s' of super class '%s'", |
1052 name.ToCString(), | 1071 name.ToCString(), |
1053 class_name.ToCString(), | 1072 class_name.ToCString(), |
1054 name.ToCString(), | 1073 name.ToCString(), |
1055 super_class_name.ToCString()); | 1074 super_class_name.ToCString()); |
1056 } | 1075 } |
| 1076 // An implicit setter is not generated for a static field, therefore, we |
| 1077 // cannot rely on the code below handling the static setter case to report |
| 1078 // a conflict with an instance setter. So we check explicitly here. |
| 1079 setter_name = Field::SetterSymbol(name); |
| 1080 super_class = FindSuperOwnerOfFunction(cls, setter_name); |
| 1081 if (!super_class.IsNull()) { |
| 1082 const String& class_name = String::Handle(cls.Name()); |
| 1083 const String& super_class_name = String::Handle(super_class.Name()); |
| 1084 const Script& script = Script::Handle(cls.script()); |
| 1085 ReportError(Error::Handle(), // No previous error. |
| 1086 script, field.token_pos(), |
| 1087 "static field '%s' of class '%s' conflicts with " |
| 1088 "instance setter '%s=' of super class '%s'", |
| 1089 name.ToCString(), |
| 1090 class_name.ToCString(), |
| 1091 name.ToCString(), |
| 1092 super_class_name.ToCString()); |
| 1093 } |
| 1094 |
1057 } else { | 1095 } else { |
1058 // Instance field. Check whether the field overrides a method | 1096 // Instance field. Check whether the field overrides a method |
1059 // (but not getter). | 1097 // (but not getter). |
1060 super_class = FindSuperOwnerOfFunction(cls, name); | 1098 super_class = FindSuperOwnerOfFunction(cls, name); |
1061 if (!super_class.IsNull()) { | 1099 if (!super_class.IsNull()) { |
1062 const String& class_name = String::Handle(cls.Name()); | 1100 const String& class_name = String::Handle(cls.Name()); |
1063 const String& super_class_name = String::Handle(super_class.Name()); | 1101 const String& super_class_name = String::Handle(super_class.Name()); |
1064 const Script& script = Script::Handle(cls.script()); | 1102 const Script& script = Script::Handle(cls.script()); |
1065 ReportError(Error::Handle(), // No previous error. | 1103 ReportError(Error::Handle(), // No previous error. |
1066 script, field.token_pos(), | 1104 script, field.token_pos(), |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 type_name.ToCString()); | 1143 type_name.ToCString()); |
1106 } else { | 1144 } else { |
1107 // Do not report an error yet, even in checked mode, since the field | 1145 // Do not report an error yet, even in checked mode, since the field |
1108 // may not actually be used. | 1146 // may not actually be used. |
1109 // Also, we may be generating a snapshot in production mode that will | 1147 // 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 | 1148 // later be executed in checked mode, in which case an error needs to |
1111 // be reported, should the field be accessed. | 1149 // be reported, should the field be accessed. |
1112 // Therefore, we undo the optimization performed by the parser, i.e. | 1150 // Therefore, we undo the optimization performed by the parser, i.e. |
1113 // we create an implicit static final getter and reset the field value | 1151 // we create an implicit static final getter and reset the field value |
1114 // to the sentinel value. | 1152 // to the sentinel value. |
1115 const String& getter_name = String::Handle(Field::GetterSymbol(name)); | |
1116 const Function& getter = Function::Handle( | 1153 const Function& getter = Function::Handle( |
1117 Function::New(getter_name, | 1154 Function::New(getter_name, |
1118 RawFunction::kImplicitStaticFinalGetter, | 1155 RawFunction::kImplicitStaticFinalGetter, |
1119 /* is_static = */ true, | 1156 /* is_static = */ true, |
1120 /* is_const = */ field.is_const(), | 1157 /* is_const = */ field.is_const(), |
1121 /* is_abstract = */ false, | 1158 /* is_abstract = */ false, |
1122 /* is_external = */ false, | 1159 /* is_external = */ false, |
1123 cls, | 1160 cls, |
1124 field.token_pos())); | 1161 field.token_pos())); |
1125 getter.set_result_type(type); | 1162 getter.set_result_type(type); |
(...skipping 13 matching lines...) Expand all Loading... |
1139 interfaces.Add(super_class); | 1176 interfaces.Add(super_class); |
1140 CollectInterfaces(super_class, interfaces); | 1177 CollectInterfaces(super_class, interfaces); |
1141 super_class = super_class.SuperClass(); | 1178 super_class = super_class.SuperClass(); |
1142 } | 1179 } |
1143 // Resolve function signatures and check for conflicts in super classes and | 1180 // Resolve function signatures and check for conflicts in super classes and |
1144 // interfaces. | 1181 // interfaces. |
1145 array = cls.functions(); | 1182 array = cls.functions(); |
1146 Function& function = Function::Handle(); | 1183 Function& function = Function::Handle(); |
1147 Function& overridden_function = Function::Handle(); | 1184 Function& overridden_function = Function::Handle(); |
1148 const intptr_t num_functions = array.Length(); | 1185 const intptr_t num_functions = array.Length(); |
1149 String& function_name = String::Handle(); | |
1150 Error& error = Error::Handle(); | 1186 Error& error = Error::Handle(); |
1151 for (intptr_t i = 0; i < num_functions; i++) { | 1187 for (intptr_t i = 0; i < num_functions; i++) { |
1152 function ^= array.At(i); | 1188 function ^= array.At(i); |
1153 ResolveAndFinalizeSignature(cls, function); | 1189 ResolveAndFinalizeSignature(cls, function); |
1154 function_name = function.name(); | 1190 name = function.name(); |
| 1191 if (FLAG_error_on_bad_override && // Report signature conflicts only. |
| 1192 !function.is_static() && !function.IsConstructor()) { |
| 1193 // A constructor cannot override anything. |
| 1194 for (int i = 0; i < interfaces.Length(); i++) { |
| 1195 super_class ^= interfaces.At(i); |
| 1196 overridden_function = super_class.LookupDynamicFunction(name); |
| 1197 if (!overridden_function.IsNull() && |
| 1198 !function.HasCompatibleParametersWith(overridden_function, |
| 1199 &error)) { |
| 1200 const String& class_name = String::Handle(cls.Name()); |
| 1201 const String& super_class_name = String::Handle(super_class.Name()); |
| 1202 const Script& script = Script::Handle(cls.script()); |
| 1203 ReportError(error, script, function.token_pos(), |
| 1204 "class '%s' overrides method '%s' of super class '%s' " |
| 1205 "with incompatible parameters", |
| 1206 class_name.ToCString(), |
| 1207 name.ToCString(), |
| 1208 super_class_name.ToCString()); |
| 1209 } |
| 1210 } |
| 1211 } |
| 1212 if (function.IsSetterFunction() || function.IsImplicitSetterFunction()) { |
| 1213 if (function.is_static()) { |
| 1214 super_class = FindSuperOwnerOfFunction(cls, name); |
| 1215 if (!super_class.IsNull()) { |
| 1216 const String& class_name = String::Handle(cls.Name()); |
| 1217 const String& super_class_name = String::Handle(super_class.Name()); |
| 1218 const Script& script = Script::Handle(cls.script()); |
| 1219 ReportError(Error::Handle(), // No previous error. |
| 1220 script, function.token_pos(), |
| 1221 "static setter '%s=' of class '%s' conflicts with " |
| 1222 "instance setter '%s=' of super class '%s'", |
| 1223 name.ToCString(), |
| 1224 class_name.ToCString(), |
| 1225 name.ToCString(), |
| 1226 super_class_name.ToCString()); |
| 1227 } |
| 1228 } |
| 1229 continue; |
| 1230 } |
| 1231 if (function.IsGetterFunction() || function.IsImplicitGetterFunction()) { |
| 1232 getter_name = name.raw(); |
| 1233 name = Field::NameFromGetter(getter_name); |
| 1234 } else { |
| 1235 getter_name = Field::GetterSymbol(name); |
| 1236 } |
1155 if (function.is_static()) { | 1237 if (function.is_static()) { |
1156 super_class = FindSuperOwnerOfInstanceMember(cls, function_name); | 1238 super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name); |
1157 if (!super_class.IsNull()) { | 1239 if (!super_class.IsNull()) { |
1158 const String& class_name = String::Handle(cls.Name()); | 1240 const String& class_name = String::Handle(cls.Name()); |
1159 const String& super_class_name = String::Handle(super_class.Name()); | 1241 const String& super_class_name = String::Handle(super_class.Name()); |
1160 const Script& script = Script::Handle(cls.script()); | 1242 const Script& script = Script::Handle(cls.script()); |
1161 ReportError(Error::Handle(), // No previous error. | 1243 ReportError(Error::Handle(), // No previous error. |
1162 script, function.token_pos(), | 1244 script, function.token_pos(), |
1163 "static function '%s' of class '%s' conflicts with " | 1245 "static %s '%s' of class '%s' conflicts with " |
1164 "instance member '%s' of super class '%s'", | 1246 "instance member '%s' of super class '%s'", |
1165 function_name.ToCString(), | 1247 (function.IsGetterFunction() || |
| 1248 function.IsImplicitGetterFunction()) ? "getter" : "method", |
| 1249 name.ToCString(), |
1166 class_name.ToCString(), | 1250 class_name.ToCString(), |
1167 function_name.ToCString(), | 1251 name.ToCString(), |
1168 super_class_name.ToCString()); | 1252 super_class_name.ToCString()); |
1169 } | 1253 } |
1170 // The function may be a still unresolved redirecting factory. Do not yet | 1254 // 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. | 1255 // try to resolve it in order to avoid cycles in class finalization. |
1172 } else if (FLAG_error_on_bad_override && !function.IsConstructor()) { | 1256 } else if (function.IsGetterFunction() || |
1173 // A constructor cannot override anything. | 1257 function.IsImplicitGetterFunction()) { |
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); | 1258 super_class = FindSuperOwnerOfFunction(cls, name); |
1196 if (!super_class.IsNull()) { | 1259 if (!super_class.IsNull()) { |
1197 const String& class_name = String::Handle(cls.Name()); | 1260 const String& class_name = String::Handle(cls.Name()); |
1198 const String& super_class_name = String::Handle(super_class.Name()); | 1261 const String& super_class_name = String::Handle(super_class.Name()); |
1199 const Script& script = Script::Handle(cls.script()); | 1262 const Script& script = Script::Handle(cls.script()); |
1200 ReportError(Error::Handle(), // No previous error. | 1263 ReportError(Error::Handle(), // No previous error. |
1201 script, function.token_pos(), | 1264 script, function.token_pos(), |
1202 "getter '%s' of class '%s' conflicts with " | 1265 "getter '%s' of class '%s' conflicts with " |
1203 "function '%s' of super class '%s'", | 1266 "method '%s' of super class '%s'", |
1204 name.ToCString(), | 1267 name.ToCString(), |
1205 class_name.ToCString(), | 1268 class_name.ToCString(), |
1206 name.ToCString(), | 1269 name.ToCString(), |
1207 super_class_name.ToCString()); | 1270 super_class_name.ToCString()); |
1208 } | 1271 } |
1209 } else if (!function.IsSetterFunction()) { | 1272 } else if (!function.IsSetterFunction() && |
| 1273 !function.IsImplicitSetterFunction()) { |
1210 // A function cannot conflict with a setter, since they cannot | 1274 // A function cannot conflict with a setter, since they cannot |
1211 // have the same name. Thus, we do not need to check setters. | 1275 // have the same name. Thus, we do not need to check setters. |
1212 name = Field::GetterName(function_name); | 1276 super_class = FindSuperOwnerOfFunction(cls, getter_name); |
1213 super_class = FindSuperOwnerOfFunction(cls, name); | |
1214 if (!super_class.IsNull()) { | 1277 if (!super_class.IsNull()) { |
1215 const String& class_name = String::Handle(cls.Name()); | 1278 const String& class_name = String::Handle(cls.Name()); |
1216 const String& super_class_name = String::Handle(super_class.Name()); | 1279 const String& super_class_name = String::Handle(super_class.Name()); |
1217 const Script& script = Script::Handle(cls.script()); | 1280 const Script& script = Script::Handle(cls.script()); |
1218 ReportError(Error::Handle(), // No previous error. | 1281 ReportError(Error::Handle(), // No previous error. |
1219 script, function.token_pos(), | 1282 script, function.token_pos(), |
1220 "function '%s' of class '%s' conflicts with " | 1283 "method '%s' of class '%s' conflicts with " |
1221 "getter '%s' of super class '%s'", | 1284 "getter '%s' of super class '%s'", |
1222 function_name.ToCString(), | 1285 name.ToCString(), |
1223 class_name.ToCString(), | 1286 class_name.ToCString(), |
1224 function_name.ToCString(), | 1287 name.ToCString(), |
1225 super_class_name.ToCString()); | 1288 super_class_name.ToCString()); |
1226 } | 1289 } |
1227 } | 1290 } |
1228 } | 1291 } |
1229 } | 1292 } |
1230 | 1293 |
1231 | 1294 |
1232 // Copy the type parameters of the super and mixin classes to the | 1295 // Copy the type parameters of the super and mixin classes to the |
1233 // mixin application class. Change type arguments of super type and of | 1296 // mixin application class. Change type arguments of super type and of |
1234 // interfaces to refer to the respective type parameters of the mixin | 1297 // 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"); | 2308 expected_name ^= String::New("_offset"); |
2246 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2309 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
2247 field ^= fields_array.At(2); | 2310 field ^= fields_array.At(2); |
2248 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2311 ASSERT(field.Offset() == TypedDataView::length_offset()); |
2249 name ^= field.name(); | 2312 name ^= field.name(); |
2250 ASSERT(name.Equals("length")); | 2313 ASSERT(name.Equals("length")); |
2251 #endif | 2314 #endif |
2252 } | 2315 } |
2253 | 2316 |
2254 } // namespace dart | 2317 } // namespace dart |
OLD | NEW |