compiler: finalize types parsed for inline functions
When we inline functions, we may parse types that we have not seen
before inlining. Inlining runs after the finalize_methods pass, so
those types will not be finalized, meaning that we don't have an
accurate list of which methods they support. Explicitly finalize them
when we parse them.
Change-Id: I93632910ca87f1168523786f5ead6ec721e0e4f3
Reviewed-on: https://go-review.googlesource.com/c/150068
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/gogo.cc b/go/gogo.cc
index eb0297b..a5a0e56 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -3243,6 +3243,17 @@
this->traverse(&finalize);
}
+// Finalize the method list for a type. This is called when a type is
+// parsed for an inlined function body, which happens after the
+// finalize_methods pass.
+
+void
+Gogo::finalize_methods_for_type(Type* type)
+{
+ Finalize_methods finalize(this);
+ Type::traverse(type, &finalize);
+}
+
// Set types for unspecified variables and constants.
void
diff --git a/go/gogo.h b/go/gogo.h
index 8ca567c..854d37a 100644
--- a/go/gogo.h
+++ b/go/gogo.h
@@ -637,6 +637,10 @@
void
finalize_methods();
+ // Finalize the method list for one type.
+ void
+ finalize_methods_for_type(Type*);
+
// Work out the types to use for unspecified variables and
// constants.
void
diff --git a/go/import.cc b/go/import.cc
index 524e739..eefee7c 100644
--- a/go/import.cc
+++ b/go/import.cc
@@ -886,7 +886,9 @@
if (c == '>')
{
// A reference to a type defined earlier.
- return this->type_for_index(index, "import data", stream->pos());
+ bool parsed;
+ return this->type_for_index(index, "import data", stream->pos(),
+ &parsed);
}
if (this->version_ >= EXPORT_FORMAT_V3)
@@ -1092,12 +1094,13 @@
return type;
}
-// Return the type given an index.
+// Return the type given an index. Set *PARSED if we parsed it here.
Type*
Import::type_for_index(int index, const std::string& input_name,
- size_t input_offset)
+ size_t input_offset, bool* parsed)
{
+ *parsed = false;
if (index >= 0 && !this->type_data_.empty())
{
if (static_cast<size_t>(index) >= this->type_offsets_.size())
@@ -1114,6 +1117,7 @@
{
if (!this->parse_type(index))
return Type::make_error_type();
+ *parsed = true;
}
}
@@ -1497,6 +1501,15 @@
return Type::make_error_type();
}
- return this->imp_->type_for_index(static_cast<int>(val), this->name(),
- static_cast<unsigned long>(start));
+ bool parsed;
+ Type* type = this->imp_->type_for_index(static_cast<int>(val), this->name(),
+ static_cast<unsigned long>(start),
+ &parsed);
+
+ // If we just read this type's information, its methods will not
+ // have been finalized. Do that now.
+ if (parsed)
+ this->gogo_->finalize_methods_for_type(type);
+
+ return type;
}
diff --git a/go/import.h b/go/import.h
index 948cdf7..e2f4e50 100644
--- a/go/import.h
+++ b/go/import.h
@@ -284,10 +284,11 @@
read_type();
// Return the type for a type index. INPUT_NAME and INPUT_OFFSET
- // are only for error reporting.
+ // are only for error reporting. PARSED is set to whether we parsed
+ // the type information for a new type.
Type*
type_for_index(int index, const std::string& input_name,
- size_t input_offset);
+ size_t input_offset, bool* parsed);
// Read an escape note.
std::string