===================================================================
@@ -1,4 +1,4 @@
-170ecdf6b2eab8aac2b8c852fa95d3c36d6bf604
+ec754ff4617d564d3dc377121ea9ac5e55f6535a
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
===================================================================
@@ -3422,24 +3422,6 @@ Gogo::create_function_descriptors()
this->traverse(&cfd);
}
-// Look for interface types to finalize methods of inherited
-// interfaces.
-
-class Finalize_methods : public Traverse
-{
- public:
- Finalize_methods(Gogo* gogo)
- : Traverse(traverse_types),
- gogo_(gogo)
- { }
-
- int
- type(Type*);
-
- private:
- Gogo* gogo_;
-};
-
// Finalize the methods of an interface type.
int
===================================================================
@@ -3556,6 +3556,24 @@ class Traverse
Expressions_seen* expressions_seen_;
};
+// This class looks for interface types to finalize methods of inherited
+// interfaces.
+
+class Finalize_methods : public Traverse
+{
+ public:
+ Finalize_methods(Gogo* gogo)
+ : Traverse(traverse_types),
+ gogo_(gogo)
+ { }
+
+ int
+ type(Type*);
+
+ private:
+ Gogo* gogo_;
+};
+
// A class which makes it easier to insert new statements before the
// current statement during a traversal.
===================================================================
@@ -290,10 +290,16 @@ Import::Import(Stream* stream, Location
: gogo_(NULL), stream_(stream), location_(location), package_(NULL),
add_to_globals_(false), packages_(), type_data_(), type_pos_(0),
type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
- types_(), version_(EXPORT_FORMAT_UNKNOWN)
+ types_(), finalizer_(NULL), version_(EXPORT_FORMAT_UNKNOWN)
{
}
+Import::~Import()
+{
+ if (this->finalizer_ != NULL)
+ delete this->finalizer_;
+}
+
// Import the data in the associated stream.
Package*
@@ -672,9 +678,40 @@ Import::read_types()
this->gogo_->add_named_type(nt);
}
+ // Finalize methods for any imported types. This is done after most of
+ // read_types() is complete so as to avoid method finalization of a type
+ // whose methods refer to types that are only partially read in.
+ // See issue #33013 for more on why this is needed.
+ this->finalize_methods();
+
return true;
}
+void
+Import::finalize_methods()
+{
+ if (this->finalizer_ == NULL)
+ this->finalizer_ = new Finalize_methods(gogo_);
+ Unordered_set(Type*) real_for_named;
+ for (size_t i = 1; i < this->types_.size(); i++)
+ {
+ Type* type = this->types_[i];
+ if (type != NULL && type->named_type() != NULL)
+ {
+ this->finalizer_->type(type);
+ real_for_named.insert(type->named_type()->real_type());
+ }
+ }
+ for (size_t i = 1; i < this->types_.size(); i++)
+ {
+ Type* type = this->types_[i];
+ if (type != NULL
+ && type->named_type() == NULL
+ && real_for_named.find(type) == real_for_named.end())
+ this->finalizer_->type(type);
+ }
+}
+
// Import a constant.
void
===================================================================
@@ -20,6 +20,7 @@ class Expression;
class Import_function_body;
class Temporary_statement;
class Unnamed_label;
+class Finalize_methods;
// Expressions can be imported either directly from import data (for
// simple constant expressions that can appear in a const declaration
@@ -207,8 +208,7 @@ class Import : public Import_expression
// Constructor.
Import(Stream*, Location);
- virtual ~Import()
- {}
+ virtual ~Import();
// Register the builtin types.
void
@@ -423,6 +423,10 @@ class Import : public Import_expression
return true;
}
+ // Finalize methods for newly imported types.
+ void
+ finalize_methods();
+
// The general IR.
Gogo* gogo_;
// The stream from which to read import data.
@@ -446,6 +450,8 @@ class Import : public Import_expression
std::vector<Named_type*> builtin_types_;
// Mapping from exported type codes to Type structures.
std::vector<Type*> types_;
+ // Helper for finalizing methods.
+ Finalize_methods* finalizer_;
// Version of export data we're reading.
Export_data_version version_;
};