From 34ea95978d0f2af4adff2de7fd9bd32e4526b0d1 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 27 Nov 2018 21:34:44 +0000 Subject: [PATCH] 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. Reviewed-on: https://go-review.googlesource.com/c/150068 From-SVN: r266530 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 11 +++++++++++ gcc/go/gofrontend/gogo.h | 4 ++++ gcc/go/gofrontend/import.cc | 23 ++++++++++++++++++----- gcc/go/gofrontend/import.h | 5 +++-- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 3f87798749c..9947fcf68a1 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -ce81aad0e3d53215e2c0f1f060c7fd6219e6fb23 +c11d9528a0846293e4d615c86fc773c97252fdce The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index eb0297bc2db..a5a0e5620d3 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -3243,6 +3243,17 @@ Gogo::finalize_methods() 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/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 8ca567ca13c..854d37a6333 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -637,6 +637,10 @@ class Gogo 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/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index 524e739f21c..eefee7cb1e6 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -886,7 +886,9 @@ Import::read_type() 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 @@ Import::read_named_type(int index) 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(index) >= this->type_offsets_.size()) @@ -1114,6 +1117,7 @@ Import::type_for_index(int index, const std::string& input_name, { if (!this->parse_type(index)) return Type::make_error_type(); + *parsed = true; } } @@ -1497,6 +1501,15 @@ Import_function_body::read_type() return Type::make_error_type(); } - return this->imp_->type_for_index(static_cast(val), this->name(), - static_cast(start)); + bool parsed; + Type* type = this->imp_->type_for_index(static_cast(val), this->name(), + static_cast(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/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h index 948cdf7552f..e2f4e50378c 100644 --- a/gcc/go/gofrontend/import.h +++ b/gcc/go/gofrontend/import.h @@ -284,10 +284,11 @@ class Import : public Import_expression 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 -- 2.30.2