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

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

Issue 22999022: Report compile-time errors for conflicting overrides as specified by latest (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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 | « no previous file | runtime/vm/object.h » ('j') | tools/testing/dart/multitest.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/object.h » ('j') | tools/testing/dart/multitest.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698