Index: runtime/vm/parser.cc |
=================================================================== |
--- runtime/vm/parser.cc (revision 11113) |
+++ runtime/vm/parser.cc (working copy) |
@@ -227,7 +227,8 @@ |
// For parsing a compilation unit. |
Parser::Parser(const Script& script, |
- const Library& library) |
+ const Library& library, |
+ bool generating_snapshot) |
: script_(script), |
tokens_iterator_(TokenStream::Handle(script.tokens()), 0), |
token_kind_(Token::kILLEGAL), |
@@ -240,7 +241,8 @@ |
current_class_(Class::Handle()), |
library_(library), |
try_blocks_list_(NULL), |
- expression_temp_(NULL) { |
+ expression_temp_(NULL), |
+ class_finalizer_(generating_snapshot) { |
ASSERT(tokens_iterator_.IsValid()); |
ASSERT(!library.IsNull()); |
} |
@@ -262,7 +264,8 @@ |
current_class_(Class::Handle(current_function_.Owner())), |
library_(Library::Handle(current_class_.library())), |
try_blocks_list_(NULL), |
- expression_temp_(NULL) { |
+ expression_temp_(NULL), |
+ class_finalizer_(ClassFinalizer::kNotGeneratingSnapshot) { |
ASSERT(tokens_iterator_.IsValid()); |
ASSERT(!function.IsNull()); |
if (FLAG_enable_type_checks) { |
@@ -308,10 +311,11 @@ |
void Parser::ParseCompilationUnit(const Library& library, |
- const Script& script) { |
+ const Script& script, |
+ bool generating_snapshot) { |
ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump()); |
TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer); |
- Parser parser(script, library); |
+ Parser parser(script, library, generating_snapshot); |
parser.ParseTopLevel(); |
} |
@@ -1088,7 +1092,7 @@ |
ASSERT(signature_function.signature_class() == signature_class.raw()); |
Type& signature_type = Type::ZoneHandle(signature_class.SignatureType()); |
if (!is_top_level_ && !signature_type.IsFinalized()) { |
- signature_type ^= ClassFinalizer::FinalizeType( |
+ signature_type ^= class_finalizer_.FinalizeType( |
signature_class, signature_type, ClassFinalizer::kCanonicalize); |
} |
// The type of the parameter is now the signature type. |
@@ -3520,6 +3524,42 @@ |
} |
+// Add 'interface' to 'interface_list' if it is not already in the list and |
+// return true. Also return true if 'interface' is not added, because it is |
+// not unique, i.e. it is already in the list. |
+// Return false if 'interface' conflicts with an interface already in the list |
+// with the same class, but different type arguments. |
+// In the case of a conflict, set 'conflicting' to the existing interface. |
+static bool AddInterfaceIfUnique( |
+ const GrowableObjectArray& interface_list, |
+ const AbstractType& interface, |
+ AbstractType* conflicting) { |
+ String& interface_class_name = String::Handle(interface.ClassName()); |
+ String& existing_interface_class_name = String::Handle(); |
+ String& interface_name = String::Handle(); |
+ String& existing_interface_name = String::Handle(); |
+ AbstractType& other_interface = AbstractType::Handle(); |
+ for (intptr_t i = 0; i < interface_list.Length(); i++) { |
+ other_interface ^= interface_list.At(i); |
+ existing_interface_class_name = other_interface.ClassName(); |
+ if (interface_class_name.Equals(existing_interface_class_name)) { |
+ // Same interface class name, now check names of type arguments. |
+ interface_name = interface.Name(); |
+ existing_interface_name = other_interface.Name(); |
+ // TODO(regis): Revisit depending on the outcome of issue 4905685. |
+ if (!interface_name.Equals(existing_interface_name)) { |
+ *conflicting = other_interface.raw(); |
+ return false; |
+ } else { |
+ return true; |
+ } |
+ } |
+ } |
+ interface_list.Add(interface); |
+ return true; |
+} |
+ |
+ |
void Parser::AddInterfaces(intptr_t interfaces_pos, |
const Class& cls, |
const Array& interfaces) { |
@@ -3550,9 +3590,7 @@ |
String::Handle(interface.UserVisibleName()).ToCString()); |
} |
} |
- if (!ClassFinalizer::AddInterfaceIfUnique(all_interfaces, |
- interface, |
- &conflicting)) { |
+ if (!AddInterfaceIfUnique(all_interfaces, interface, &conflicting)) { |
ASSERT(!conflicting.IsNull()); |
ErrorMsg(interfaces_pos, |
hausner
2012/08/22 00:15:39
I think you could emit the error message in AddInt
regis
2012/08/22 02:24:26
Done, but I needed to make AddInterfaceIfUnique an
|
"interface '%s' conflicts with interface '%s'", |
@@ -4538,11 +4576,10 @@ |
AbstractTypeArguments::Handle(signature_type.arguments()); |
if (!signature_type.IsFinalized()) { |
- signature_type ^= ClassFinalizer::FinalizeType( |
+ signature_type ^= class_finalizer_.FinalizeType( |
signature_class, signature_type, ClassFinalizer::kCanonicalize); |
- // The call to ClassFinalizer::FinalizeType may have |
- // extended the vector of type arguments. |
+ // The call to FinalizeType may have extended the vector of type arguments. |
signature_type_arguments = signature_type.arguments(); |
ASSERT(signature_type.IsMalformed() || |
signature_type_arguments.IsNull() || |
@@ -7281,7 +7318,7 @@ |
parameterized_type.set_type_class(resolved_type_class); |
} else if (finalization >= ClassFinalizer::kCanonicalize) { |
// The type is malformed. |
- ClassFinalizer::FinalizeMalformedType( |
+ class_finalizer_.FinalizeMalformedType( |
Error::Handle(), // No previous error. |
current_class(), parameterized_type, finalization, |
"type '%s' is not loaded", |
@@ -7359,7 +7396,7 @@ |
Type& type = Type::ZoneHandle( |
Type::New(current_class(), type_arguments, type_pos)); |
if (!is_top_level_) { |
- type ^= ClassFinalizer::FinalizeType( |
+ type ^= class_finalizer_.FinalizeType( |
current_class(), type, ClassFinalizer::kCanonicalizeWellFormed); |
} |
return &type; |
@@ -7966,7 +8003,8 @@ |
const Class& scope_class = Class::Handle(TypeParametersScopeClass()); |
ResolveTypeFromClass(scope_class, finalization, &type); |
if (finalization >= ClassFinalizer::kCanonicalize) { |
- type ^= ClassFinalizer::FinalizeType(current_class(), type, finalization); |
+ type ^= class_finalizer_.FinalizeType( |
+ current_class(), type, finalization); |
} |
} |
return type.raw(); |
@@ -8553,7 +8591,7 @@ |
Type& temp_type = Type::Handle(Type::New( |
constructor_class, temp_type_arguments, type.token_pos(), Heap::kNew)); |
// No need to canonicalize temporary type. |
- temp_type ^= ClassFinalizer::FinalizeType( |
+ temp_type ^= class_finalizer_.FinalizeType( |
current_class(), temp_type, ClassFinalizer::kFinalize); |
// The type argument vector may have been expanded with the type arguments |
// of the super type when finalizing the temporary type. |