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

Unified Diff: runtime/vm/class_finalizer.cc

Issue 10377095: Implement latest rules prohibiting some self referencing typedefs. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/class_finalizer.cc
===================================================================
--- runtime/vm/class_finalizer.cc (revision 7523)
+++ runtime/vm/class_finalizer.cc (working copy)
@@ -563,9 +563,8 @@
FinalizationKind finalization) {
ASSERT(arguments.Length() >= cls.NumTypeArguments());
if (!cls.is_finalized()) {
- const GrowableObjectArray& visited =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- ResolveInterfaces(cls, visited);
+ GrowableArray<intptr_t> visited_interfaces;
+ ResolveInterfaces(cls, &visited_interfaces);
FinalizeTypeParameters(cls);
}
Type& super_type = Type::Handle(cls.super_type());
@@ -669,9 +668,8 @@
// parameters of the type class must be finalized.
Class& type_class = Class::Handle(parameterized_type.type_class());
if (!type_class.is_finalized()) {
- const GrowableObjectArray& visited =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- ResolveInterfaces(type_class, visited);
+ GrowableArray<intptr_t> visited_interfaces;
+ ResolveInterfaces(type_class, &visited_interfaces);
FinalizeTypeParameters(type_class);
}
@@ -752,10 +750,8 @@
}
}
- // Illegally self referencing types may get finalized indirectly.
- if (parameterized_type.IsFinalized()) {
- ASSERT(parameterized_type.IsMalformed());
- } else {
+ // Self referencing types may get finalized indirectly.
+ if (!parameterized_type.IsFinalized()) {
// Mark the type as finalized.
if (parameterized_type.IsInstantiated()) {
parameterized_type.set_is_finalized_instantiated();
@@ -791,18 +787,30 @@
}
}
- // If the type class is a signature class, we also finalize its signature
- // type, thereby finalizing the result type and parameter types of its
- // signature function.
+ // If the type class is a signature class, we are currently finalizing a
+ // signature type, i.e. finalizing the result type and parameter types of the
+ // signature function of this signature type.
// We do this after marking this type as finalized in order to allow a
// function type to refer to itself via its parameter types and result type.
if (type_class.IsSignatureClass()) {
- // Signature classes are finalized upon creation.
- ASSERT(type_class.is_finalized());
- // Resolve and finalize the result and parameter types of the signature
- // function of this signature class.
- ResolveAndFinalizeSignature(
- type_class, Function::Handle(type_class.signature_function()));
+ // Signature classes are finalized upon creation, except function type
+ // aliases.
+ if (type_class.IsCanonicalSignatureClass()) {
+ ASSERT(type_class.is_finalized());
+ // Resolve and finalize the result and parameter types of the signature
+ // function of this signature class.
+ ASSERT(type_class.SignatureType() == type.raw());
+ ResolveAndFinalizeSignature(
+ type_class, Function::Handle(type_class.signature_function()));
+ } else {
+ // This type is a function type alias. Its class may need to be finalized
+ // and checked for illegal self reference.
+ FinalizeClass(type_class, false);
+ // Finalizing the signature function here (as in the canonical case above)
+ // would not mark the canonical signature type as finalized.
+ const Type& signature_type = Type::Handle(type_class.SignatureType());
+ FinalizeType(cls, signature_type, finalization);
+ }
}
return parameterized_type.Canonicalize();
@@ -1059,8 +1067,6 @@
if (FLAG_trace_class_finalization) {
OS::Print("Finalize %s\n", cls.ToCString());
}
- // Signature classes are finalized upon creation.
- ASSERT(!cls.IsSignatureClass());
if (!IsSuperCycleFree(cls)) {
const String& name = String::Handle(cls.Name());
const Script& script = Script::Handle(cls.script());
@@ -1068,9 +1074,8 @@
"class '%s' has a cycle in its superclass relationship",
name.ToCString());
}
- const GrowableObjectArray& visited =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- ResolveInterfaces(cls, visited);
+ GrowableArray<intptr_t> visited_interfaces;
+ ResolveInterfaces(cls, &visited_interfaces);
// Finalize super class.
const Class& super_class = Class::Handle(cls.SuperClass());
if (!super_class.IsNull()) {
@@ -1084,6 +1089,24 @@
super_type ^= FinalizeType(cls, super_type, kFinalizeWellFormed);
cls.set_super_type(super_type);
}
+ // Signature classes are finalized upon creation, except function type
+ // aliases.
+ if (cls.IsSignatureClass()) {
+ ASSERT(!cls.IsCanonicalSignatureClass());
+ // Check for illegal self references.
+ GrowableArray<intptr_t> visited_aliases;
+ if (!IsAliasCycleFree(cls, &visited_aliases)) {
+ const String& name = String::Handle(cls.Name());
+ const Script& script = Script::Handle(cls.script());
+ ReportError(script, cls.token_index(),
+ "typedef '%s' illegally refers to itself",
+ name.ToCString());
+ }
+ // TODO(regis): Also check this: "It is a compile-time error if any default
+ // values are specified in the signature of a function type alias".
+ cls.Finalize();
+ return;
+ }
// Finalize factory class, if any.
if (cls.is_interface()) {
if (cls.HasFactoryClass()) {
@@ -1153,6 +1176,58 @@
}
+// Returns false if the function type alias illegally refers to itself.
+bool ClassFinalizer::IsAliasCycleFree(const Class& cls,
+ GrowableArray<intptr_t>* visited) {
+ ASSERT(cls.IsSignatureClass());
+ ASSERT(!cls.IsCanonicalSignatureClass());
+ ASSERT(!cls.is_finalized());
+ ASSERT(visited != NULL);
+ const intptr_t cls_index = cls.index();
+ for (int i = 0; i < visited->length(); i++) {
+ if ((*visited)[i] == cls_index) {
+ // We have already visited alias 'cls'. We found a cycle.
+ return false;
+ }
+ }
+
+ // Visit the result type and parameter types of this signature type.
+ visited->Add(cls.index());
+ const Function& function = Function::Handle(cls.signature_function());
+ // Check class of result type.
+ AbstractType& type = AbstractType::Handle(function.result_type());
+ ResolveType(cls, type, kFinalize);
+ if (type.IsType() && !type.IsMalformed()) {
+ const Class& type_class = Class::Handle(type.type_class());
+ if (!type_class.is_finalized() &&
+ type_class.IsSignatureClass() &&
+ !type_class.IsCanonicalSignatureClass()) {
+ if (!IsAliasCycleFree(type_class, visited)) {
+ return false;
+ }
+ }
+ }
+ // Check classes of formal parameter types.
+ const intptr_t num_parameters = function.NumberOfParameters();
+ for (intptr_t i = 0; i < num_parameters; i++) {
+ type = function.ParameterTypeAt(i);
+ ResolveType(cls, type, kFinalize);
+ if (type.IsType() && !type.IsMalformed()) {
+ const Class& type_class = Class::Handle(type.type_class());
+ if (!type_class.is_finalized() &&
+ type_class.IsSignatureClass() &&
+ !type_class.IsCanonicalSignatureClass()) {
+ if (!IsAliasCycleFree(type_class, visited)) {
+ return false;
+ }
+ }
+ }
+ }
+ visited->RemoveLast();
+ return true;
+}
+
+
bool ClassFinalizer::AddInterfaceIfUnique(
const GrowableObjectArray& interface_list,
const AbstractType& interface,
@@ -1191,12 +1266,11 @@
// graph. If we visit an interface a second time on a given path,
// we found a loop.
void ClassFinalizer::ResolveInterfaces(const Class& cls,
- const GrowableObjectArray& visited) {
- ASSERT(!visited.IsNull());
- Class& visited_cls = Class::Handle();
- for (int i = 0; i < visited.Length(); i++) {
- visited_cls ^= visited.At(i);
- if (visited_cls.raw() == cls.raw()) {
+ GrowableArray<intptr_t>* visited) {
+ ASSERT(visited != NULL);
+ const intptr_t cls_index = cls.index();
+ for (int i = 0; i < visited->length(); i++) {
+ if ((*visited)[i] == cls_index) {
// We have already visited interface class 'cls'. We found a cycle.
const String& interface_name = String::Handle(cls.Name());
const Script& script = Script::Handle(cls.script());
@@ -1219,7 +1293,7 @@
(cls.library() == Library::CoreImplLibrary());
// Resolve and check the interfaces of cls.
- visited.Add(cls);
+ visited->Add(cls_index);
AbstractType& interface = AbstractType::Handle();
Class& interface_class = Class::Handle();
for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
@@ -1260,7 +1334,7 @@
// Now resolve the super interfaces.
ResolveInterfaces(interface_class, visited);
}
- visited.RemoveLast();
+ visited->RemoveLast();
}
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698