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

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/parser.cc » ('j') | tests/language/field_override3_test.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();
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/parser.cc » ('j') | tests/language/field_override3_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698